looping through recordset in stored procedure - sql

I have created a tbl having SELECT statement as value (fieldname sqltxt).
Now want to read rows one by one and execute all the select statement stored in this table.
If it does not return any row i.e. zero row
insert a new record in DMSResults with value of DOCID from DMSRec
For that I use following script
set nocount on
use TESTDB
declare #sqlTXT as varchar(max);
DECLARE #DocID nvarchar(30);
drop table DMSResults
CREATE TABLE DMSResults (DOCID nvarchar(30) );`
drop table DMSRec
SELECT .....intoDMSRec FROM tbl....
Above syntax is a Big SQl script to create a recordset.
For my conveyance I insert all the records into new tbl.
Its returns more than 10,00,000 records
Now want to loop in tbl DMSREC, read the value of field sqltxt
Execute that statement.
If it doesn't return a record
Insert a record in DMSResults with value of DOCID field.
I also tried with following commands, but do not know how to loop in sql for next rec until eof and exit
Since DMSRec is a temporary table, once a row is processed then we can remove record from DMSRec.
declare #rc as bigint
Select #rc = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'DMSRec'
WHILE #rc <1
BEGIN
exec(select sqltxt from dmsrec where row=1)
-- here check record is exist or not then
-- if it is not exist or returning zero
-- add record in dmsresult with docid value
-- delete dmsrec where row=1
-- loop for next
END
Considering the huge size of database SQL-Server 2008r2 please guide me any optimize solution.
DMSRec TBL recordset.
DOCID         SQLTXT
A01/17-18     SELECT VRNO FROM TBL_LET WHERE VRNO='A01/17-18'

I can't address the actual problem here, but I can elaborate on the question of how to loop through all records. BTW< loops are terrible for performance and thus are avoided at all costs in SQL Server.
--get the row count of the table
declare #rc as bigint
Select #rc = (select count(*) from DMSRec)
--variables for incrementing rows and storing SQL
declare #i bigint = 1
declare #sql varchar(max)
WHILE #i <= #rc
BEGIN
--get the SQL Statement from the table
set #sql = (select sqltxt from dmsrec where row=#i)
--If no value was returned, insert into DSMResults
if (#sql is null) or (ltrim(rtrim(#sql)) = '')
begin
insert into DMSResults
select DOCID from dmsrec
end
--If a value was returned, execute that statement
else
begin
exec(#sql)
end
--increment the row number
set #i = #i + 1
END

Related

How to use results from an SQL Query as a list to delete (WSUS) updates

My problem is that I want to use the results from a SELECT query as the input values for a Stored Procedure. The issue is that the SP will only accept Scalar values, and I do not know SQL and so have been struggling to find a workaround or solution.
I want to modify the following Proc to accept multiple values to be used within the query:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spDeleteUpdateByUpdateID]
#updateID UNIQUEIDENTIFIER
AS
SET NOCOUNT ON
DECLARE #localUpdateID INT
SET #localUpdateID = NULL
SELECT #localUpdateID = LocalUpdateID FROM dbo.tbUpdate WHERE UpdateID = #updateID
IF #localUpdateID IS NULL
BEGIN
RAISERROR('The update could not be found.', 16, 40)
RETURN(1)
END
IF EXISTS (SELECT r.RevisionID FROM dbo.tbRevision r
WHERE r.LocalUpdateID = #localUpdateID
AND (EXISTS (SELECT * FROM dbo.tbBundleDependency WHERE BundledRevisionID = r.RevisionID)
OR EXISTS (SELECT * FROM dbo.tbPrerequisiteDependency WHERE PrerequisiteRevisionID = r.RevisionID)))
BEGIN
RAISERROR('The update cannot be deleted as it is still referenced by other update(s).', 16, 45)
RETURN(1)
END
DECLARE #retcode INT
EXEC #retcode = dbo.spDeleteUpdate #localUpdateID
IF ##ERROR <> 0 OR #retcode <> 0
BEGIN
RAISERROR('spDeleteUpdateByUpdateID got error from spDeleteUpdate', 16, -1)
RETURN(1)
END
RETURN (0)
TLDR: if anyone knows a quick way for me to use the results from SELECT UpdateID FROM tbUpdate WHERE UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629' to run exec spDeleteUpdateByUpdateID #updateID= i'd be extremely grateful.
There are some examples online of people using cursors to clean up WSUS. It will be slow but you are presumably only running it once. As mentioned there are other strategies for WSUS cleanup that should probably be investigated first.
DECLARE #var1 INT
DECLARE #msg nvarchar(100)
-- Get obsolete updates into temporary table
-- insert your own ID's here if you wish
CREATE TABLE #results (Col1 INT)
INSERT INTO #results(Col1) EXEC spGetObsoleteUpdatesToCleanup
DECLARE WC Cursor
FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO #var1
WHILE (##FETCH_STATUS > -1)
BEGIN
SET #msg = 'Deleting' + CONVERT(varchar(10), #var1)
RAISERROR(#msg,0,1) WITH NOWAIT EXEC spDeleteUpdateByUpdateId #var1
FETCH NEXT FROM WC INTO #var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

how I can hide displaying result of exec command

WHILE #nxt < #rc
BEGIN
set #sql = (select Rec from DmsRec where row=#nxt)
use TestDB1
exec (#sql)
select #rc_child = ##ROWCOUNT
use MyTempDB
if #rc_child = 0
begin
insert into DMSResults
select DOCID from DmsRec where row=#nxt
end
set #nxt = #nxt + 1
END
My Question is how I can hide displaying result of exec command.
(using Sql Server 2008r2) Above query is small part of complete procedure.
Accessing multiple conditions,value and multiple databases I generate a select statement and stored in Rec Field into table DmsRec
After generating require Select.... statement I stored it into table DmsRec.
e.g. SELECT ACCD FROM M_TABLE WHERE 1=1 and ACCD='0034422'.
This select statement which is stored as a value in table DmsRec
want to execute in different database.
So I used use command and change the database name, access the recordset.
If the executed sql (return 0 row) then run the insert command which is executed in different database.
With this I came to know wether Inserted docid into DMSResults is those tranaction whose master is not avalialbel.
It works perfectly but can not hide displaying records of exec command.
I run exec(#sql) is only to check whether it is returning any row or not.
and stored rowcount value into variable.
But do not want to display records in grid (at the same time result {effected rows} should stored in variable).
Without changing options in SSMS manually i.e.
Tools/Options, Query Results/SQL Server/Results to XX, check "Discard results after query executes"
EDIT - based on comments below
You can use sp_executesql and pass parameters to it, even OUTPUT parameters.
Here's an example - you will need to amend the SQL query you're storing slightly
DECLARE #SQL NVARCHAR(MAX), #Rows INT, #nxt INT = 1
CREATE TABLE DmsRec (row INT, rec NVARCHAR(10))
INSERT INTO DmsRec(row, rec)
VALUES(1, 1)
SET #SQL = 'IF EXISTS ( SELECT rec FROM dbo.DmsRec WHERE row = #nxt) SET #Rows = 1 ELSE SET #Rows = 0' --+'; SELECT #Rows = ##ROWCOUNT'
EXEC sys.sp_executesql #sql, N'#nxt INT, #Rows INT OUTPUT', #nxt, #Rows OUTPUT;
SELECT #Rows
SET #nxt = 0 -- record doesn't exist
SET #SQL = 'IF EXISTS ( SELECT rec FROM dbo.DmsRec WHERE row = #nxt) SET #Rows = 1 ELSE SET #Rows = 0'
EXEC sys.sp_executesql #sql, N'#nxt INT, #Rows INT OUTPUT', #nxt, #Rows OUTPUT;
SELECT #Rows
You can then use #Rows variable to determine whether you need to insert a new record or not.
If #Rows = 1
BEGIN
--INSERT record
END

Copy from one temp table to another temp table on condition base?

How to copy from one temp table to another temp table on condition base then how to retrieve from that pasted table?
I tried like below but retrieving from both conditions where as I want pasted table data selection which I never getting.
alter procedure Get_LoginLogutDetails
as
begin
DECLARE #cmd AS NVARCHAR(max)
DECLARE #cmdOriginal AS NVARCHAR(max)
CREATE TABLE #result
(
LoggedOutTime datetime
)
CREATE TABLE #OriginalResult
(
Duration varchar(100)
)
declare #loggedOutTime varchar(20)
SET #cmd ='select LoggedOutTime from LastLoggedInDetails'
Insert into #result
EXEC(#cmd)
declare result_cursor cursor for
SELECT LoggedOutTime
from #result
where LoggedOutTime is null
OPEN result_cursor
FETCH NEXT FROM result_cursor INTO #loggedOutTime
WHILE ##FETCH_STATUS = 0
BEGIN
if(#loggedOutTime is null)
begin
select 'Running..'
Insert into #OriginalResult
EXEC(#cmd)
end
else if(#loggedOutTime is not null)
begin
select LoggedOutTime from #result
Insert into #OriginalResult
EXEC(#cmd)
end
FETCH NEXT FROM result_cursor INTO #loggedOutTime
END
select * from #OriginalResult
end
Ok, so i had a read through your script and have tried to work out what you are trying to do. it looks like you are possibly trying to get the LoggedOutTimes when there is a time, if there is no logged out time, you want the result "Running..." to be inserted into a temp table.
SELECT ISNULL(LoggedOutTime, 'Running...')
INTO #OriginalResult
FROM LastLoggedInDetails
This gives you a temp table with the above scenario. Unsure on the datatype of LoggedOutTime, you may need to convert it to an nvarchar.
Your original question doesn't make a lot of sense, you should try rewording it to get some more accurate help.
Sorry to all for my not good explainations , but I finally reached my need.
I want like nelow.
select LastLoggedInDetails.LoggedInTime,case
when LastLoggedInDetails.LoggedOutTime is not null then CONVERT(VARCHAR(100),DATEDIFF (hour,LastLoggedInDetails.LoggedInTime ,LastLoggedInDetails.LoggedOutTime ))+' Hours '+
CONVERT(VARCHAR(100),DATEDIFF (minute,LastLoggedInDetails.LoggedInTime ,LastLoggedInDetails.LoggedOutTime )%60) +' Minutes'
when LastLoggedInDetails.LoggedOutTime is null then 'Running...'
end
from dbo.LastLoggedInDetails

T-SQL: Update temp table using "from variable" query

I have a linked server connecting to a Lotus notes database as the source. The destination will be an MS SQL database.
I have two temp tables. The first temp table is pulling in the table names from a linked server. From there, I want to do a record count for each table and store that value into the second temp table beside the table name.
I am having trouble trying to run a loop or cursor for each table name and then updating the second temp table with the record count for each table name.
Right now I am getting an error "Incorrect syntax near 'Execute'". SET record_count = Execute(#sqlCommand)
Declare #DB_tables table (
table_cat varchar(1500),
table_schem varchar(1500),
table_name varchar(1500),
table_type varchar(1500),
remarks varchar(1500)
)
Declare #temp_table table (
table_name varchar(1500),
record_count varchar(255),
drop_script varchar(1500),
update_script varchar(1500)
)
--Load Initial data from linked server database
insert into #DB_Tables
exec sp_tables_ex [LINKED_SERVER_DB]
--Load table name from Stored Procedure
INSERT INTO #temp_table (table_name)
SELECT table_name from #DB_Tables
--select * from #temp_table
--Variable to hold each table name in a loop or cursor
declare #tbl_name varchar(1500)
--declare #sqlCommand varchar(1500)
declare cur cursor for select table_name from #DB_Tables
Open cur
--Loop through each table name from the first temp table
--then update the second temp table (#temp_table) with the record count
FETCH NEXT FROM cur into #tbl_name
While ##FETCH_STATUS = 0 BEGIN
declare #sqlCommand varchar(1500)
--query used to get the record count from the frist temp table (#DB_tables)
SET #sqlCommand = 'select count(*) from '+#tbl_name
UPDATE #temp_table
SET record_count = Execute(#sqlCommand)
END
CLOSE cur
Deallocate cur
select * from #temp_table
It's not easy to use table variables with execute because the dynamic SQL is executed in the different context and doesn't see the variable and you can't assign results from execute that way.
You can either insert the results into a table variable with this syntax:
insert into #temp_table
execute ('select ' + #tbl_name + ', count(*) from ' + #tbl_name ...)
Or use temp. tables, since then you can refer them also inside the dynamic SQL, so you could do something like:
create table #temp_table (
table_name varchar(1500),
record_count varchar(255),
drop_script varchar(1500),
update_script varchar(1500)
)
...
Execute('update #temp_table set record_count = (select count(*) from '
+#tbl_name+') where table_name = '''+#tbl_name+''')

Update a Table with Dynamic SQL results within Stored Procedure

I have a table EPFReport where I need to fill the tables with a stored procedure.
ALTER procedure [dbo].[getEPFData] #EPFCol varchar(max) , #empID varchar(max)
AS
DECLARE #sql nvarchar(max) ;
DECLARE #sql2 nvarchar(max);
set #sql = 'SELECT c.employeeID,c.empName, c.month,#sql1 from Common c where c.employeeID='+#empID
set #sql2= 'SELECT ' + #EPFCol + ' FROM Common where employeeID='+#empID
truncate table EPFReport;
INSERT into EPFReport (empID, empName, monthVal)
execute(#sql);
Up to here the requirement is fulfilled where the results of the query #sql will be inserted to the table. Now I need to update it with #sql2 query, so the question is how to execute a query within a stored procedure for an update statement?
PS: for insert I've used
INSERT into EPFReport (empID, empName, monthVal)
execute(#sql);
Also here a set of results are returned (for each month). Not one row or cell of result. So assigning to a variable and updating doesn't work.
Update: the table contains these columns
[empID] [empName] [EPFItemValues] [monthVal]
First query updates only 3 columns , and the second query should update the column EPFItemValues.
Try;
Based on your comment, the following should work;
DECLARE #ID int = (Select MAX(ID) From EPFReport) // or SCOPE_IDENTITY
Update EPFReport
set EPFItemValues = #sql2
where ID = #ID