Sql cursor and stored procedure - sql-server

I have a stored procedure. There is 3 biggest record date in order table. I want to read the IDs one by one and send a stored procedure, but it gives an error.
BEGIN TRAN
exec trn_siparis_insert 'Database',348
DECLARE #ID uniqueidentifier
DECLARE SIPARIS CURSOR FOR
Select id from TABLE.dbo.siparis where kayit_tarihi = (SELECT MAX(kayit_tarihi) FROM TABLE.dbo.siparis );
OPEN SIPARIS
FETCH NEXT FROM SIPARIS INTO #ID
WHILE ##FETCH_STATUS =0
BEGIN
BEGIN TRAN
exec trn_boyutlu_siparis_olustur #siparis_id=#ID, #TargetDb='Database'
FETCH NEXT FROM SIPARIS INTO #ID
END
CLOSE SIPARIS
DEALLOCATE SIPARIS
COMMIT TRAN

BEGIN TRAN should be moved to just before the WHILE:
DECLARE #ID uniqueidentifier
DECLARE SIPARIS CURSOR FOR
Select id from TABLE.dbo.siparis where kayit_tarihi = (SELECT MAX(kayit_tarihi) FROM TABLE.dbo.siparis );
OPEN SIPARIS
FETCH NEXT FROM SIPARIS INTO #ID
BEGIN TRAN
WHILE ##FETCH_STATUS =0
BEGIN
exec trn_boyutlu_siparis_olustur #siparis_id=#ID, #TargetDb='Database'
FETCH NEXT FROM SIPARIS INTO #ID
END
COMMIT TRAN
CLOSE SIPARIS
DEALLOCATE SIPARIS

Related

Cursorfetch: The number of variables declared in the INTO list must match that of selected columns in SQL Server 2012

I created a stored procedure that validates certain columns given a table as parameter and decided to use Cursor. But I am getting this cursor fetch error when trying to execute the stored procedure.
I already double checked the columns and it matches the number of variables in INTO list. I tried modifying the stored procedure by writing this
SELECT Lot, ItemId, PO, Status, ErrorDetails
FROM Table1
instead of
SELECT #SQLSTATEMENT
after
SET #MyCursor = CURSOR FOR
and it works fine. But I want the source table to be a parameter so this won't work for me. Any ideas?
CREATE PROCEDURE [dbo].[ValidateData]
#TABLENAME_PARAM NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #MyCursor CURSOR;
DECLARE #CustomerLot NVARCHAR(100),
#DeviceName NVARCHAR(100),
#PO NVARCHAR(100),
#Status NVARCHAR(1),
#ErrorDetails NVARCHAR(250);
DECLARE #TABLENAME NVARCHAR(100);
DECLARE #SQLSTATEMENT AS NVARCHAR(MAX);
SELECT #TABLENAME = Quotename (TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TABLENAME_PARAM
SET #SQLSTATEMENT = 'Select Lot, ItemId, PO, Status, ErrorDetails FROM ' + #TABLENAME + ' WHERE Status = ''N'''
BEGIN
SET #MyCursor = CURSOR FOR
SELECT #SQLSTATEMENT
OPEN #MyCursor
FETCH NEXT FROM #MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRAN
--some validations here
COMMIT TRAN
FETCH NEXT FROM #MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
END;
CLOSE #MyCursor;
DEALLOCATE #MyCursor;
END
END
GO
Try this-
CREATE PROCEDURE [dbo].[ValidateData] #TABLENAME_PARAM NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
--DECLARE #MyCursor CURSOR;
DECLARE
#CustomerLot NVARCHAR(100),
#DeviceName NVARCHAR(100),
#PO NVARCHAR(100),
#Status NVARCHAR(1),
#ErrorDetails NVARCHAR(250);
DECLARE #TABLENAME NVARCHAR(100);
DECLARE #SQLSTATEMENT AS NVARCHAR(MAX);
SELECT #TABLENAME = Quotename (TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TABLENAME_PARAM
SET #SQLSTATEMENT = 'DECLARE MyCursor CURSOR FOR Select Lot, ItemId, PO, Status, ErrorDetails FROM ' + #TABLENAME + ' WHERE Status = ''N'''
EXEC sp_executesql #sqlstatement
OPEN MyCursor
FETCH NEXT FROM MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRAN
--some validations here
COMMIT TRAN
FETCH NEXT FROM MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
END;
CLOSE MyCursor;
DEALLOCATE MyCursor
END
END
GO

tsql nested cursor does not do a properly rollback continue

I have the following script which works fine:
DECLARE db_cursor1 CURSOR LOCAL FOR
SELECT ID, Name table_1
OPEN db_cursor1
FETCH NEXT FROM db_cursor1 INTO #ID, #Name
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION
BEGIN TRY
<insert into table values>
COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
ROLLBACK TRANSACTION
END CATCH
FETCH NEXT FROM db_cursor1 INTO #ID, #Name
END
CLOSE db_cursor1
DEALLOCATE db_cursor1
The above script works fine in that it rolls back what is in the current iteration of db_cursor1 and then proceeds to the next iteration in case there is an error.
The problem arises when I have a nested cursor. It rolls back what is in the current iteration but DOES NOT proceed to the next iteration of cursor1.
DECLARE db_cursor1 CURSOR LOCAL FOR
SELECT ID, Name table_1
OPEN db_cursor1
FETCH NEXT FROM db_cursor1 INTO #ID, #Name
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION
BEGIN TRY
<insert into table values>
--- inner cursor
DECLARE db_cursor2 CURSOR LOCAL FOR
SELECT ID, Name table_2
OPEN db_cursor2
FETCH NEXT FROM db_cursor2 INTO #ID, #Name
WHILE ##FETCH_STATUS = 0
BEGIN
<insert into table values>
FETCH NEXT FROM db_cursor2 INTO #ID, #Name
END
CLOSE db_cursor2
DEALLOCATE db_cursor2
COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
ROLLBACK TRANSACTION
END CATCH
FETCH NEXT FROM db_cursor1 INTO #ID, #Name
END
CLOSE db_cursor1
DEALLOCATE db_cursor1
I was able to create it on my end with basic values, please see SCRIPT #1 - ERROR if you'd like to test it. The issue that you're running into is that when you have an error in db_cursor2, you exit the loop without closing or deallocating the cursor. Then when the code goes to next iteration, it fails with this error A cursor with the name 'db_cursor2' already exists. Please see SCRIPT #2 - SUCCESS for correct results. To give it more color, you needed to add CLOSE db_cursor2; DEALLOCATE db_cursoe2; in your BEGIN CATCH.
SETUP, Designed for SQL Server 2016+
DROP TABLE IF EXISTS #table_1, #table_2
CREATE TABLE #table_1
(
[ID] INT,
[Name] VARCHAR(5)
);
CREATE TABLE #table_2
(
[ID] INT,
[NAME] VARCHAR(5)
);
INSERT INTO #table_1 SELECT 1, 'j';
INSERT INTO #table_1 SELECT 2, 'j';
INSERT INTO #table_2 SELECT 1, 'j';
INSERT INTO #table_2 SELECT 2, 'j';
SCRIPT #1 - ERROR
DECLARE #ID INT;
DECLARE #name VARCHAR(5);
DECLARE db_cursor1 CURSOR LOCAL FOR SELECT [ID], [Name] FROM #table_1;
OPEN db_cursor1;
FETCH NEXT FROM db_cursor1
INTO #ID, #name;
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION;
BEGIN TRY
PRINT('trying 1')
--- inner cursor
DECLARE db_cursor2 CURSOR LOCAL FOR SELECT [ID], [Name] FROM #table_2;
OPEN db_cursor2;
FETCH NEXT FROM db_cursor2
INTO #ID, #name;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT('trying 2')
SELECT 1/0
FETCH NEXT FROM db_cursor2
INTO #ID, #name;
END;
CLOSE db_cursor2;
DEALLOCATE db_cursor2;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
ROLLBACK TRANSACTION;
END CATCH;
FETCH NEXT FROM db_cursor1
INTO #ID, #name;
END;
CLOSE db_cursor1;
DEALLOCATE db_cursor1;
SCRIPT #2 - SUCCESS
DECLARE #ID INT;
DECLARE #name VARCHAR(5);
DECLARE db_cursor1 CURSOR LOCAL FOR SELECT [ID], [Name] FROM #table_1;
OPEN db_cursor1;
FETCH NEXT FROM db_cursor1
INTO #ID, #name;
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION;
BEGIN TRY
PRINT('trying 1')
--- inner cursor
DECLARE db_cursor2 CURSOR LOCAL FOR SELECT [ID], [Name] FROM #table_2;
OPEN db_cursor2;
FETCH NEXT FROM db_cursor2
INTO #ID, #name;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT('trying 2')
SELECT 1/0
FETCH NEXT FROM db_cursor2
INTO #ID, #name;
END;
CLOSE db_cursor2;
DEALLOCATE db_cursor2;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
-- was missing in above script
CLOSE db_cursor2
DEALLOCATE db_cursor2
ROLLBACK TRANSACTION;
END CATCH;
FETCH NEXT FROM db_cursor1
INTO #ID, #name;
END;
CLOSE db_cursor1;
DEALLOCATE db_cursor1;
Because you are using a TRY-CATCH, if there is an error within the TRY, code execution will begin in the CATCH.
Inside your catch you would have to handle the error, and depending on the error, close and deallocate db_cursor2. Or if the error is benign, perhaps return execution back to the TRY with a GOTO. GOTO statements cannot be used to enter a TRY or CATCH block. GOTO statements can be used to jump to a label inside the same TRY or CATCH block or to leave a TRY or CATCH block.
As #paul-wehland stated, it's because your Try-Catch isn't disposing the nested cursor. As such, your next iteration is going to initialize a cursor by name that already exists. I've provided an example of code that will run your basic scenario with an intended failure condition at iteration 11 of each cursor.
In the example, I've commented out the part of the code that addresses the issue. Where you choose to place that block is totally up to you, but it would make sense to check either before the nested cursor declaration, or inside the Catch block.
declare
#id tinyint,
#parent_id tinyint,
#name varchar(255),
#parent_name varchar(255);
declare
#table
table
(
id tinyint not null primary key,
[name] varchar(255) not null
);
declare
#target
table
(
parent_id tinyint not null,
child_id tinyint not null,
parent_name varchar(10) not null,
child_name varchar(10) not null,
primary key(parent_id, child_id)
);
with cteNumber
as (
select top 11
[id] = row_number() over (order by [object_id])
from
sys.objects
)
insert into
#table
select
id,
[name] = replicate('a', id)
from
cteNumber;
declare
db_cursor1
cursor
local keyset read_only forward_only
for
select
0,
id,
'Initial',
[name]
from
#table;
open
db_cursor1;
fetch
next
from
db_cursor1
into
#id,
#parent_id,
#name,
#parent_name;
while ##FETCH_STATUS = 0
begin
begin transaction;
begin try
insert into #target
(parent_id, child_id, parent_name, [child_name])
values
(#parent_id, #id, #parent_name, #name);
--- inner cursor
/*
if CURSOR_STATUS('local', 'db_cursor2') = 1
begin
close
db_cursor2;
deallocate
db_cursor2;
end;
-- */
declare
db_cursor2
cursor
local keyset read_only forward_only
for
select
id,
[name]
from
#table;
open
db_cursor2;
fetch
next
from
db_cursor2
into
#id,
#name;
while ##FETCH_STATUS = 0
begin
insert into #target
(parent_id, child_id, parent_name, [child_name])
values
(#parent_id, #id, #parent_name, #name);
fetch
next
from
db_cursor2
into
#id,
#name;
end;
close
db_cursor2;
deallocate
db_cursor2;
commit transaction
end try
begin catch
print ERROR_MESSAGE();
rollback transaction;
end catch;
fetch
next
from
db_cursor1
into
#id,
#parent_id,
#name,
#parent_name;
end;
close
db_cursor1;
deallocate
db_cursor1;
select
[Last #id] = #id,
[Last #name] = #name,
[Last #parent_id] = #parent_id,
[Last #parent_name] = #parent_name;
select
*
from
#table;
select
*
from
#target;
EDITED
You could also use the creation of a Cursor Variable, and assign the nested cursor declaration to it, which would negate the problem of dealing with the duplicate names. See below:
declare
#id tinyint,
#parent_id tinyint,
#name varchar(255),
#parent_name varchar(255);
declare
#table
table
(
id tinyint not null primary key,
[name] varchar(255) not null
);
declare
#target
table
(
parent_id tinyint not null,
child_id tinyint not null,
parent_name varchar(10) not null,
child_name varchar(10) not null,
primary key(parent_id, child_id)
);
with cteNumber
as (
select top 11
[id] = row_number() over (order by [object_id])
from
sys.objects
)
insert into
#table
select
id,
[name] = replicate('a', id)
from
cteNumber;
declare
#db_cursor2 cursor;
declare
db_cursor1
cursor
local keyset read_only forward_only
for
select
0,
id,
'Initial',
[name]
from
#table;
open
db_cursor1;
fetch
next
from
db_cursor1
into
#id,
#parent_id,
#name,
#parent_name;
while ##FETCH_STATUS = 0
begin
begin transaction;
begin try
insert into #target
(parent_id, child_id, parent_name, [child_name])
values
(#parent_id, #id, #parent_name, #name);
--- inner cursor
set #db_cursor2 = cursor
local keyset read_only forward_only
for
select
id,
[name]
from
#table;
open
#db_cursor2;
fetch
next
from
#db_cursor2
into
#id,
#name;
while ##FETCH_STATUS = 0
begin
insert into #target
(parent_id, child_id, parent_name, [child_name])
values
(#parent_id, #id, #parent_name, #name);
fetch
next
from
#db_cursor2
into
#id,
#name;
end;
close
#db_cursor2;
deallocate
#db_cursor2;
commit transaction
end try
begin catch
print ERROR_MESSAGE();
rollback transaction;
end catch;
fetch
next
from
db_cursor1
into
#id,
#parent_id,
#name,
#parent_name;
end;
close
db_cursor1;
deallocate
db_cursor1;
select
[Last #id] = #id,
[Last #name] = #name,
[Last #parent_id] = #parent_id,
[Last #parent_name] = #parent_name;
select
*
from
#table;
select
*
from
#target;

Check if record exists, if yes “update” if not “insert” using cursor sql server

I have this trigger that after insert update and insert data in a table, using the if as paramter for the insert or update, at the same time i have another trigger after update that changes another register. The problem is that the first trigger when does the update it trigger the update trigger... So occours that I had to protect the first trigger by checking if there´s a register there before the insert BUT I have a cursor to insert the data in the middle of all this, after I did checking the insert of one register occurs BUT the others inside the cursor aren´t inserted in the table just one register of the list in the cursor... I cannot find the problem, please help...
this is my trigger:
ALTER TRIGGER [dbo].[tr_inclusao_dupla] ON [dbo].[tb_patrimonio]
AFTER INSERT
AS
BEGIN
begin try
IF EXISTS (SELECT * FROM INSERTED) AND EXISTS (SELECT * FROM DELETED)
BEGIN
declare #id as int
declare #count as int
declare #qtd as int
declare #emlote as bit
declare #nr_serie as varchar(100)
declare #nr_patrimonio as varchar(100)
declare #dm_identificado as bit
declare #nr_inventario as varchar(100)
set #nr_patrimonio = (select nr_patrimonio_efetivo from inserted)
set #nr_serie = (select nr_serie from inserted)
set #nr_inventario = (select nr_inventario from inserted)
/*single insert*/
if (#nr_patrimonio is not null or #nr_serie is not null or #nr_inventario is not null)
begin
set #emlote =0
declare registros cursor for
select cd_patrimonio , nr_qtd_lote,nr_serie, nr_patrimonio_efetivo from inserted
open registros
fetch next from registros into #id, #qtd, #nr_serie, #nr_patrimonio
while( ##fetch_status = 0)
begin
set #dm_identificado = 1
update tb_patrimonio set dm_identificado = #dm_identificado, dm_em_lote = #emlote
where cd_patrimonio = #id
end
fetch next from registros into #id, #qtd,#nr_serie, #nr_patrimonio
close registros
deallocate registros
end
END
ELSE
BEGIN
/*multiple insert*/
begin
set #emlote =0
set #dm_identificado = 0
declare registros2 cursor for
select cd_patrimonio , nr_qtd_lote,nr_serie, nr_patrimonio_efetivo from inserted
open registros2
fetch next from registros2 into #id, #qtd, #nr_serie, #nr_patrimonio
while( ##fetch_status = 0)
begin
print #qtd
set #count = 1
update tb_patrimonio set dm_identificado = #dm_identificado, dm_em_lote = #emlote
where cd_patrimonio = #id
while (#count <= (#qtd-1))
begin
INSERT INTO [dbo].[tb_patrimonio]
([dm_patrimonio]
,[dm_em_lote]
,[nr_qtd_lote]
,[cd_grupo_produto]
,[nm_patrimonio]
,[nr_patrimonio_efetivo]
,[nr_patrimonio_antigo]
,[nr_serie]
,[ds_descricao]
,[nr_lacre]
,[cd_barra]
,[dm_tipo_entrada]
,[nr_garantia]
,[cd_nota_fiscal]
,[ds_garantia]
,[img_patrimonio]
,[cd_situacao_patrimonio]
,[cd_orgao]
,[cd_local]
,[dm_situacao]
,[cd_usuario_inc]
,[cd_estado_patrimonio]
,[cd_tipo_posse]
,[cd_usuario_alt]
,[dt_alteracao]
,[cd_usuario]
,[dt_inclusao]
,[cd_estado_equipamento]
,[cd_fornecedor]
,[nr_termo]
,[img_termo]
,[dm_identificado]
,[dt_instalacao_equipamento]
,[nr_inventario])
SELECT
[dm_patrimonio]
,#emlote
,[nr_qtd_lote]
,[cd_grupo_produto]
,[nm_patrimonio]
,[nr_patrimonio_efetivo]
,[nr_patrimonio_antigo]
,[nr_serie]
,[ds_descricao]
,[nr_lacre]
,[cd_barra]
,[dm_tipo_entrada]
,[nr_garantia]
,[cd_nota_fiscal]
,[ds_garantia]
,[img_patrimonio]
,[cd_situacao_patrimonio]
,[cd_orgao]
,[cd_local]
,[dm_situacao]
,[cd_usuario_inc]
,[cd_estado_patrimonio]
,[cd_tipo_posse]
,[cd_usuario_alt]
,[dt_alteracao]
,[cd_usuario]
,[dt_inclusao]
,[cd_estado_equipamento]
,[cd_fornecedor]
,[nr_termo]
,[img_termo]
,#dm_identificado
,[dt_instalacao_equipamento]
,[nr_inventario]
FROM inserted where cd_patrimonio = #id
set #count = #count + 1
end
fetch next from registros2 into #id, #qtd,#nr_serie, #nr_patrimonio
end
close registros2
deallocate registros2
end
END
end try
begin catch
declare #errormessage nvarchar(4000)
declare #errorseverity int
declare #errorstate int
select
#errormessage = ERROR_MESSAGE(),
#errorseverity = ERROR_SEVERITY(),
#errorstate = ERROR_STATE()
raiserror (
#errormessage,
#errorseverity,
#errorstate
)
end catch end

SQL Trigger Error -

I am trying to develop one trigger, but I seem to be getting the following error:
A cursor with the name 'CONTACT_CURSOR' does not exist. 5339B6CC-5480-4B24-AC5D-3A4C0EAF64EC 3F0F445B-7BA3-4311-944A-E372D41FD307 The statement has been terminated.
Here is the trigger I am trying to develop:
USE [124959test]
GO
/****** Object: Trigger [dbo].[TRG_AUTOCAMPAIGN_Based_on_IDStatus_Value_Latest] Script Date: 05/28/2015 10:48:50 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRG_AUTOCAMPAIGN_Based_on_IDStatus_Value_Latest]
ON [dbo].[SN_Contact2]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF (UPDATE(contact_category)) -- selector field is the one that determines if an action shou dbe taken
BEGIN
DECLARe #CAMPAIGNSTARTTIME datetime
DECLARE #DELETEOLD INT
DECLARE #TRIGGERFIELD VARCHAR(100)
DECLARE #USERID VARCHAR(36)
DECLARE #CONTACTID VARCHAR(36)
DECLARE #CAMPAIGNID VARCHAR(36)
DECLARE #SCHEDULEFOR VARCHAR(36)
DECLARE #COMMINGLE VARCHAR(100)
DECLARE #DROPSHIP VARCHAR(100)
DECLARE #EDDM VARCHAR(100)
DECLARE #EXPEDITEDDROPSHIP VARCHAR(100)
DECLARE #EXPEDITEDSERVICES VARCHAR(100)
DECLARE #FIRSTCLASS VARCHAR (100)
DECLARE #FLATS VARCHAR(100)
DECLARE #FREIGHTROVER VARCHAR(100)
DECLARE #INTERNATIONAL VARCHAR(100)
DECLARE #MAILROVER VARCHAR(100)
DECLARE #OBBASHIP VARCHAR(100)
DECLARE #OBBATRACK VARCHAR(100)
DECLARE #PARCEL VARCHAR(100)
DECLARE #PRODUCTION VARCHAR(100)
SELECT #DELETEOLD = 0
DECLARE CONTACT_CURSOR CURSOR FOR
SELECT Contact_ContactID, SNL_RecordManagerID,contact_category,cust_commingle,CUST_Drop_Ship,
cust_eddm,CUST_Expedited_Drop_Ship,CUST_Expedited_Services,CUST_First_Class,CUST_Flats,
CUST_Freight_Rover,CUST_International,CUST_MailRover,CUST_OBBAShip,CUST_OBBATrack,
CUST_Parcel,CUST_Production FROM inserted
--where snl_recordmanagerid = '1C42B435-4A81-4109-A008-34AE91C2D48F'
OPEN CONTACT_CURSOR
FETCH NEXT FROM CONTACT_CURSOR
INTO #CONTACTID, #USERID, #TRIGGERFIELD, #COMMINGLE, #DROPSHIP, #EDDM, #EXPEDITEDDROPSHIP, #EXPEDITEDSERVICES,
#FIRSTCLASS, #FLATS, #FREIGHTROVER, #INTERNATIONAL, #MAILROVER, #OBBASHIP, #OBBATRACK, #PARCEL, #PRODUCTION
WHILE ##FETCH_STATUS = 0
BEGIN
IF #TRIGGERFIELD = 'Client' AND #USERID = '5339B6CC-5480-4B24-AC5D-3A4C0EAF64EC'
--or #USERID = '277D668E-F18F-48E7-B7C1-2FDCF50F1B36'
--or #USERID = '7FF6E867-8DDA-47FE-9A2F-E7E042FFAC56'
/* This is to launch the New Client Workflow*/
BEGIN
SET #CAMPAIGNID = 'D25053D9-EF07-4184-98F5-EC6DB1814B7E' -- CampaignID of the New client Campaign
SET #Campaignstarttime = getdate()
EXEC usp_AssignCampaign #CONTACTID, #USERID, #CAMPAIGNID, #DELETEOLD, #CAMPAIGNSTARTTIME
/* This is to launch the Send Welcome Package Workflow*/
SET #CAMPAIGNID = '08118AC6-456B-4BEC-BD09-F09A0FDC893D' -- CampaignID of the Welcome Package Campaign.
SET #Campaignstarttime = getdate()
SET #USERID = '9E283EF8-208F-4A60-BACA-555F3BECEBAB' -- The UserID of to whom the to-do task will be scheduled to.
EXEC usp_AssignCampaign #CONTACTID, #USERID, #CAMPAIGNID, #DELETEOLD, #CAMPAIGNSTARTTIME
END
ELSE
BEGIN
IF #TRIGGERFIELD = 'Prospect'
BEGIN
--Update sn_contact2 set cust_newsletter = Yes' -- When ID/Status = Prospect/Hot Prospect update Newsletter field to Yes.
SET #CAMPAIGNID = 'B1649041-FB74-40D1-807C-F969D8AE4D40' -- CampaignID of the Opt-out Email with LinkedIn Follow Up Campaign
SET #Campaignstarttime = getdate()
EXEC usp_AssignCampaign #CONTACTID, #USERID, #CAMPAIGNID, #DELETEOLD, #CAMPAIGNSTARTTIME
END
ELSE
BEGIN
IF #TRIGGERFIELD = 'Hot Prospect'
BEGIN
--Update sn_contact2 set cust_newsletter = Yes' -- When ID/Status = Prospect/Hot Prospect update Newsletter field to Yes.
SET #CAMPAIGNID = 'B1649041-FB74-40D1-807C-F969D8AE4D40' -- CampaignID of the Opt-out Email with LinkedIn Follow Up Campaign
SET #Campaignstarttime = getdate()
EXEC usp_AssignCampaign #CONTACTID, #USERID, #CAMPAIGNID, #DELETEOLD, #CAMPAIGNSTARTTIME
end
end
FETCH NEXT FROM CONTACT_CURSOR
INTO #CONTACTID, #USERID, #TRIGGERFIELD, #COMMINGLE, #DROPSHIP, #EDDM, #EXPEDITEDDROPSHIP, #EXPEDITEDSERVICES,
#FIRSTCLASS, #FLATS, #FREIGHTROVER, #INTERNATIONAL, #MAILROVER, #OBBASHIP, #OBBATRACK, #PARCEL, #PRODUCTION
END
CLOSE CONTACT_CURSOR
DEALLOCATE CONTACT_CURSOR
END
end
end
Any thoughts?
I think you have an END in the wrong place. It's pushing your Fetch Next out of scope of your Cursor declaration. Try amending the end of your code to the following...
BEGIN
--Update sn_contact2 set cust_newsletter = Yes' -- When ID/Status = Prospect/Hot Prospect update Newsletter field to Yes.
SET #CAMPAIGNID = 'B1649041-FB74-40D1-807C-F969D8AE4D40' -- CampaignID of the Opt-out Email with LinkedIn Follow Up Campaign
SET #Campaignstarttime = getdate()
EXEC usp_AssignCampaign #CONTACTID, #USERID, #CAMPAIGNID, #DELETEOLD, #CAMPAIGNSTARTTIME
end
end
END
FETCH NEXT FROM CONTACT_CURSOR
INTO #CONTACTID, #USERID, #TRIGGERFIELD, #COMMINGLE, #DROPSHIP, #EDDM, #EXPEDITEDDROPSHIP, #EXPEDITEDSERVICES,
#FIRSTCLASS, #FLATS, #FREIGHTROVER, #INTERNATIONAL, #MAILROVER, #OBBASHIP, #OBBATRACK, #PARCEL, #PRODUCTION
END
CLOSE CONTACT_CURSOR
DEALLOCATE CONTACT_CURSOR
END
end
There are couple problems with the code. First you need to move FETCH right before END that matches BEGIN after WHILE. Next thing you need to move CLOSE and DEALLOCATE to outside.
FETCH NEXT FROM CONTACT_CURSOR
INTO #CONTACTID, #USERID, #TRIGGERFIELD, #COMMINGLE, #DROPSHIP, #EDDM, #EXPEDITEDDROPSHIP,
#EXPEDITEDSERVICES, #FIRSTCLASS, #FLATS, #FREIGHTROVER, #INTERNATIONAL, #MAILROVER,
#OBBASHIP, #OBBATRACK, #PARCEL, #PRODUCTION
END
CLOSE CONTACT_CURSOR
DEALLOCATE CONTACT_CURSOR
END
END
This is basic outline of the cursor
DECLARE Some_Cursor CURSOR
OPEN Some_Cursor
FETCH NEXT FROM Some_Cursor
WHILE ##FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM Some_Cursor
END
CLOSE Some_Cursor
DEALLOCATE Some_Cursor
Appreciate all the help guys! I have made this trigger running, after I verify it works correctly, I will then refine or restructure this so it would no longer be using contact cursors.
Appreciate the help!
Thanks again!
-Mike

Execute a Stored Procedure with OUTPUT For Each Row in SELECT Statement

Is it possible to execute a stored procedure for each row in a SELECT? This only executes the first row, looking for something to execute for all rows:
Declare
#Loop bit = 1, #ID int, #Exists bit, #ReturnValue bit = 0
WHILE (#Loop) = 1
BEGIN
SELECT #ID = ID FROM Table --Multiple Rows Returned
EXEC [dbo].[StoredProc1] --Exec SP for Each Row
#InputID = #ID
,#Exists = #Exists OUTPUT
IF #Exists = 1
BEGIN
SET #Loop = 0
SET #ReturnValue = 1
END
END
SELECT #ReturnValue [ReturnValue]
Use a cursor:
DECLARE #exists bit
DECLARE db_cursor CURSOR FOR
SELECT ID
FROM Table
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC [dbo].[StoredProc1] --Exec SP for Each Row
#ID
, #exists OUTPUT
FETCH NEXT FROM db_cursor INTO #id
END
CLOSE db_cursor
DEALLOCATE db_cursor

Resources