Access Listbox query preventing SQL Server Update Query - sql-server

I'm developing an Access application and a SQL Server backend simultaneously. I have a Form with a listbox which, when a record is double clicked, opens an unbound form and loads data into it based on the record selected. When changes are made in this second form, a button initiates a pass through query that executes a stored procedure updating the details of the record in the base table in SQL Server.
Here's the thing. As long as Form1 (with the listbox) is open, the stored procedure times out without running. If I close that form, it takes less than a second. It behaves this way when run from Access, when run from management studio, and when run in management studio as a query with hard values (not a sproc with parameters).
The row source for the listbox is a linked table that references a View in SQL Server. The query within the view is a recursive common table expression of two different tables, one of which is the table being edited by the sproc. I've set the view to read only. Is there another setting that I can do to help here?
Here's the stored procedure:
PROCEDURE [dbo].[spSalesPlanUpdate]
#Salesyear numeric(4,0),
#ItemNumber varchar(20),
#Baseline int,
#Speculation int,
#Comments varchar(max)
AS
declare #SY numeric(4,0),
#ItN varchar (20),
#BL int,
#SPL int,
#CmT varchar(max)
set #SY = #Salesyear
set #ItN = #ItemNumber
set #BL = #Baseline
set #SPL = #Speculation
set #CmT = #Comments
BEGIN
SET NOCOUNT ON;
update SalesPlan
set Baseline = #BL
,Speculation = #SPL
,DateModified = getdate()
,Comments = #CmT
where SalesYear = #SY and ItemNumber = #ItN
END
I used both parameters and local variables because at first I was thinking it might be about parameter sniffing.
Here's the view the listbox is queried from:
view [dbo].[vwSalesPlan] as
with cte
as
(
select Item, year(getdate()) as SY
from vwItemsAndLiners il
union all
select ial.Item,
(cte.SY + 1)
From vwItemsAndLiners ial join cte on ial.Item = cte.Item
Where SY < (year(getdate())+ial.YearsFromProp)
)
select sp.ItemNumber, ial.Variety, ial.Size, ial.PerTray, sp.SalesYear, sp.SalesYear - ial.YearsFromProp as PropYear,
sp.SalesYear - ial.YearsFromProduction as ProductionYear,
sp.Baseline, sp.Speculation,
CEILING((CAST(SP.BASELINE AS NUMERIC (12,2)) + CAST(SP.SPECULATION AS numeric(12,2)))/IAL.PerTray)*IAL.PerTray as Total ,
sp.DateModified, ial.Segment ,'Entered' as [Status], sp.Comments
From SalesPlan sp inner join vwItemsAndLiners ial on sp.ItemNumber = ial.Item
Where ial.status = 'Sell'
union
select cte.Item, ial.Variety, ial.Size, ial.PerTray, SY, cte.sy - ial.YearsFromProp as PropYear,
cte.SY - ial.YearsFromProduction as ProductionYear,'', '', 0, null, ial.Segment , 'Not Entered', null
from cte inner join vwItemsAndLiners ial on cte.Item = ial.Item
where cte.Item not in (select ItemNumber from SalesPlan where salesplan.SalesYear = CTE.SY) and ial.Status = 'Sell'
with check option
Table being updated: SalesPlan
View that the listbox is queried from: vwSalesPlan
I realize that there's a lot of stuff here. Really, I'm just hoping this generates some ideas of why a form being open would lock the original table from an update query. Thanks!

I tried:
Indexing the views in SQL Server that provide the rowsource for the listbox, but because they contain CTE's they cannot be indexed.
lstbox.recordset.movefirst then lstbox.recordset.movelast to force access to read the entire list, but whenever the list was filtered or requeried it would throw an error saying the recordset object had changed and the movefirst command was invalid.
So I wrote this sub:
Private Sub readtheData()
Dim i As Integer
i = Me.lstSalesPlan.ListCount
End Sub
Simply forcing it to count the records every time the form was loaded or the query behind the listbox was filtered forced access to release the lock. Hope this helps somebody down the road!

Related

prevent duplicate value to submit using stored procedure in sql server

I want to prevent the same #coupon_value in sp to submit and return
any message for validation using csharp but I am not able to how to
make changes in stored procedure.
CREATE PROCEDURE [dbo].[USP_REBATE_CAMPAIGN_RULE_DETAIL_VALIDATE]
#rebate_campaign_seq INT,
#coupon_value Varchar(50)='',
#Type varchar(50)='SERIES'
AS
SET NOCOUNT ON
BEGIN
SELECT rcrd.rebate_campaign_rule_detail_seq AS id,Type_value AS NAME,
'SERIES' AS type,
rcrd.amount_per_range AS Amount
FROM rebate_campaign_rule_detail rcrd (nolock)
INNER JOIN rebate_campaign_rule rcr
ON rcr.rebate_campaign_rule_seq = rcrd.rebate_campaign_rule_seq
INNER JOIN rebate_campaign rc
ON rc.rebate_campaign_seq = rcr.rebate_campaign_seq
WHERE rc.rebate_campaign_seq = #rebate_campaign_seq
AND rcrd.active_flag = 'Y' AND rcrd.type = #Type
AND rcrd.type_value=#coupon_value
End
The only way to prevent duplicate in database data is to add a UNIQUE CONSTRAINT. Everything else will fail, especially any solution coded with a procedural program, because of concurrency (imagine for a moment that two users launch the same procedure with the same values at the same time...).
To have a NULLbale UNIQUE constraint, you can add a UNIQUE filtered INDEX like this one :
CREATE INDEX X_UNIQUE_COUPON_RCRD
ON rebate_campaign_rule_detail (type_value)
WHERE type_value IS NOT NULL;

How to determine who performed DROP/DELETE on Sql Server database objects?

There is always a need to find out details, either intentionally Or mistakenly someone executed DROP/DELETE command on any of following SQL Server database objects.
DROPPED - Table from your database
DROPPED - Stored Procedure from your database
DELETED - Rows from your database table
Q. Is there TSQL available to find db user who performed DELETE/DROP?
Q. What kind of permissions are needed for user to find out these details?
Did you check this ?
Right click on database.
Go to as shown in image :
Solution 2 :
This query gives alot of useful information for a database(apply filter as required) :
DECLARE #filename VARCHAR(255)
SELECT #FileName = SUBSTRING(path, 0, LEN(path)-CHARINDEX('\', REVERSE(path))+1) + '\Log.trc'
FROM sys.traces
WHERE is_default = 1;
SELECT gt.HostName,
gt.ApplicationName,
gt.NTUserName,
gt.NTDomainName,
gt.LoginName,
--gt.SPID,
-- gt.EventClass,
te.Name AS EventName,
--gt.EventSubClass,
-- gt.TEXTData,
gt.StartTime,
gt.EndTime,
gt.ObjectName,
gt.DatabaseName,
gt.FileName,
gt.IsSystem
FROM [fn_trace_gettable](#filename, DEFAULT) gt
JOIN sys.trace_events te ON gt.EventClass = te.trace_event_id
WHERE EventClass in (164) --AND gt.EventSubClass = 2
ORDER BY StartTime DESC;

list records from sql server UDF that returns Table in classic asp

I wrote my first sql Server returning table UDF since thought was better than using a SP
but, while can easily retrieve the result from sql server.. I can't get result calling it from classic ASP ADO
UDF is as follows:
CREATE FUNCTION dbo.udf_Alert
(
#I nvarchar (30),
#L nvarchar (10)
)
RETURNS TABLE AS RETURN
(
SELECT a.Message, a.Height, a.backgroundColor, a.isFree
from Advice a
join ActiveMessages b on b.MessageID=a.MessageID
join Items i on b.ItemID=i.ItemID
join Sellers s on i.UserID=s.UserID
join Users u on u.UID=s.UID
WHERE
(i.ItemID=#I and a.Active='1' and b.Active='1' and i.active='1' and i.Show='1' and CHARINDEX('ALERT',u.Modules)>0
and a.ValidFrom<GETDATE() and a.ValidTo>GETDATE() and u.PaidUntil>GETDATE() and charindex(#L,a.Languages)>-1 or charindex('all',a.Languages)>-1 )
UNION ALL
SELECT a.Message, a.Height, a.backgroundColor, a.isFree
FROM Advice a, Users u
WHERE u.isFree='1' and a.isFree='1' and (CHARINDEX(#L,a.Languages)>-1 or Charindex('all',a.Languages)>-1)
)
and I can easily execute from SSMS calling
Select * from dbo.udf_Alert('281F50246','fr')
But I have to embed into a classic ASP routine but I've not found the way to do it..
tried the SP method.. but I got error when try to set the parameters:
here what I tried:
sql="Select dbo.udf_Alert('xx','yy')"
dim cmdA
set cmdA = Server.CreateObject("ADODB.Command")
cmdA.ActiveConnection= cn
cmdA.CommandType=4
cmdA.CommandText=sql
cmda.Parameters.Append cmdA.CreateParameter("fd", nvarchar, adParamInput,30, itemID)
cmda.Parameters.Append cmdA.CreateParameter("fde", nvarchar, adParamInput,10, LanguageID)
' cmdA.Parameters("#I")=ItemID '<-----ERRROR HERE
' cmdA.Parameters("#L")=LanguageID
set rs=cmdA.Execute()
so I tried set Parametrs in other way.. but got same result:
ADODB.Command error '800a0bb9'
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
Can suggest some advice?
Thanks
Sergio
We tend to create stored procedure "wrappers" for UDFs on a one-to-one basis which can be called directly from web code. For your example, this might look like
CREATE PROCEDURE [dbo].[pr_Alert]
#I nvarchar (30),
#L nvarchar (10)
AS
SELECT * FROM testDb.dbo.udf_Alert(#I, #L)
RETURN
Your commandText would then be simply the name of the wrapper SP, "pr_Alert".
Hope this helps.

Retrieving data from a MS SQL 2012 table based on FK value from another table using stored procedure

I am working on MS SQL Server 2012. I have two tables - Associates and Clients and they have M:N relation so I have another table MapClientToAssociates where I have two foreign keys - ClientID and AssociateID. What I want to achieve is by providing a ClientID to take all the AssociateID's for this Client and then take all the information about each Associate (As I wrote, the relation is M:N so there can be several Associates for a certain client) and I want to return this data.
So basically I want to return rows containing :
`ID` - from `MapClientToAssociates`
`ClientID` - from `MapClientToAssociates`
`AssociateID` - from `MapClientToAssociates`
[column1] - from `Associates` (based on the `AssociateID` value)
[column2] - from `Associates` (based on the `AssociateID` value)
.
.
.
[columnN] - from `Associates` (based on the `AssociateID` value)
I tried to follow an existing code that is doing something pretty similar to that :
CREATE PROCEDURE [dbo].[usp_ClientGetAssociates]
#ClientID int
AS
BEGIN
If Exists (Select * From dbo.MapClientToAssociates map Where map.ClientID = #ClientID)
Begin
Declare #AssociateID int = (Select * map.AssociateID From dbo.MapClientToAssociates map Where map.ClientID = #ClientID)
And I get an error that I don't understand at the very beginning - Declare #AssociateID int = (Select * map.AssociateID - here map.AssociateID map is underscored in red saying Incorrect syntax near map) but I have to admit I don't have any experience with T-SQL or writing stored procedures and this seems like a standard stuff for a sproc to do so I would appreciate any help to make this sproc working and hopefully later I'll have the time to examine how exactly the code is working, but for now the most important thing for me is to make the sproc returns the result I want.
This clause (Select * map.AssociateID From dbo.MapClientToAssociates map Where map.ClientID = #ClientID) is returning a derived table of integer values. You are trying to assign it to a scalar (single) integer value, which does not make sense.
As for the actual syntax error, this :
Select * map.AssociateID From dbo.MapClientToAssociates map Where map.ClientID = #ClientID
is invalid because you would need to either remove the * or put a comma between it and the map.AssociateID.
This is how I would write this myself:
CREATE PROCEDURE [dbo].[usp_ClientGetAssociates]
#ClientID int
AS
BEGIN
Select act.*
From dbo.MapClientToAssociates map
Left Join dbo.Associates as act ON act.AssociateID = map.AssociateID
Where map.ClientID = #ClientID)
End
Unless I needed to consume the returned rowset in another SQL procedure or expression, then I would write it as a table-valued function instead.
CREATE PROCEDURE [dbo].[usp_ClientGetAssociates]
#ClientID int
AS
BEGIN
Select map.*, ass.*
from dbo.MapClientToAssociates map, dbo.Associates ass
where ass.AssociateID = map.AssociateID
and map.ClientID = #ClientID
If this response is wrong, can you provide a script for create and populate table and the full code of stored procedure?

Seeing String or binary data would be truncated when executing Stored Procedure MS SQL 2008

I have a stored procedure in MS SQL 2008, which compiles without error, but when go to execute the stored procedure I receive the error message 'String or binary data would be truncated'. Unfortunately, I am unable to trace where this is happening.
When I developed my Stored Procedure, I tested the query first, and it worked.
So, if anyone can show where and why this happening to me and how to solve it, I would be grateful:
ALTER PROCEDURE [dbo].[sp_Material_Validation]
#ValidType varchar(MAX),
#MaterialID varchar(MAX)
AS
BEGIN
DECLARE
#MessageReturn varchar(100);
SET #MessageReturn = NULL;
IF #ValidType = 'Primary'
Select TOP 1 Valid.StatusMessage
From
(Select MatID,'Property Not Completed' as StatusMessage
From dbo.Properties
WHERE DATALENGTH(ValueString)=0
UNION
Select PrpCount.MatID,'There not all Properties exist' as StatusMessage
From (Select Count(unkey) as unKeyCt, MatID
From Properties
Group By MatID
Having NOT Count(Cast(UnKey as Int)) = 19)AS PrpCount
UNION
SELECT Header,'Material does not exist' as StatusMessage
FROM Materials Item
Where NOT EXISTS (Select ID
FROM MatMaster Mat
WHERE MAT.ID= Item.HEAD)
UNION
SELECT Header,'Material(s) not Complete' as StatusMessage
FROM Materials
Where MatID IN (Select ID
FROM MatMaster
WHERE INC ='Y')) as Valid
Where Valid.MatID = #MaterialID;
IF #MessageReturn IS NOT NULL
UPDATE dbo.Mat_DEV
SET Inco ='Y',
User_Message = #MessageReturn
WHERE MatID = #MaterialID
ELSE
UPDATE dbo.Mat_DEV
SET User_Message = 'No Validation Errors'
WHERE MatID = #MaterialID
String or binary data would be truncated only appears when you try and put a value in a box that isn't big enough to hold the value.
Now, you're only actually writing values in two places, so the candidates for your problem are:-
UPDATE dbo.Mat_DEV
SET Inco ='Y',
User_Message = #MessageReturn
WHERE MatID = #MaterialID
..or..
UPDATE dbo.Mat_DEV
SET User_Message = 'No Validation Errors'
WHERE MatID = #MaterialID
Check the column definitions for both these columns ( Inco and User_Message ). My guess is that one is too small to hold the value you want to set.
My guess is that column User_Message does not have enough length
I had the same problem.
When I executed the stored proc directly, everything worked as it should.
When I called the same proc from ASP.NET, I got 'String or binary data would be truncated'...
Finally I realized the culprit was a varchar(20) field with the default value 'suser_sname()'... in SQL Management Studio the user name was short, from ASP.NET it was more than 20 chars... A simple CAST solved the problem. :)

Resources