SQL Server - Select max - sql

I have a SQL Server stored procedure with an update statement:
UPDATE Sale_Sheet
SET concluded = 'True'
, concluded_time = GETDATE()
, saleNumber = (SELECT MAX(saleNumber) + 1 FROM Sale_Sheet)
WHERE vatNumber = #vatNumber
AND [user_id] = #user_id
It happens that two users initiate a procedure at the same time, and both users receive the same maximum value (SELECT MAX(saleNumber) + 1 FROM Sale_Sheet). How can I fix this?

Related

Invalid column name 'filter' error in SQL Server

I am getting an weird kind of error. I say weird because I don't understand why am I getting that error. I suppose there is syntax error but i don't exactly get what the error since it looks correct.
Error that I am getting is in a SQL Server Procedure that I have created. In the below procedure I am getting an error specifically in below part.
INSERT INTO agentids (filter, agentid)
SELECT
filter
,agentid
FROM selected_agents sa
WHERE sa.agentname = #p_agentname
AND sa.agentloginid = #p_agentloginid;
If I remove the above Insert Statement, I am able to compile the procedure. I understand that filter is in-build SQL Server variable but I have used it at other places in the procedure and it executes properly if I remove the Insert Statement part
Update Note: I missed mentioning this earlier, but if I execute this
procedure as it is "master" database it gets compiled successfully.
CREATE PROCEDURE [dbo].[getAgentLogActivity] #p_agentname NVARCHAR(50),
#p_agentloginid NVARCHAR(50),
#p_startTime DATETIME,
#p_endTime DATETIME
AS
BEGIN
DECLARE #l_event_login SMALLINT
DECLARE #l_event_logout SMALLINT
DECLARE #l_eventtype SMALLINT
DECLARE #l_reasoncode SMALLINT
DECLARE #l_agentid INT
DECLARE #l_eventdatetime DATETIME
DECLARE #l_filter BIT
DECLARE #l_mineventdatetime DATETIME
DECLARE #l_maxeventdatetime DATETIME
DECLARE #SWV_cursor_var1 CURSOR
SET #l_event_login = 1
SET #l_event_logout = 7
DELETE FROM agentids
INSERT INTO agentids (filter, agentid)
SELECT
filter
,agentid
FROM selected_agents sa
WHERE sa.agentname = #p_agentname
AND sa.agentloginid = #p_agentloginid;
DELETE FROM temp_asdr1
INSERT INTO temp_asdr1(agentid, eventtype, eventdatetime, reasoncode)
SELECT
asdr.agentid
,asdr.eventtype
,asdr.eventdatetime
,asdr.reasoncode
FROM
agentstatedetail asdr
,agentids ai
WHERE asdr.agentid = ai.agentid
AND asdr.eventdatetime BETWEEN #p_startTime AND #p_endTime
AND asdr.eventtype IN(#l_event_login,#l_event_logout)
UPDATE temp_asdr1
SET filter = (SELECT
filter
FROM agentids ai
WHERE ai.agentid = temp_asdr1.agentid)
DELETE FROM temp_asdr
--alter sequence temp_asdr_seq
SELECT
#l_mineventdatetime = min(eventdatetime)
,#l_maxeventdatetime = max(eventdatetime)
FROM temp_asdr1
WHERE filter = 1
EXECUTE dbo.sp_executesql 'l_mineventdatetime'
,#l_mineventdatetime
EXECUTE dbo.sp_executesql 'l_maxeventdatetime'
,#l_maxeventdatetime
IF ##rowcount = 0
BEGIN
SELECT
#l_mineventdatetime = NULL
,#l_maxeventdatetime = NULL
EXECUTE dbo.sp_executesql 'l_mineventdatetime'
,#l_mineventdatetime
EXECUTE dbo.sp_executesql 'l_maxeventdatetime'
,#l_maxeventdatetime
END
DELETE FROM temp_asdr1
WHERE ((eventdatetime <= l_mineventdatetime)
OR (eventdatetime >= #l_maxeventdatetime))
AND filter = 0
SET #SWV_cursor_var1 = CURSOR FOR
SELECT
agentid,
eventtype,
eventdatetime,
reasoncode,
filter
FROM temp_asdr1
ORDER BY eventdatetime
OPEN #SWV_cursor_var1
FETCH NEXT FROM #SWV_cursor_var1 INTO #l_agentid, #l_eventtype, #l_eventdatetime, #l_reasoncode, #l_filter
WHILE ##FETCH_STATUS = 0
BEGIN
-- WARNING: The INSERT statement was commented, because column name or number of supplied values does not match table definition.
-- insert into temp_asdr(agentid, eventtype, eventdatetime, reasoncode, filter) values(temp_asdr_seq.nextval,l_agentid, l_eventtype, l_eventdatetime, l_reasoncode, l_filter);
FETCH NEXT FROM #SWV_cursor_var1 INTO #l_agentid, #l_eventtype, #l_eventdatetime, #l_reasoncode, #l_filter
END
CLOSE #SWV_cursor_var1
DELETE FROM temp_asdr1
SELECT TOP 1
#l_eventtype = eventtype,
#l_eventdatetime = eventdatetime,
#l_reasoncode = reasoncode,
#l_filter = filter
FROM temp_asdr
WHERE eventdatetime = (SELECT
MIN(eventdatetime)
FROM temp_asdr)
IF ##rowcount = 0
SELECT
#l_eventtype = NULL,
#l_eventdatetime = NULL,
#l_reasoncode = NULL,
#l_filter = NULL
DELETE FROM temp_login_logout
IF (#l_eventtype = #l_event_logout)
INSERT INTO temp_login_logout (seq, logintime, op1, logouttime, reasoncode, loginfilter, logoutfilter)
VALUES (0, NULL, '<', #l_eventdatetime, NULL, #l_filter, #l_filter)
INSERT INTO temp_login_logout (seq, logintime, loginfilter)
SELECT
seq,
eventdatetime,
filter
FROM temp_asdr tasdr
WHERE eventtype = #l_event_login
UPDATE temp_login_logout
SET logouttime = (SELECT
eventdatetime
FROM temp_asdr tasdr
WHERE tasdr.eventtype = #l_event_logout
AND tasdr.seq = (temp_login_logout.seq + 1)),
logoutfilter = (SELECT
filter
FROM temp_asdr tasdr
WHERE tasdr.eventtype = #l_event_logout
AND tasdr.seq = (temp_login_logout.seq + 1)),
reasoncode = (SELECT
reasoncode
FROM temp_asdr tasdr
WHERE tasdr.eventtype = #l_event_logout
AND tasdr.seq = (temp_login_logout.seq + 1))
UPDATE temp_login_logout
SET logouttime = #p_endTime,
op2 = '>',
logoutfilter = 0
WHERE logouttime IS NULL
UPDATE temp_login_logout
SET logintime = NULL,
op1 = '<',
reasoncode = NULL
WHERE loginfilter = 0
AND logoutfilter = 1
UPDATE temp_login_logout
SET logouttime = NULL,
op2 = '>',
reasoncode = NULL
WHERE loginfilter = 1
AND logoutfilter = 0
DELETE FROM temp_login_logout
WHERE loginfilter = 0
AND logoutfilter = 0
UPDATE temp_login_logout
SET duration = dbo.datediff('ss', logintime, logouttime)
END
Can someone please help with this error.
I guess, I have understood an issue with this.
May be its a glitch or something. But here what I did was deleted the function created where I had this table variable created. And then created the Stored Procedure first and then created function.
I was able to successfully compiled.

Optimise Stored Procedure Update and Select

The stored procedure I've created works, but is there a more efficient way of doing this? To be fair there is no performance hit for any of this nor does it need optimised but I'd like to know in the interest of doing things correctly.
Execution plan states query 1: 17%, query 2: 67%, query 3: 16%
DECLARE #CurrentVoucherID int;
SET #CurrentVoucherID =
(
SELECT TOP(1) IdGiftVoucherPhysicalCode
from GiftVoucherPhysicalCodes
WHERE Activated = 0 and assigned = 0 and Value = 10
ORDER BY IdGiftVoucherPhysicalCode
);
UPDATE GiftVoucherPhysicalCodes
SET Activated = 1, Activated_at = GETDATE()
WHERE IdGiftVoucherPhysicalCode = #CurrentVoucherID;
SELECT * FROM GiftVoucherPhysicalCodes
WHERE IdGiftVoucherPhysicalCode = #CurrentVoucherID;
I may not be understanding it correctly, but it looks like you are just running the update one record at a time? Why not do it in bulk?
UPDATE GiftVoucherPhysicalCodes
SET Activated = 1, Activated_at = GETDATE()
WHERE Activated = 0 and assigned = 0 and Value = 10
you can do it without variable
UPDATE GiftVoucherPhysicalCodes
SET Activated = 1, Activated_at = GETDATE()
WHERE IdGiftVoucherPhysicalCode = (SELECT TOP(1) IdGiftVoucherPhysicalCode
from GiftVoucherPhysicalCodes
WHERE Activated = 0 and assigned = 0 and Value = 10
ORDER BY IdGiftVoucherPhysicalCode)
SELECT * FROM GiftVoucherPhysicalCodes
WHERE IdGiftVoucherPhysicalCode = (SELECT TOP(1) IdGiftVoucherPhysicalCode
from GiftVoucherPhysicalCodes
WHERE Activated = 1 and assigned = 0 and Value = 10
ORDER BY IdGiftVoucherPhysicalCode)

IF ELSE condition in SQL select

I want to do a if-else condition statement in SQL Server but am not sure how.
Inside the stored procedure I have the following parameters:
#MarketId nvarchar (10),
#RegionId nvarchar (10)
And the following statement:
select * from Interaction I
where
(#MarketId = 0 ) OR (I.MarketId = (SELECT Id FROM Market WHERE ExternalId = #MarketId))
What I want to do is to check the value of #MarketId
if #MarketId = 0
then I want the where condition for I.MarketId to get its Ids from elsewhere like
(SELECT ID FROM Market WHERE ExternalId = #RegionId)
otherwise, if its 1, then I just want to leave it as is and get the Id from #MarketId instead of #RegionId..
How should I go about this?
Thanks!
This should work:
SELECT *
FROM Interaction I
WHERE ( #MarketID = 0
AND EXISTS (SELECT 1 FROM Market
WHERE ExternalId = #RegionId AND Id = I.MarketID)
OR I.MarketID = #MarketID

Retrieving the Name of Running Stored Procedures Across Multiple Databases

I'm trying to write a query that reports the current database activity. The query links together various DMV's like sys.dm_exec_connections, sys.dm_exec_sessions, sys.dm_exec_requests, etc. The query also pulls the actual queries being run via the sys.dm_exec_sql_text function.
(I'm aware of Activity Monitor and SQL Profiler. I need to gather this information up in a query, so neither of these programs are relevant here.)
Much of the activity in our systems takes place in stored procedures and functions. It would be nice to see the names of these procedures in this query.
My question is:
How do I reliably display the name of the stored procedures or functions being executed?
I'm aware that the sys.dm_exec_sql_text function returns an objectid, and that I can join this objectid to sys.objects. The problem is, there are multiple databases on this server, and sys.objects only applies to the current database. I want this query to be able to show the running object name no matter what database the query happened to be run against.
So far the only solution I have is to use sp_msforeachdb create a temp table containing all the object IDs and names from all databases and join to this table from the result of the dm_exec_sql_text function.
Is there a better solution to the temp table approach? I feel like I'm missing something.
I would recommend Adam Machanic's excellent sp_WhoISActive. It doesn't return the exact object name, but does return the sql command being executed in a nice clickable form.
--I use the following proc:
USE [master]
GO
CREATE PROC [dbo].[sp_who3]
AS
SET NOCOUNT ON
DECLARE #LoginName varchar(128)
DECLARE #AppName varchar(128)
SELECT [SPID] = s.[spid]
, [CPU] = s.[cpu]
, [Physical_IO] = s.[physical_io]
, [Blocked] = s.[blocked]
, [LoginName] = CONVERT([sysname], RTRIM(s.[Loginame]))
, [Database] = d.[name]
, [AppName] = s.[program_name]
, [HostName] = s.[hostname]
, [Status] = s.[Status]
, [Cmd] = s.[cmd]
, [Last Batch] = s.[last_batch]
, [Kill Command] = 'Kill ' + CAST(s.[spid] AS varchar(10))
, [Buffer Command] = 'DBCC InputBuffer(' + CAST(s.[spid] AS varchar(10))
+ ')'
FROM [master].[dbo].[sysprocesses] s WITH(NOLOCK)
JOIN [master].[sys].[databases] d WITH(NOLOCK)
ON s.[dbid] = d.[database_id]
WHERE s.[Status] 'background'
AND s.[spid] ##SPID --#CurrentSpid#
ORDER BY s.[blocked] DESC, s.[physical_io] DESC, s.[cpu] DESC, CONVERT([sysname], RTRIM(s.[Loginame]))
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT [Spid] = er.[session_Id]
, [ECID] = sp.[ECID]
, [Database] = DB_NAME(sp.[dbid])
, [User] = [nt_username]
, [Status] = er.[status]
, [Wait] = [wait_type]
, [Individual Query] = SUBSTRING(qt.[text], er.[statement_start_offset] / 2, (CASE WHEN er.[statement_end_offset] = - 1 THEN LEN(CONVERT(VARCHAR(MAX), qt.[text])) * 2
ELSE er.[statement_end_offset] END - er.[statement_start_offset]) / 2)
, [Parent Query] = qt.[text]
, [Program] = sp.[program_name]
, [Hostname] = sp.[Hostname]
, [Domain] = sp.[nt_domain]
, [Start_time] = er.[Start_time]
FROM [sys].[dm_exec_requests] er WITH(NOLOCK)
INNER JOIN [sys].[sysprocesses] sp WITH(NOLOCK)
ON er.[session_id] = sp.[spid]
CROSS APPLY [sys].[dm_exec_sql_text](er.[sql_handle]) qt
WHERE er.[session_Id] > 50 -- Ignore system spids.
AND er.[session_Id] NOT IN (##SPID) -- Ignore the current statement.
ORDER BY er.[session_Id], sp.[ECID]
END
GO

SQL Stored Procedure set variables using SELECT

I have a stored procedure in SQL Server 2005 with multiple variables and I want to set the values of these variables using a select statement. All three variables come from a same table and there should be a way to set them using one select statement instead of the way I currently have as shown below. Please help me to figure it out.
DECLARE #currentTerm nvarchar(max)
DECLARE #termID int
DECLARE #endDate datetime
SET #currentTerm =
(
Select CurrentTerm from table1 where IsCurrent = 1
)
SET #termID =
(
Select TermID from table1 where IsCurrent = 1
)
SET #endDate =
(
Select EndDate from table1 where IsCurrent = 1
)
select #currentTerm = CurrentTerm, #termID = TermID, #endDate = EndDate
from table1
where IsCurrent = 1
One advantage your current approach does have is that it will raise an error if multiple rows are returned by the predicate. To reproduce that you can use.
SELECT #currentTerm = currentterm,
#termID = termid,
#endDate = enddate
FROM table1
WHERE iscurrent = 1
IF( ##ROWCOUNT <> 1 )
BEGIN
RAISERROR ('Unexpected number of matching rows',
16,
1)
RETURN
END