Iterate through a temp table - sql

I did try looping through a temp table, but of no use end up with so many errors only.
Please help me on how can I work this one out..
My need is like :
I need to fetch an ID column from a table, and store it in one temp table.
Then iterate through each ID, and execute a stored procedure which takes that ID as an parameter.
Insert the return value (= one column) of that stored procedure in another table.
Please guide me on how to do this.
I did search a lot..and got confused with cursor and set based join.

IMHO in your case you don't need a temp table.
Let's say you have following two tables. First is source table and the other is destination table.
CREATE TABLE mytable(id INT IDENTITY PRIMARY KEY, col1 nvarchar(10));
CREATE TABLE mytable2(id INT, value INT);
mytable has following sample data in it:
id col1
----------------
1 row1
2 row2
3 row3
4 row4
And you have some SP that calculates something based on id, something like this
CREATE PROCEDURE getValue (#id INT, #value INT OUT)
AS
SET NOCOUNT ON;
SET #value = #id * 2;
Then you can create an SP that will do the job like this
CREATE PROCEDURE proccessData
AS
SET NOCOUNT ON;
DECLARE #id INT, #value INT;
DECLARE id_cursor CURSOR FOR
SELECT id FROM mytable WHERE id > 1 AND id < 4;
OPEN id_cursor;
FETCH NEXT FROM id_cursor INTO #id;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC getValue #id, #value OUTPUT;
INSERT INTO mytable2 VALUES(#id, #value);
-- Or use update if you already have id's in mytable2
-- UPDATE mytable2 SET value = #value WHERE id = #id;
FETCH NEXT FROM id_cursor INTO #id;
END
CLOSE id_cursor;
DEALLOCATE id_cursor;
After you call that SP
EXEC proccessData
you'll get in mytable2
id value
----------- -----------
2 4
3 6
And here is working sqlfiddle

Related

Updating Null records of a table by invoking stored procedure throws error 'Subquery returned more than one value'

I am trying to update all null values of a column with Uuid (generated with the help of a stored procedure GetOptimizedUuid). While doing so I am getting an error
Subquery returned more than 1 value
I could understand the causes of error but none of my fix helped out.
I tried out with some loops but it doesn't fix
BEGIN
DECLARE #no INT;
DECLARE #i INT;
SET #no = (SELECT COUNT(id) FROM table1)
SET #i = 0;
WHILE #i < #no
BEGIN
DECLARE #TempUuid TABLE(SeqUuid UNIQUEIDENTIFIER, OptimizedUuid UNIQUEIDENTIFIER)
INSERT INTO #TempUuid
EXECUTE [Sample].[dbo].[GetOptimizedUuid]
UPDATE table1
SET col2 = (SELECT OptimizedUuid FROM #TempUuid)
WHERE col2 IS NULL;
SET #i = #i + 1;
END
END
Help me to sort out this, Thanks!
Not entirely sure what you're doing - what do you need to call this GetOptimizedUuid stored procedure? Can't you just use NEWID() to get a new GUID?
Anyway - assuming you have to call this stored procedure, I assume you'd call it once before the loop, to get the ID's you need - and then you get the top (1) UUID from the table and update one row in your database table - and then you also need to remove that UUID that you've just used from the temp table, otherwise you keep re-using the same ID over and over again....
Try something like this:
BEGIN
DECLARE #no INT;
DECLARE #i INT;
SET #no = (SELECT COUNT(id) FROM table1)
SET #i = 0;
-- define and fill the table *ONCE* and *BEFORE* the loop
DECLARE #TempUuid TABLE(SeqUuid UNIQUEIDENTIFIER, OptimizedUuid UNIQUEIDENTIFIER)
INSERT INTO #TempUuid
EXECUTE [Sample].[dbo].[GetOptimizedUuid]
-- declare a UUID to use
DECLARE #NewUuid UNIQUEIDENTIFIER;
WHILE #i < #no
BEGIN
-- get the first UUID from the temp table
SELECT TOP (1) #NewUuid = OptimizedUuid
FROM #TempUuid;
-- update your table
UPDATE table1
SET col2 = #NewUuid
WHERE col2 IS NULL;
-- *REMOVE* that UUID that you've used from the table
DELETE FROM #TempUuid
WHERE OptimizedUuid = #NewUuid;
SET #i = #i + 1;
END
END

Printing all values of two columns in sql stored procedure

I have been trying to print all values of two columns of table using loop in sql stored procedure but no luck yet.
CREATE PROCEDURE [usp_my_procedure_name]
AS
SET NOCOUNT ON;
BEGIN
DECLARE #User_ID INT =16
DECLARE #ID INT
DECLARE #Count INT
DECLARE #Count1 INT
DECLARE #Code VARCHAR(500)
SELECT #Count1= MAX(ID), #Count = MIN(ID)
FROM ABC
WHERE ID = 10 AND Code NOT LIKE '%ABC%'
WHILE (#Count <= #count1)
BEGIN
SELECT #ID = (ID), #Code = Code
FROM ABC
WHERE ID = 10 AND Code NOT LIKE '%ABC%
PRINT #ID
PRINT #Code
SET #Count = #Count + 1
END
END
Also how to optimize it further as i have to traverse for 7k records
Try this, and share with us what it gives you, and what the ideal result would look like (also share some of the input rows from ABC).
CREATE PROCEDURE [usp_my_procedure_name]
AS
SET NOCOUNT ON;
BEGIN
SELECT Distinct ID, Code
FROM ABC
WHERE Code NOT LIKE '%ABC%
ORDER BY ID
END

looping through recordset in stored procedure

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

Replicate SQL row with same data but not defining all columns

Is it possible to do a SQL query where I can take let's say all columns form the row for user 'A' and copy them into row for user 'B' without defining the column names.
For an Example, this will not be against speed or intense data, but to help these tasks be functional instead of doing them redundantly over and over. The params for base user and target user would be the stored procedure params.
Declare #BaseUserId varchar(50),
#TargetUserId varchar(50),
#ColumnName varchar(100)
Declare columnNameCursor Cursor For SELECT c.name
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('dbo.EmployeeMenuAccess')
--Opens the cursor now for loop reading
Open columnNameCursor
Fetch next From columnNameCursor into #ColumnName
While ##Fetch_Status=0 Begin
update DocSS set #ColumnName = (select #ColumnName from DocSS where
Username = #BaseUserId) where Username = #TargetUserID
Fetch next From c into #ColumnName
End
Close columnNameCursor
Deallocate columnNameCursor
Thanks in advance.
CREATE TABLE Test
(id int, name char(10))
;
INSERT INTO Test VALUES(1, 'first');
INSERT INTO Test VALUES(2, 'second');
BEGIN TRAN T1;
SELECT * INTO Temp FROM Test WHERE id = 1;
UPDATE Temp SET id = (SELECT MAX(id)+1 FROM Test);
INSERT INTO Test SELECT * FROM Temp;
DROP TABLE Temp;
COMMIT TRAN T1;
SELECT * FROM Test;
Try this

update trigger get the updated primary key

I have a trigger ,but I need to get the updated record's primary key (like as inserting the data SELECT #Id= ##IDENTITY) thus, I can pass it to where condition. How can I do that?
ALTER TRIGGER [dbo].[CariBakiyeBorcAktar]
ON [dbo].[BakimKartiDegisenParcalar]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id int
DECLARE #CariId int
DECLARE #SId int
DECLARE #MId int
declare #Tutar decimal
declare #Bakiye decimal
declare #s decimal = 0
DECLARE #ParcaId int
--how I can I get the last updateed record Identity like this??
--and pass it to update query as a where condition
SELECT #Id= ##IDENTITY
set #SId=(select SId from CariBakiye where Id =#Id)
select #CariId=tblk.CariId ,#MId=tblk.MId, #SId= tblk.SId,#Tutar=tblk.Tutar from (
SELECT tbl.CariId , tbl.MId,tbl.SId,tbl.Tutar from (select cb.MId,SUM(bk.Tutar) as Tutar,bk.SId,cb.Id as CariId FROM [BakimKartiDegisenParcalar] bk
join CariBakiye cb on cb.SId=bk.SId
where bk.SId =cb.SId group by bk.SId,cb.MId,cb.Id ) as tbl
) as tblk where SId = #SId
set #Bakiye = #s-#Tutar
update CariBakiye set Borc=#Tutar,Bakiye=#Bakiye where Id=#CariId
print #Id
-- Insert statements for trigger here
END
As Martin said, you have to understand that SQL Server triggers are per statement, not per row. So in context of your trigger you have two tables - inserted and deleted, where you could find all information about data updated. If you really want to do per row processing, you could use cursor:
ALTER TRIGGER [dbo].[CariBakiyeBorcAktar] ON [dbo].[BakimKartiDegisenParcalar]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id int
DECLARE #CariId int
DECLARE #SId int
DECLARE #MId int
declare #Tutar decimal
declare #Bakiye decimal
declare #s decimal = 0
DECLARE #ParcaId int
declare tr_cursor cursor local fast_forward for
select ID from inserted
while 1 = 1
begin
fetch tr_cursor into #Id
if ##fetch_status <> 0 break
set #SId=(select SId from CariBakiye where Id =#Id)
select #CariId=tblk.CariId ,#MId=tblk.MId, #SId= tblk.SId,#Tutar=tblk.Tutar from (
SELECT tbl.CariId , tbl.MId,tbl.SId,tbl.Tutar from (select cb.MId,SUM(bk.Tutar) as Tutar,bk.SId,cb.Id as CariId FROM [BakimKartiDegisenParcalar] bk
join CariBakiye cb on cb.SId=bk.SId
where bk.SId =cb.SId group by bk.SId,cb.MId,cb.Id ) as tbl
) as tblk where SId = #SId
set #Bakiye = #s-#Tutar
update CariBakiye set Borc=#Tutar,Bakiye=#Bakiye where Id=#CariId
print #Id
-- Insert statements for trigger here
end
close tr_cursor
deallocate tr_cursor
END