I have a stored procedure which takes a single parameter containing single value.
I want to pass a collection of values to the procedure one by one and get the combined result into one table . Is this possible ?
Currently I am using cursor to execute procedure in loop but only result from passing first value in the collection is obtained.
declare #clientid varchar(10)
create table #tmpp(secid varchar(10))
insert into #tmpp values(2319)
insert into #tmpp values(2855)
insert into #tmpp values(1303)
declare cur CURSOR LOCAL for
select secid from #tmpp
open cur
fetch next from cur into #seclientid
while ##FETCH_STATUS = 0 BEGIN
exec getReportforclient #clientid
fetch next from cur into #clientid
END
close cur
deallocate cur
drop table #tmpp
If this is too obfuscated / unclear/ silly, can somebody please provide me an alternative ?
Any help is most appreciated . Thanks.
There probably is a way to this without using cursors, but without taking a look at your stored procedure we can't help too much on that. You can create a table (temporary or not) that has the same structure that the results of your sp and insert the results into it. Something like this:
DECLARE #clientid VARCHAR(10)
CREATE TABLE #tmpp(secid VARCHAR(10))
INSERT INTO #tmpp VALUES(2319)
INSERT INTO #tmpp VALUES(2855)
INSERT INTO #tmpp VALUES(1303)
CREATE TABLE #Results(col1 INT, col2.... -- create the table that will hold your
-- results
DECLARE cur CURSOR LOCAL for
SELECT secid
FROM #tmpp
OPEN cur
FETCH NEXT FROM cur INTO #seclientid
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #Results
exec getReportforclient #clientid
FETCH NEXT FROM cur INTO #clientid
END
CLOSE cur
DEALLOCATE cur
DROP TABLE #tmpp
SELECT *
FROM #Results
Loop without CURSOR
IF OBJECT_ID('tempdb.dbo.#tmpp') IS NOT NULL DROP TABLE #tmpp
CREATE TABLE #tmpp(Clientid varchar(10))
INSERT #tmpp values(2319), (2855), (1303)
IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results(--output columns of procedure)
DECLARE #Clientid int = (SELECT MIN(Clientid) FROM #tmpp)
WHILE (#Clientid IS NOT NULL)
BEGIN
INSERT INTO #Results
EXEC getReportforclient #Clientid
SELECT #Clientid = MIN(Clientid) FROM #tmpp WHERE Clientid > #Clientid
END
Simple example on SQLFiddle
Related
Declare Userrole_Cursor Cursor For
Select (User_Role_id,
Pos_entity_Id,
User_role_code,
User_Role_description,
Print_Sequence,
Update_date,
Tx_id,
Add_date,
Add_Username,
Update_Username,
Active_Flag) from User_Role_Tb where pos_entity_id = (pos_entity_id)
Open Cursor
FETCH NEXT FROM UserRole_Cursor into
the above is the Cursor creation i have written, now need to insert in all the mentioned columns in a User_role_tb. please help. this is the first time i am using cursor.
This simple example can help you
-- assume this is your table
create table #tmp (MyDbName varchar(100), MyDbId int, MyStatus int)
-- you need to have a variable for each field.
DECLARE #MyDbName varchar(100)
DECLARE #MyDbId int
DECLARE #MyDbStatus int
DECLARE db_cursor CURSOR FOR
SELECT name, [dbid], [status]
FROM master.dbo.sysdatabases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #MyDbName, #MyDbId, #MyDbStatus
WHILE ##FETCH_STATUS = 0
BEGIN
-- insert data into your table using variables
insert into #tmp (MyDbName, MyDbId, MyStatus)
values (#MyDbName, #MyDbId, #MyDbStatus)
-- fetch next row from cursor
FETCH NEXT FROM db_cursor INTO #MyDbName, #MyDbId, #MyDbStatus
END
CLOSE db_cursor
DEALLOCATE db_cursor
-- select from your table to make sure data is there
select * from #tmp
I want to create a SP that have 2 String parameters for 2 table names. In the SP I use dynamic SQL to modify one of the tables, but the other is inside a cursor, and I cant use dynamic SQL after the "FOR"
ALTER PROCEDURE NameProcedure #SourceTable VARCHAR(100),#DestinationTable VARCHAR(100)
AS
BEGIN
DECLARE #AddressSource VARCHAR(100), #AddressDestination VARCHAR(100)
SELECT #AddressSource = '[Test_Toa].[dbo].[' + #SourceTable + ']'
SELECT #AddressDestination = '[Test_Toa].[dbo].[' + #DestinationTable + ']'
--Source Table columns
DECLARE #id int, #idmercado int, #idcadena int, #barcode nvarchar(255),#Complete_P nvarchar(MAX)
DECLARE #Cursor CURSOR
SET #Cursor = CURSOR FOR
--HEREE ITS MY PROBLEM :(!!!!!
SELECT id, idmercado, idcadena, barcode, precios + ',' FROM #AddressSource
OPEN #Cursor
FETCH NEXT
FROM #Cursor INTO #id,#idmercado,#idcadena,#barcode,#Complete_P
WHILE ##FETCH_STATUS = 0
BEGIN
--bla bla code
FETCH NEXT
FROM #Cursor INTO #id,#idmercado,#idcadena,#barcode,#Complete_P
END
CLOSE #Cursor
DEALLOCATE #Cursor
END
I just want to declare a cursor for the table that the user gives
Well, you need to write a dynamic sql statement. Just as an hint. You can copy the values from your given source table into a temp table, generate a cursor on the temp table, iterate through it and deallocate the cursor afterwards and drop the temp table. :-)
Here a short demo code:
DECLARE #sql nvarchar(max), #sourceTable nvarchar(255)
CREATE TABLE dbo.t1(id int, name nvarchar(200))
CREATE TABLE dbo.t2(id int, name nvarchar(200))
SET #sourceTable = N'dbo.t1'
CREATE TABLE #temp(id int, name nvarchar(200))
SET #sql = N'
INSERT INTO #temp(id,name)
SELECT id, name
FROM '+#sourceTable
EXEC(#sql)
DECLARE cur CURSOR FOR
SELECT id, name
FROM #temp
OPEN cur
DECLARE #id int, #name nvarchar(200)
FETCH NEXT FROM cur INTO #id, #name
WHILE ##fetch_status = 0 BEGIN
SELECT #id, #name -- demo output
FETCH NEXT FROM cur INTO #id, #name
END
-- cleanup
CLOSE cur
DEALLOCATE cur
DROP TABLE dbo.t1
DROP TABLE dbo.t2
DROP TABLE #temp
Beware, I just have written this in notepad without any database. But I'm quite sure it does it's job.
This just works if all available variants of #sourceTable have the same column specification. If not, you need to extract the needed columns from information schema and build a more dynamic code.
I need help with writing stored procedure that calls another stored procedure and passes values to it. So far this was done in C#, now I want to move it to stored procedure and make an SQL agent job that calls it at specific time. Any ideas? This is the case.
Table A:
PK_TableA_ID
Table B:
PK_TableB_ID
Stored procedure SP1:
#TableA_ID
#TableB_ID
I need this but in T-SQL
foreach(var TableAId in TableA)
{
foreach(var TableBId in TableB)
{
//call stored procedure
SP1(TableAId, TableBId);
}
}
Here's an example of how you can use cursors to do loops:
-- set up some test data
declare #table_a table (PK_TableA_ID int)
declare #table_b table (PK_TableB_ID int)
insert #table_a values (1),(2),(3)
insert #table_b values (4),(5),(6)
-- do the actual processing
SET NOCOUNT ON
DECLARE #TableA_ID int, #TableB_ID int
DECLARE TableA_cursor CURSOR FOR SELECT PK_TableA_ID FROM #table_a
OPEN TableA_cursor
FETCH NEXT FROM TableA_cursor INTO #TableA_ID
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE TableB_cursor CURSOR FOR SELECT PK_TableB_ID FROM #table_b
OPEN TableB_cursor
FETCH NEXT FROM TableB_cursor INTO #TableB_ID
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT CAST(#TableA_ID AS CHAR(1)) + ':' + CAST(#TableB_ID AS CHAR(1))
-- execute your stored procedure here:
-- EXEC Your_stored_procedure (#TableA_ID, #TableB_ID)
FETCH NEXT FROM TableB_cursor INTO #TableB_ID
END
CLOSE TableB_cursor
DEALLOCATE TableB_cursor
FETCH NEXT FROM TableA_cursor INTO #TableA_ID
END
CLOSE TableA_cursor
DEALLOCATE TableA_cursor
The cursor above (with the test data in the temporary tables) will generate this output:
1:4
1:5
1:6
2:4
2:5
2:6
3:4
3:5
3:6
Using cursors might not be the best way to solve your problem though.
I have a clean and clear option without cursors for this case using the table ids.
DECLARE
#Counter1 INT,#MaxId1 INT,
#Counter2 INT, #MaxId2 INT
SELECT #Counter1 = min(PK_TableA_ID) , #MaxId1 = max(PK_TableA_ID)
FROM TableA
SELECT #Counter2 = min(PK_TableB_ID) , #MaxId2 = max(PK_TableB_ID)
FROM TableB
WHILE(#Counter1 IS NOT NULL AND #Counter1 <= #MaxId1)
BEGIN
WHILE(#Counter2 IS NOT NULL AND #Counter2 <= #MaxId2)
BEGIN
//call stored procedure
SP1(#Counter1, #Counter2);
SET #Counter2 = #Counter2 + 1
END;
SELECT #Counter2 = min(PK_TableB_ID) , #MaxId2 = max(PK_TableB_ID)
FROM TableB
SET #Counter1 = #Counter1 + 1
END;
I'm trying to create table using statements stored in table. I'm using a cursor with execute(sql) as below:
create table tab
(
CreateSql varchar(250)
)
insert into tab values ('create table tab1 (id int )')
insert into tab values ('create table tab2 (id int )')
insert into tab values ('create table tab3 (id int )')
declare cur cursor for
select createsql
from tab
declare #sql varchar(255)
open cur
fetch cur into #sql
while ##SqlStatus = 0
begin
execute(#Sql)
fetch cur into #sql
end
close cur
deallocate cursor cur
If I run it then appears an error :
Could not execute statement. Cursor not open SQLCODE=-180, ODBC 3
State="34000"
The first table (tab1) will create, but other (tab2, tab3) tables not.
If I replace statement execute(sql) with select sql, script will work correctly.
Thanks in advance for your answer.
PX
IQ likes to close the cursor after the first commit.
You need to use the WITH HOLD clause (or something along those lines) to keeps the cursor open.
Why dont you do it with while loop.using Cursor is overkill in these scenarios.
I am not familiar with sybase syntax but in SQL Server 2008 you can do like this
create table tab
(
CreateSql varchar(250)
,ID int IDENTITY(1,1)
)
insert into tab values ('create table tab1 (id int )')
insert into tab values ('create table tab2 (id int )')
insert into tab values ('create table tab3 (id int )')
DECLARE #max INT = (SELECT MAX(ID) FROM tab)
,#index int =1
,#sql varchar(255)
while (#index<= #max )
begin
select #sql= createsql from tab WHERE ID=#index
execute(#Sql)
SET #index = #index+1
end
I'm not a sybase expert but it looks like you missing next on the fetch statement.
fetch next cur into #sql
I'm trying to put the results of a stored procedure into a cursor to use within the current procedure. I've added my code below but I'm not sure if this is possible or if my syntax is correct?
DECLARE cursorIDList CURSOR FOR
EXEC spGetUserIDs
OPEN cursorIDList
FETCH NEXT FROM cursorIDList INTO #ID
I receive the following error: Incorrect syntax near 'EXEC'. Expecting SELECT, '(' or WITH.
Thanks in advance.
You can do it like this:
DECLARE #t TABLE (ID INT)
INSERT INTO #t
EXEC spGetUserIDs
DECLARE cursorIDList CURSOR FOR
SELECT * FROM #t
OPEN cursorIDList
FETCH NEXT FROM cursorIDList INTO #ID
in my opinion very interesting approach would be to use cursor as parameter (although if you not going to update table i don't think its better choice):
create Table dbo.MyTable
(
i int
);
Insert Into dbo.MyTable (i) values (1)
Insert Into dbo.MyTable (i) values (2)
Insert Into dbo.MyTable (i) values (3)
Insert Into dbo.MyTable (i) values (4)
Go
Set NoCount ON;
Go
Create Proc dbo.myProc
(
#someValue int,
#cur Cursor Varying Output
)
As
Begin
declare #x int;
Set #cur = Cursor for
Select i From dbo.MyTable
Where i < #someValue;
open #cur
End
Go
-- Use of proc
declare #cur cursor;
declare #x int;
Exec dbo.myProc 3, #cur output
fetch next from #cur into #x
while ##fetch_status = 0
begin
print 'value: ' + cast(#x as varchar)
fetch next from #cur into #x
end
close #cur;
Deallocate #cur;
Go
--Cleanup
Drop Proc dbo.myProc
Drop Table dbo.MyTable
The syntax of cursor in SQL-Server is:
DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSOR FOR select_statement
After FOR you must write a SELECT.
For more info see:
https://msdn.microsoft.com/it-it/library/ms180169.aspx