Update specific batch of records from minute to minute on SQL Server - sql

Sorry in advance if the question makes little sense.
I need to know how to update a table every X seconds/minutes/hours.
I normally do something like this:
UPDATE myTable SET someField = someField WHERE id_ofMyTable > 0 and id_ofMyTable < 1000
After this query, some XMLs files are created thanks to a second Stored Procedure.
The problem is that I want to update all the id_ofMyTable from 0 to the max. But if I make an update without the id_ofMyTable parameter then the XMLs get corrupted or the server that "fetch" the XMLs gets overloaded.
Does anybody know a way to update the table every 'x' time instead of me doing a manual UPDATE whenever I see that the XMLs were fetched?
I hope my question make sense and I apologize in advance if it seems totally wrong. I'm more than happy to elaborate more on the topic if needed.

Okay, let us make it simple (only if you do not want to use SQL Agent).
In Sql Server Management Studio Run the following script, please modify it as per your need.
DECLARE #DATA_ID INT
DECLARE #MAX_DATA_ID INT
SET #DATA_ID = 0
SELECT #MAX_DATA_ID = MAX(id_ofMyTable) FROM MyTable
WHILE #DATA_ID <= #MAX_DATA_ID
BEGIN
IF #MAX_DATA_ID - #DATA_ID >= 1000
BEGIN
UPDATE myTable SET someField = someField WHERE id_ofMyTable >= #DATA_ID AND id_ofMyTable < #DATA_ID + 1000
SET #DATA_ID = #DATA_ID + 1000
END
ELSE
BEGIN
UPDATE myTable SET someField = someField WHERE id_ofMyTable >= #DATA_ID AND id_ofMyTable < #DATA_ID + (#MAX_DATA_ID - #DATA_ID)
SET #DATA_ID = #DATA_ID + (#MAX_DATA_ID - #DATA_ID)
END
WAITFOR DELAY '00:00:01' --Set your sleep time here.
END
You can run it and leave it. One drawback is you need to run it manually, once and then again if there is a disconnection with SQL Server.

A SQL Agent job can be scheduled to run SQL batches at defined time intervals.
Information on how to configure and use SQL Agent can be found here.

Related

Adding microseconds to Timestamp and assigning to Host variable in DB2 - BIND ERROR FROM BUILD

I've been struggling with this for far too long and can't seem to wrap my head around what really is the issue.
As an input I receive from caller TMS = 2020-01-02-03.04.05.060708. I then want to achieve the following - but my build ends in BINDLOG ERROR (see bottom).
DCL TMS CHAR(26);
DCL START CHAR(26);
DCL END CHAR(26);
IF TMS ^= ''
THEN
DO;
EXEC SQL SET :START = TMS + 1 MICROSECOND;
EXEC SQL SET :END = TMS + 30 DAYS;
END;
ELSE
DO;
EXEC SQL SET :START = '0001-01-01 00:00:00.000000';
EXEC SQL SET :END = CURRENT TIMESTAMP;
END;
Seems like TMS is not properly set to the respective Host varriable, even though TMS is in fact a timestamp. Looking at the documentation only seems to confuse me more. Any clues as how to perform arithmetic actions on date/time variables?
I have tried adding days to a date format which worked fine. But adding days, or microseconds to a TIMESTAMP is causing me lots of headache. The below works like a charm, just struggling to understand why?
DCL TMS_VALID CHAR(10);
DCL TMS_EMPTY CHAR(10);
IF TMS ^= ''
THEN
DO;
TMS_VALID = SUBSTR(TMS,1,10);
EXEC SQL SET :START = DATE(:TMS_VALID); /* Would like to add 1 microsecond to :START*/
EXEC SQL SET :END = DATE(:TMS_VALID) + 30 DAYS;
END;
ELSE
DO;
TMS_EMPTY = SUBSTR(CURRENT_TIMESTAMP,1,10);
EXEC SQL SET :START = DATE(:TMS_EMPTY) - 30 DAYS;
EXEC SQL SET :END = DATE(:TMS_EMPTY);
END;
Below is the BINDLOG. Any help would be greatly appreciated, thanks!
DSNX200I :DB2A BIND SQL ERROR
USING TSTSD AUTHORITY
PLAN=(NOT APPLICABLE)
DBRM=AB12345
STATEMENT=455
SQLCODE=-206
SQLSTATE=42703
TOKENS=AB12345I.TMS
CSECT NAME=DSNXORSO
RDS CODE=-225
DSNX200I :DB2A BIND SQL ERROR
USING TSTSD AUTHORITY
PLAN=(NOT APPLICABLE)
DBRM=AB12345
STATEMENT=456
SQLCODE=-206
SQLSTATE=42703
TOKENS=AB12345I.TMS
CSECT NAME=DSNXORSO
RDS CODE=-225

IBM DB2 SQL sleep, wait or delay for stored procedure

I have a small loop procedure that is waiting for another process to write a flag to a table. Is there any way to add a delay so this process doesn't consume so much cpu? I believe it may need to run between 1-2 min if everything ends correctly.
BEGIN
DECLARE STOPPED_TOMCAT VARCHAR (1);
UPDATE MRC_MAIN.DAYEND SET DENDSTR = 'Y';
SET STOPPED_TOMCAT = (SELECT TOMCSTP FROM MRC_MAIN.DAYEND);
WHILE ( STOPPED_TOMCAT <> 'Y')
DO
SET STOPPED_TOMCAT = (SELECT TOMCSTP FROM MRC_MAIN.DAYEND);
END WHILE;
END;
Use call dbms_alert.sleep(x), where x - number of seconds.
I don't have the resources to test this solution, but why don't try calling IBM i Command DLYJOB in your code:
CALL QCMDEXC('DLYJOB DLY(1)', 13);
The parameter DLY indicates the wait time in seconds and the number 13 is the length of the command string being executed.

SSMS Set Statistics Time On/Off prints multiple lines instead of just one

When I run my query, it prints multiple execution times instead of just one. I only want one so what do I need to do to get this to only print one time stamp?
SET STATISTICS TIME ON
DECLARE #firstNum INT, #secondNum INT, #thirdNum INT, #evenSum INT
SET #firstNum = 1
SET #secondNum = 2
set #thirdNum = 2
SET #evenSum = 2
WHILE (#thirdNum <= 4000000)
BEGIN
SET #thirdNum = #firstNum + #secondNum
SET #firstNum = #secondNum
SET #secondNum = #thirdNum
IF (#thirdNum % 2) = 0
SET #evenSum += #thirdNum
END
PRINT 'Answer = ' + CONVERT(VARCHAR, #evenSum)
SET STATISTICS TIME OFF
If you remove PRINT 'Answer = ' + CONVERT(VARCHAR, #evenSum) from your code
then it won't print multiple execution time.
Here is the example of it.
Statistic time will print for each execution. Since you are looping you are performing multiple query statements (I believe this also applies for sets -i could be wrong though), each will provide an execution time. There really is no way to modify statistic time for what I think you are looking for.
You could declare a datetime2 and store the start time in the beginning by using SysDateTime, and get the end time upon completion, thus printing the difference onto the screen using DateDiff. (This will achieve what you are asking for. )
You could also look into client statistic (but that might not be what you want).
Side note and irrelevant: you are looping queries. This is not profient and you may be doing this to learn. I would recommend looking into Tally tables for replacing loops. You can greatly improve performance if you design your query correctly.

T-SQL: Stop query after certain time

I am looking to run a query in t-SQL (MS SQL SMS) that will stop after X number of seconds. Say 30 seconds. My goal is to stop a query after 6 minutes. I know the query is not correct, but wanted to give you an idea.
Select * from DB_Table
where (gatedate()+datepart(seconds,'00:00:30')) < getdate()
In SQL Server Management Studio, bring up the options dialog (Tools..Options). Drill down to "Query Execution/SQL Server/General". You should see something like this:
The Execution time-out setting is what you want. A value of 0 specifies an infinite time-out. A positive value the time-out limit in seconds.
NOTE: this value "is the cumulative time-out for all network reads during command execution or processing of the results. A time-out can still occur after the first row is returned, and does not include user processing time, only network read time." (per MSDN).
If you are using ADO.Net (System.Data.SqlClient), the SqlCommand object's CommandTimeout property is what you want. The connect string timeout verb: Connect Timeout, Connection Timeout or Timeout specifies how long to wait whilst establishing a connection with SQL Server. It's got nothing to do with query execution.
Yes, let's try it out.
This is a query that will run for 6 minutes:
DECLARE #i INT = 1;
WHILE (#i <= 360)
BEGIN
WAITFOR DELAY '00:00:01'
print FORMAT(GETDATE(),'hh:mm:ss')
SET #i = #i + 1;
END
Now create an Agent Job that will run every 10 seconds with this step:
-- Put here a part of the code you are targeting or even the whole query
DECLARE #Search_for_query NVARCHAR(300) SET #Search_for_query = '%FORMAT(GETDATE(),''hh:mm:ss'')%'
-- Define the maximum time you want the query to run
DECLARE #Time_to_run_in_minutes INT SET #Time_to_run_in_minutes = 1
DECLARE #SPID_older_than smallint
SET #SPID_older_than = (
SELECT
--text,
session_id
--,start_time
FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
WHERE text LIKE #Search_for_query
AND text NOT LIKE '%sys.dm_exec_sql_text(sql_handle)%' -- This will avoid the killing job to kill itself
AND start_time < DATEADD(MINUTE, -#Time_to_run_in_minutes, GETDATE())
)
-- SELECT #SPID_older_than -- Use this for testing
DECLARE #SQL nvarchar(1000)
SET #SQL = 'KILL ' + CAST(#SPID_older_than as varchar(20))
EXEC (#SQL)
Make sure the job is run by sa or some valid alternative.
Now you can adapt it to your code by changing:
#Search_for_query = put here a part of the query you are looking for
#Time_to_run_in_minutes = the max number of minutes you want the job to run
What will you be using to execute this query? If you create a .NET application, the timeout for stored procedures by default is 30 seconds. You can change the timeout to be 6 minutes if you wish by changing SqlCommand.CommandTimeout
In SQL Server, I just right click on the connection in the left Object Explorer pane, choose Activity Monitor, then Processes, right click the query that's running, and choose Kill Process.

How to organize infinite while loop in SQL Server?

I want to use infinite WHILE loop in SQL Server 2005 and use BREAK keyword to exit from it on certain condition.
while true does not work, so I have to use while 1=1.
Is there a better way to organize infinite loop ?
I know that I can use goto, but while 1=1 begin ... end looks better structurally.
In addition to the WHILE 1 = 1 as the other answers suggest, I often add a "timeout" to my SQL "infintie" loops, as in the following example:
DECLARE #startTime datetime2(0) = GETDATE();
-- This will loop until BREAK is called, or until a timeout of 45 seconds.
WHILE (GETDATE() < DATEADD(SECOND, 45, #startTime))
BEGIN
-- Logic goes here: The loop can be broken with the BREAK command.
-- Throttle the loop for 2 seconds.
WAITFOR DELAY '00:00:02';
END
I found the above technique useful within a stored procedure that gets called from a long polling AJAX backend. Having the loop on the database-side frees the application from having to constantly hit the database to check for fresh data.
Using While 1 = 1 with a Break statement is the way to do it. There is no constant in T-SQL for TRUE or FALSE.
If you really have to use an infinite loop than using while 1=1 is the way I'd do it.
The question here is, isn't there some other way to avoid an infinite loop? These things just tend to go wrong ;)
you could use the snippet below to kick a sp after soem condition are rised. I assume that you ahev some sort of CurrentJobStatus table where all the jobs/sp keeps their status...
-- *** reload data on N Support.usp_OverrideMode with checks on Status
/* run
Support.usp_OverrideMode.Number1.sql
and
Support.usp_OverrideMode.Number2.sql
*/
DECLARE #FileNameSet TABLE (FileName VARCHAR(255));
INSERT INTO #FileNameSet
VALUES ('%SomeID1%');
INSERT INTO #FileNameSet
VALUES ('%SomeID2%');
DECLARE #BatchRunID INT;
DECLARE #CounterSuccess INT = 0;
DECLARE #CounterError INT = 0;
-- Loop
WHILE WHILE (#CounterError = 0 AND #CounterSuccess < (select COUNT(1) c from #FileNameSet) )
BEGIN
DECLARE #CurrenstStatus VARCHAR(255)
SELECT #CurrenstStatus = CAST(GETDATE() AS VARCHAR)
-- Logic goes here: The loop can be broken with the BREAK command.
SELECT #CounterSuccess = COUNT(1)
FROM dbo.CurrentJobStatus t
INNER JOIN #FileNameSet fns
ON (t.FileName LIKE fns.FileName)
WHERE LoadStatus = 'Completed Successfully'
SELECT #CounterError = COUNT(1)
FROM dbo.CurrentJobStatus t
INNER JOIN #FileNameSet fns
ON (t.FileName LIKE fns.FileName)
WHERE LoadStatus = 'Completed with Error(s)'
-- Throttle the loop for 3 seconds.
WAITFOR DELAY '00:00:03';
select #CurrenstStatus = #CurrenstStatus +char(9)+ '#CounterSuccess ' + CAST(#CounterSuccess AS VARCHAR(11))
+ char(9)+ 'CounterError ' + CAST(#CounterError AS VARCHAR(11))
RAISERROR (
'Looping... # %s'
,0
,1
,#CurrenstStatus
)
WITH NOWAIT;
END
-- TODO add some codition on #CounterError value
/* run
Support.usp_OverrideMode.WhenAllSuceed.sql
*/
Note the code is flexibile you can add as many condition checks on the #FileNameSet table var
Mario