How really functions WAITFOR statement in SQL? - sql-server

Maybe someone already ask this, but I can't find appropriate answer to this question.
If I have, let's say, following query:
SELECT
column1,
column2,
column3
FROM Table1 AS t1
WAITFOR DELAY '10:00:00'
where this query returns around 100000 rows.
Did WAITFOR statement waiting 10 hours before telling SQL Server to execute query and produce result or SQL Server execute query immediately and keep result in RAM for 10 hours and then send it over network or just show?
Am I missing here something?
I would appreciate if someone give me real example that prove first or second solution.
I executed next query:
SELECT GETDATE()
SELECT GETDATE()
WAITFOR DELAY '00:00:05'
The result was two dates that were the same. On this basis, I will conclude that SQL Server immediately executes the query and keeps the result for certain time to show, but that made little sense for me.

According to the docs, the WAITFOR command is used to block a statement or transaction for the specified amount of time. In that case, you'd use it to delay subsequent statements. In other words, you'd want to execute something after the WAITFOR command, not before. Here's a few examples:
The following example executes the stored procedure after a two-hour delay.
BEGIN
WAITFOR DELAY '02:00';
EXECUTE sp_helpdb;
END;
GO
The following example executes the stored procedure sp_update_job at 10:20 P.M. (22:20).
USE msdb;
EXECUTE sp_add_job #job_name = 'TestJob';
BEGIN
WAITFOR TIME '22:20';
EXECUTE sp_update_job #job_name = 'TestJob',
#new_name = 'UpdatedJob';
END;
GO

Related

Time Delay in Union Operator in SQL Server

I am having statement.
SELECT *
FROM DemoTable
WHERE i = 7
UNION
SELECT *
FROM DemoTable
WHERE i = 6
What i need i need to put time delay between the union statement i need to check something related to snapshot isolation.
Can i put time delay between the union
Such as
SELECT *
FROM DemoTable
WHERE i = 7
Will Run First and after 10 seconds
SELECT *
FROM DemoTable
WHERE i = 6
But i need both in one statement i.e with union only.
You cannot put a delay in the middle of the union. A select/union is part of the SQL DML. Delay is a programming construct and is not related to data manipulation in any way.
Also, isolation and concurrency would not be impacted by separates reads on the same table. Reads generally use a shared lock. You'll need to start a transaction that modifies the data in some way for there to be any impact to concurrency. You'd be better off using multiple query windows or connections with explicit transactions.
You can use WAITFOR inside of a stored procedure, but never with a union.
CREATE PROCEDURE dbo.testproc
AS
BEGIN
SELECT CURRENT_TIMESTAMP;
WAITFOR DELAY '00:00:02'
SELECT CURRENT_TIMESTAMP;
END
go
EXEC dbo.testproc
try insert WAITFOR DELAY '00:02';

SQL injection with parameterised procedures

need a bit of help with this sql injection issue:
The following is a version of a parameterised stored procedure. Excluding how it is called from an application, is there anyway to prevent #v_string from being treated as dynamic SQL?
I think this is fairly water tight - there's no execute or concatenated sql, but still inserting a semicolon allows additional data to be returned.
I know there are multiple levels to consider this question on, but I want to know if there is some simple solution I am missing here as the majority of injection fixes involve dynamic queries.
create table dbo.Employee (EmpID int,EmpName varchar(60))
declare
#v_id int,
#v_string varchar(60)
begin
set #v_string='test'''; waitfor delay '0:0:5' --
if #v_id is null
begin
set #v_id = (select EmpID
from Abc.Employee
where EmpName=#v_string);
end
print #v_id
end
is there anyway to prevent #v_string from being treated as dynamic
SQL?
I would not expect #v_string to be treated as dynamic SQL here since the T-SQL code has no EXECUTE or EXECUTE sp_executeSQL. The value will not be executed, but treated as a WHERE clause value not vulnerable to SQL injection.
If this doesn't answer your question, post a full example that demonstrates the value being treated as dynamic SQL.
You're being confused by your own testing. The line:
set #v_string='test'''; waitfor delay '0:0:5' --
Is creating a string #v_string with the value test', and then executing waitfor delay '0:0:5'. Then your actual Employee query is being run.
So if you run your query as is, with your additional example:
set #v_string='test'''; select * from sys.databases
...what will happen is that line of code will set #v_string to be test', then immediately execute select * from sys.databases. Then the rest of your code will run, executing your actual select. So you'll see the result of select * from sys.databases, followed by the result of your Employee query, but only because you actually hard-coded the statement select * from sys.databases into your procedure without realising it :)
If you want the string #v_string to be set to test'; waitfor delay '0:0:5' then you've got the string quoting wrong. It should be:
set #v_string='test''; waitfor delay ''0:0:5'''

SQL Server prepared statement execution - strange behavior

I have some .NET application which communicates with a SQL Server 2012 database.
Generally it gets a request from the client, runs some set of SQL queries to process the request and returns the result. To optimize performance, I prepare all the queries at startup and then execute the prepared statements each and every time. This works good most of the time, but occasionally I got some strange performance glitches, so I tried to investigate what's going on with the help of profiler.
I caught Showplan XML Statistics Profile and RPC:Completed events.
When the application behaves normally, I can see in profiler that on startup it executes something like:
declare #p1 int
set #p1 = 5
exec sp_prepexec #p1 output, N'#my_param_list', N'select my_field from my_table'
and then on each client request:
exec sp_execute 5, #myparam1=value1, #myparam2=value2 ...
Before this RPC:Completed line I can see Showplan XML Statistics Profile event with pretty normal execution plan. The duration of the query is ~50ms, which is good.
Now, when the problem occurs, I can see in profiler about 2500(!) lines of Showplan XML Statistics Profile events - each one with some meaningless index scan on one of the tables participating in the query (the only difference is the index which participates in the scan), followed by "Stream Aggregate" . And after all these lines I can see at last RPC:Completed event with the following text:
declare #p1 int
set #p1 = NULL
exec sp_prepexec #p1 output, N'#my_param_list', N'select my_field from my_table'
and the duration of more than 30 seconds. I can't understand why it takes so long, what is the meaning of all these scans, and why the handler is NULL in sp_prepexec. It looks to me like SQL Server tries very hard to execute the prepared statement, than abandons it or probably tries to re-prepare it.
So I'd be happy to get an explanation of what's wrong with this and what is going on.... Thanks in advance and sorry for the long explanation.

Status of Stored Procedure call from Agent job, when job is stopped

We have a clean-up job, which calls a stored procedure, which in turn deletes one day's worth of records for a log table. This job runs every five minutes and usually completes in less than 10 seconds. Sometimes, it take much longer, as long as 15 minutes. During such instances, the log table gets locked and subsequent transactions timeout, till the job completes.
In order to address this, we came up with this solution -
1) Remove the scheduling of the existing job
2) Create a new job, to call the original job
3) Schedule the new job to run every 5 minutes
4) See below code of the new job
DECLARE #JobToRun NVARCHAR(128) = N'OM_EDU_Purge logs'
EXEC msdb.dbo.sp_start_job #JobToRun
WAITFOR DELAY '00:00:20'
IF EXISTS(SELECT 1
FROM msdb.dbo.sysjobs J
JOIN msdb.dbo.sysjobactivity A
ON A.job_id=J.job_id
WHERE J.name=#JobToRun
AND A.run_requested_date IS NOT NULL
AND A.stop_execution_date IS NULL
)
BEGIN -- job is running or finishing (not idle)
EXEC msdb.dbo.sp_stop_job #job_name=#JobToRun
-- could log info, raise error, send email etc here
END
This seems to work fine and stops the job if it is still running after 20 seconds. However, since the job calls a stored procedure, here is my question:
When the job is stopped, will it also terminate the stored procedure that is executing?
I think you query gets stuck because the log table being updated or creating records concurrently with you delete statement. So you might try to lock the table while delete statement execution. update your procedure inside query like this exp: delete from logs with(tablock)
Here, a stored proc is just calling another nested stored proc. So no, stored proc won't be stopped. The control will return to the calling stored proc. You should have sufficient error-handling in the proc to take care of scenarios where the called sproc errors out.

TSQL : Timeouts on High traffic table

I'm having issues with timeouts of a table on mine.
Example table:
Id BIGINT,
Token uniqueidentifier,
status smallint,
createdate datetime,
updatedate datetime
I'm inserting data into this table from 2 different stored procedures that are wrapped with transaction (with specific escalation) and also 1 job that executes once every 30 secs.
I'm getting timeout from only 1 of them, and the weird thing that its from the simple one
BEGIN TRY
BEGIN TRAN
INSERT INTO [dbo].[TempTable](Id, AppToken, [Status], [CreateDate], [UpdateDate])
VALUES(#Id, NEWID(), #Status, GETUTCDATE(), GETUTCDATE() )
COMMIT TRAN
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN;
END CATCH
When there is some traffic on this table (TempTable) this procedure keeps getting timeout.
I checked the execution plan and it seems I haven't missed any indexes in both stored procedures.
Also, the only index on TempTable is the clustered PK on Id.
Any ideas?
If more information is needed, do tell.
The 2nd stored procedure using this table isn't causing any big IO or something.
The job, however, uses an atomic UPDATE on this table and in the end of it DELETEs from the table, but as I checked on high IO of this table, the job takes no longer than 3 secs.
Thanks.
It is most propably because some other process is blocking your insert operation, It could be another insert, delete , update or some trigger or any other sql statement.
To find out who is blocking your operation you can use some esaily avialable stored procedures like
sp_who2
sp_whoIsActive (My Preferred)
While your insert statement is being executed/hung up execute one of these procedures and see who is blocking you.
In sp_who2 you will see a column by the name Blk_by get the SPID from that column and execute the following query
DBCC INPUTBUFFER(71);
GO
This will reutrn the last query executed by that process id. and it is not very well formatted the sql statement, all the query will be in one single line you will need to format it in your SSMS to acutally be able to read it.
On the other hand sp_WhoIsActive will only return the queries that are blocking other process and will have the query formatted just as the user has execute it. Also it will give you the execution plan for that query.

Resources