SQL Trigger Error - - sql-server

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

Related

While executing the stored procedure from backend(MSSQL 2012).Unable to open a few modules from pb12.5 desktop application

We have an stored procedure to transfer the data(contract data) from database 1 to database 2(interfacing with SAP to Intermeidate Database , then our database), and this contain loops and more that one table in the execution.And we have an PB12.5 desktop application with several modules like procurement,crewing, employee etc.The issue is here while executing the stored procedure from MSSQL using exec, it will take nearly 2 minutes depend on the recieved data from SAP.During the execution I'm unable to open procurement window and it is opening once the stored procedure completed the execution.The other side employee window is opening without any issue.The below are my findings/comments
Procurement module is using table1 and table2 , but in the stored procedure we are not using any of this tables.We are using table 3 and table 4(but later we will use the table from procurement module in proc)
2.While executing the proc Im able to select the tables from procurement module using select * from table1.
3.None of the table is locking from proc.
4.We have tried the same scenarios from different PC same issue exist.
5.Later we will extend the stored procedure with more tables and multiple loops(cursor)
Below are the small part of procedure(we have to extend more and it is hold now because of this issue)
Many thanks in advance.
alter PROC [spectwosuite].[CST_GENERATE_IPurchase_contract]
as begin
SET NOCOUNT ON;
/**/
--truncate table spectwosuite.CUSTOM_SAP_CONTRACT_ITEM;
--truncate table spectwosuite.CUSTOM_SAP_CONTRACT_header;
--truncate table spectwosuite.CUSTOM_SAP_PROC_LOG;
--Variable declaration
DECLARE #MATERIALNO VARCHAR(20);
DECLARE #PURCHASEDOCNO VARCHAR(20);
DECLARE #PORTID NUMERIC(15);
DECLARE #PRICE DECIMAL(11,2);
DECLARE #PKID NUMERIC(16);
DECLARE #STOCKTYPEID NUMERIC(15);
DECLARE #STOCKTYPECODE VARCHAR(50);
DECLARE #STNAME VARCHAR(50);
DECLARE #UNITID NUMERIC(15);
DECLARE #BUSFLOWID NUMERIC(15);
DECLARE #BUSSTATUSID NUMERIC(15);
DECLARE #ITEMNO VARCHAR(5);
DECLARE #SUBITEMNO VARCHAR(10);
DECLARE #STOCKDISID NUMERIC(15);
DECLARE #PURCONTRACTID NUMERIC(15);
DECLARE #REVISIONNO NUMERIC(15);
DECLARE #DESCR NVARCHAR(100);
DECLARE #ADDRESSID NUMERIC(15);
DECLARE #DELTERMSID NUMERIC(15);
DECLARE #PAYTERMSID NUMERIC(15);
DECLARE #VALIDSTART DATETIME;
DECLARE #VALIDEND DATETIME;
DECLARE #CURRENCY NCHAR(3);
DECLARE #PRODUCTGROUPID NUMERIC(15);
DECLARE #PURCONTRACTPRODUCTGROUPID NUMERIC(15);
DECLARE #MATERIALGRP NVARCHAR(20);
DECLARE #NETPRICE NUMERIC(16,6);
DECLARE #BASEPRICE NUMERIC(16,6);
DECLARE #PRODUCTGROUPLINEID NUMERIC(15);
DECLARE #SECTION VARCHAR(20);
DECLARE #PUREXIST NUMERIC(1);
DECLARE #HEADERPKID NUMERIC(16);
DECLARE #ITEMPRICE NUMERIC(16,6);
DECLARE #BASEITEMPRICE NUMERIC(16,2);
DECLARE #PURCONTRACTVARIABLEID NUMERIC(15);
DECLARE #FACTORVALUE NUMERIC(9,4);
DECLARE #ITEMPERCENTAGE NUMERIC(15,2);
DECLARE #ITEMPRICEDIFF1 NUMERIC(15,2);
DECLARE #ITEMPRICEDIFF2 NUMERIC(15,2);
DECLARE #ITEMPKID NUMERIC(16);
/*CONT1: Transfering all the portid and purchase document number to different table */
--PRINT 'CONT1 START'
--PRINT GETDATE();
BEGIN TRY
--BEGIN TRANSACTION
--BEGIN
SET #SECTION='CONT1';
BEGIN TRANSACTION CONT1
INSERT INTO SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_PORT
(PORTID
,PURCHASE_DOC_NO
)
SELECT DISTINCT PORTID,PURCHASE_DOC_NO FROM SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK) WHERE IMPORT_STATUS IS NULL and DELETION_IND NOT IN('L','1')
and portid>0 and MATERIAL_NO<>'' and FACTOR>0 and
not exists (select PORTID from SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_PORT where PORTID=SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_PORT.PORTID
and PURCHASE_DOC_NO =SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_PORT.PURCHASE_DOC_NO) ORDER BY PURCHASE_DOC_NO,PORTID ASC;
COMMIT TRANSACTION CONT1
--END
----INSERT INTO spectwosuite.CUSTOM_SAP_PROC_LOG
---- (STATUS
---- ,DESCRIPTION
---- ,PROCESSEDDATE
---- ,RECORDCOUNT)
---- VALUES
---- (1,
---- 'CONT1'
---- ,GETDATE()
---- ,##ROWCOUNT
---- );
--PRINT 'CONT1 END'
--PRINT GETDATE();
/* CONT1 END */
/*CONT2 Inserting new item which one dont have price in all ports*/
/*Variable declaration*/
--PRINT 'CONT2 START'
--PRINT GETDATE();
-- BEGIN
SET #SECTION='CONT2';
--SELECT DISTINCT CAST(MATERIAL_NO AS VARCHAR(20))AS MATERIAL_NO,PURCHASE_DOC_NO FROM SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK) WHERE PURCHASE_DOC_NO='4600000820' and IMPORT_STATUS IS NULL and MATERIAL_NO<>'' and DELETION_IND NOT IN('L','1') and len(material_no)>0 and factor>0 and portid>0 ORDER BY MATERIAL_NO,PURCHASE_DOC_NO ASC;
DECLARE CONT2CR CURSOR FOR
SELECT DISTINCT CAST(MATERIAL_NO AS VARCHAR(20))AS MATERIAL_NO,PURCHASE_DOC_NO FROM SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK) WHERE IMPORT_STATUS IS NULL and MATERIAL_NO<>'' and DELETION_IND NOT IN('L','1') and len(material_no)>0 and factor>0 and portid>0 ORDER BY MATERIAL_NO,PURCHASE_DOC_NO ASC;
OPEN CONT2CR
FETCH NEXT FROM CONT2CR INTO #MATERIALNO,#PURCHASEDOCNO
WHILE ##FETCH_STATUS=0
BEGIN
BEGIN TRAN CONT2
select #PKID=MIN(pk_id),#PRICE=MIN(NET_PRICE) from SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK) WHERE MATERIAL_NO=#MATERIALNO AND PURCHASE_DOC_NO=#PURCHASEDOCNO and IMPORT_STATUS IS NULL and DELETION_IND NOT IN('L','1') and factor>0 and portid>0;
/*Retreiving port details table*/
DECLARE CONT2PORTCR CURSOR FOR
SELECT DISTINCT portid FROM SAP_INTERFACE.spectwosuite.custom_sap_contract_port WITH(NOLOCK) WHERE (SAP_INTERFACE.spectwosuite.custom_sap_contract_port.purchase_doc_no = #PURCHASEDOCNO) and ( custom_sap_contract_port.portid > 0 ) ;
OPEN CONT2PORTCR
FETCH NEXT FROM CONT2PORTCR INTO #PORTID
WHILE #PORTID>0
BEGIN
IF #PORTID>0
BEGIN
BEGIN TRAN
/*Insert Script*/
SET #SECTION='ITEM_ADDITION';
IF (select COUNT(*) from SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK) where MATERIAL_NO=CAST(#MATERIALNO AS varchar(20)) AND PORTID=#PORTID and PURCHASE_DOC_NO=#PURCHASEDOCNO and IMPORT_STATUS IS NULL and DELETION_IND NOT IN('L','1') and factor>0 and portid>0)<=0
BEGIN
INSERT INTO SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM
(DELETION_IND,PURCHASE_DOC_NO,ITEM_NO,MATERIAL_NO,SHORT_TEXT,MATERIAL_GRP,QTY,UOM,NET_PRICE,PORTID,TEMPPORTID,FACTOR)
select DELETION_IND,PURCHASE_DOC_NO,ITEM_NO,MATERIAL_NO,SHORT_TEXT,MATERIAL_GRP,QTY,UOM,NET_PRICE,#PORTID,1252,FACTOR from SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK) WHERE pk_id=#PKID and DELETION_IND<>'1' and IMPORT_STATUS IS NULL;
END
SET #PORTID=0;
COMMIT TRAN
END
FETCH NEXT FROM CONT2PORTCR INTO #PORTID
END
CLOSE CONT2PORTCR
DEALLOCATE CONT2PORTCR
COMMIT TRAN CONT2
FETCH NEXT FROM CONT2CR INTO #MATERIALNO,#PURCHASEDOCNO
END
CLOSE CONT2CR
DEALLOCATE CONT2CR
--END
--INSERT INTO spectwosuite.CUSTOM_SAP_PROC_LOG
-- (STATUS
-- ,DESCRIPTION
-- ,PROCESSEDDATE
-- ,RECORDCOUNT)
-- VALUES
-- (1,
-- 'CONT2'
-- ,GETDATE()
-- ,##ROWCOUNT
-- );
--PRINT 'CONT2 END'
--PRINT GETDATE();
/*CONT2 END*/
/*CONT3*/
--PRINT 'CONT3 START'
--PRINT GETDATE();
SET #SECTION='CONT3';
BEGIN TRAN CONT3
INSERT INTO spectwosuite.CUSTOM_SAP_CONTRACT_HEADER
(TABLEPKID
,PURCHASE_DOC_NO
,COMPANY_CODE
,CREATED_ON_DATE
,VENDOR_CODE
,PAYMENT_TERMS
,PURCHASE_GRP
,VALIDITY_START
,VALIDITY_END
,YOUR_REFERENCE
,OUR_REFERNCE
,TARGET_AMOUNT
,CURRENCY
,DESCRIPTION
,SHIPCODE
,STATUS
,CREATEDATE
,VALIDATESTART
,VALIDATEEND
,INTERNAL_STATUS
,INTERNAL_MESSAGE
)
SELECT
PK_ID
,PURCHASE_DOC_NO
,COMPANY_CODE
,CREATED_ON_DATE
,VENDOR_CODE
,PAYMENT_TERMS
,PURCHASE_GRP
,VALIDITY_START
,VALIDITY_END
,YOUR_REFERENCE
,OUR_REFERNCE
,TARGET_AMOUNT
,CURRENCY
,DESCRIPTION
,SHIPCODE
,STATUS
,CREATEDATE
,VALIDATESTART
,VALIDATEEND
,INTERNAL_STATUS
,INTERNAL_MESSAGE
FROM SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_HEADER WITH(NOLOCK)
where import_status is null and purchase_doc_no<>'' and validity_start<>'' and validity_end<>'' and currency<>''and status>0
and not exists(select pk_id from spectwosuite.CUSTOM_SAP_CONTRACT_HEADER WHERE TABLEPKID= SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_HEADER.PK_ID)
COMMIT TRAN CONT3
--INSERT INTO spectwosuite.CUSTOM_SAP_PROC_LOG
-- (STATUS
-- ,DESCRIPTION
-- ,PROCESSEDDATE
-- ,RECORDCOUNT)
-- VALUES
-- (1,
-- 'CONT3'
-- ,GETDATE()
-- ,##ROWCOUNT
-- );
--PRINT 'CONT3 END'
--PRINT GETDATE();
/*CONT3 END*/
/*CONT4*/
--PRINT 'CONT4 START'
--PRINT GETDATE();
SET #SECTION='CONT4';
BEGIN TRAN CONT4
INSERT INTO spectwosuite.CUSTOM_SAP_CONTRACT_ITEM
(TABLEPKID,PURCHASE_DOC_NO
,ITEM_NO
,DELETION_IND
,MATERIAL_NO
,SHORT_TEXT
,MATERIAL_GRP
,QTY
,UOM
,NET_PRICE
,PORTID
,STOCKTYPEID
,INTERNAL_MESSAGE
,INTERNAL_STATUS
,CONTRACTTYPE
,AGREEMENTSUBITEMNO
,FACTOR
)
select PK_ID,PURCHASE_DOC_NO
,ITEM_NO
,DELETION_IND
,MATERIAL_NO
,SHORT_TEXT
,MATERIAL_GRP
,QTY
,UOM
,NET_PRICE
,PORTID
,STOCKTYPEID
,INTERNAL_MESSAGE
,INTERNAL_STATUS
,CONTRACTTYPE
,AGREEMENTSUBITEMNO
,FACTOR
from SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM WITH(NOLOCK)
where IMPORT_STATUS is null and MATERIAL_NO<>'' and DELETION_IND<>'L' AND PORTID>0 and FACTOR>0 and LEN(SHORT_TEXT)>0 AND LEN(PURCHASE_DOC_NO)>0 AND
not exists (select PK_ID from spectwosuite.CUSTOM_SAP_CONTRACT_ITEM where TABLEPKID= SAP_INTERFACE.spectwosuite.CUSTOM_SAP_CONTRACT_ITEM.PK_ID ) ORDER BY PK_ID ASC;
COMMIT TRAN CONT4
-- /*Inserting History*/
-- /*Transfering process status to interface table.*/
TRUNCATE TABLE spectwosuite.CUSTOM_SAP_CONTRACT_HEADER;
TRUNCATE TABLE spectwosuite.CUSTOM_SAP_CONTRACT_ITEM;
DELETE FROM spectwosuite.CUSTOM_SAP_PROC_LOG WHERE STATUS=99;
COMMIT
-- /*PURCHASE CONTRACT CREATION END*/
-- SET NOCOUNT OFF;
-- --COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE #ERRORNUMBER VARCHAR(20);
DECLARE #ERRMSG VARCHAR(MAX);
SET #ERRORNUMBER=CAST(ERROR_LINE() AS VARCHAR(20));
SET #ERRMSG=ERROR_MESSAGE();
BEGIN TRAN ER
INSERT INTO spectwosuite.CUSTOM_SAP_PROC_LOG
(STATUS
,DESCRIPTION
,PROCESSEDDATE
,RECORDCOUNT
,ERRORMSG)
VALUES
(
88,
#SECTION
,getdate()
,1
,#ERRORNUMBER +','+ #ERRMSG
);
COMMIT TRAN ER
END CATCH
END
Try to add Begin tran and commit Tran without success

Tuning Stored Procedure

How can you improve this without using a cursor? I was thinking using table variable would help, but am I going right direction doing so? I have omitted cursor and try to do it with table variable. Please help, here is the code.
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[BatchProcessBridge_CustomerEvent]') AND [xtype] IN (N'P'))
BEGIN
DROP PROCEDURE [dbo].[BatchProcessBridge_CustomerEvent]
END
GO
CREATE PROCEDURE [dbo].[BatchProcessBridge_CustomerEvent]
(
#BatchJobTable Bridge_CustomerEventBatchJobTable READONLY,
#Name VARCHAR(50)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Lsn BINARY(10),
DECLARE #SeqVal BINARY(10),
DECLARE #Action VARCHAR(300),
DECLARE #CustId VARCHAR(MAX)
--using tabel variable. Cursor gives bad performance.
DECLARE #TEMP_TABLE TABLE ( [Lsn] BINARY(10), [SeqVal] BINARY(10), [Action] VARCHAR(300), [CustId] VARCHAR(MAX))
INSERT INTO #TEMP_TABLE
SELECT Lsn, SeqVal, [Action], [CustId] FROM #BatchJobTable
--DECLARE GetBatchJobCursor CURSOR FAST_FORWARD
--FOR
--SELECT Lsn, SeqVal, [Action], [CustId] FROM #BatchJobTable
--OPEN GetBatchJobCursor
--FETCH NEXT FROM GetBatchJobCursor INTO #Lsn, #SeqVal, #Action, #CustId
--WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRY
BEGIN TRANSACTION
IF (#Action = 'create')
BEGIN
-- Create.
INSERT INTO [Bridge_Customer]
(
[CustId]
,[PersonId]
,[DisplayName]
,[CreatedDate]
,[ModifiedDate]
)
SELECT
[CustId]
,[PersonId]
,[DisplayName]
,[CreatedDate]
,[ModifiedDate]
FROM
#BatchJobTable
WHERE
(Lsn = #Lsn) AND (SeqVal = #SeqVal)
END
ELSE IF (#Action = 'update')
BEGIN
-- Update.
UPDATE [Target]
SET
[Target].[CustId] = [Ref].[CustId]
,[Target].[PersonId] = [Ref].[PersonId]
,[Target].[DisplayName] = [Ref].[DisplayName]
,[Target].[CreatedDate] = [Ref].[CreatedDate]
,[Target].[ModifiedDate] = [Ref].[ModifiedDate]
FROM
[dbo].[Bridge_Customer] AS [Target]
INNER JOIN
(SELECT * FROM #BatchJobTable WHERE (Lsn = #Lsn) AND (SeqVal = #SeqVal)) AS [Ref]
ON
([Target].[CustId] = [Ref].[CustId])
END
ELSE IF (#Action = 'delete')
BEGIN
DELETE FROM [dbo].[Bridge_Customer] WHERE [CustId] = #CustId
END
-- Update last processed event.
EXEC [dbo].[UpdateLastProcessedEvent]
#Name = #Name,
#Lsn = #Lsn,
#SeqVal = #SeqVal
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
-- Use RAISERROR inside the CATCH block to return error
-- information about the original error that caused
-- execution to jump to the CATCH block.
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
ROLLBACK TRANSACTION
END CATCH
--FETCH NEXT FROM GetBatchJobCursor INTO #Lsn, #SeqVal, #Action, #CustId
END
--CLOSE GetBatchJobCursor
--DEALLOCATE GetBatchJobCursor
END
GO
A cursor is not necessary here; this is just basic SQL. Forgive any mistakes with my code as you haven't provided any DLL but I'm pretty sure you can just do this:
IF (#Action = 'create')
INSERT INTO Bridge_Customer
(
CustId
,PersonId
,DisplayName
,CreatedDate
,ModifiedDate
)
SELECT
CustId
,PersonId
,DisplayName
,CreatedDate
,ModifiedDate
FROM #BatchJobTable
ELSE IF (#Action = 'update')
UPDATE tgt
SET tgt.CustId = Ref.CustId
,tgt.PersonId = Ref.PersonId
,tgt.DisplayName = Ref.DisplayName
,tgt.CreatedDate = Ref.CreatedDate
,tgt.ModifiedDate = Ref.ModifiedDate
FROM dbo.Bridge_Customer AS tgt
INNER JOIN #BatchJobTable AS ref
ON (tgt.CustId = Ref.CustId)
ELSE IF (#Action = 'delete')
DELETE FROM dbo.Bridge_Customer
WHERE CustId IN (SELECT CustId FROM #BatchJobTable);
Personally, I would split this into three stored and call whichever one from the application layer. What you are doing is known as a "Catch All query" which is fine but, if you must go that route, read this: Catch All Queries (Gail Shaw)

The conversion of the varchar value overflowed an int column while REPLACE

I have table with a myNumber varchar(50) column which stores values with lead zero, like a '0000001111'.
Now I want to replace leading '0000' with '12', like '12001111'.
I tried this statement:
UPDATE myDB.dbo.myTable
SET myNumber = REPLACE(myNumber, '0000', '12')
WHERE myNumber LIKE '0000%'
But this caused an error:
Msg 248, Level 16, State 1, Procedure trplist_for_Inserted_Updated_Deleted Line 80
The conversion of the varchar value "831116399075' overflowed an int column.
Why this error caused if all columns are the varchar?
What should I do?
UPDATED
Sorry guys, the reason of error it is the tables trigger.
Here is triggers logic
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER TRIGGER [dbo].[trplist_for_Inserted_Updated_Deleted]
ON [dbo].[pList]
FOR Insert, Update, Delete
NOT FOR REPLICATION
AS
SET NOCOUNT ON
Declare #Result_check Int
Declare #NameTable nvarchar(30)
set #NameTable='plist'
Declare #FieldName nvarchar(30)
set #FieldName='ChangeTime'
Declare #Columns varbinary(MAX)
set #Columns=COLUMNS_UPDATED()
Execute CheckChangeFields #Columns, #NameTable, #FieldName, #Result_check
if #Result_check = 1
begin
return
end
set #FieldName='DateTimeInArchive'
Execute CheckChangeFields #Columns, #NameTable, #FieldName, #Result_check
if #Result_check = 1
begin
return
end
Declare #stateRecord Int
IF EXISTS(SELECT * FROM inserted)
IF EXISTS(SELECT * FROM deleted)
BEGIN
SET #stateRecord = 1 --Update
--PRINT 'Update'
END
ELSE
BEGIN
--PRINT 'Insert'
SET #stateRecord = 0 --Insert
END
ELSE
BEGIN
--PRINT 'Is DELETE'
IF EXISTS(SELECT * FROM deleted)
BEGIN
SET #stateRecord = 2 --Delete
--PRINT 'DELETE'
END
ELSE
BEGIN
SET #stateRecord = -1
--PRINT 'No DELETE'
END
END
IF #stateRecord = -1
RETURN
declare #id_value int
Declare #status_record int
declare #inn int
declare #Company int
declare #tabnumber varchar(50)
if (#stateRecord in (0,1))
BEGIN
--inserted or updated
--проверка на изменение поля StatusRecord
declare #Result_check_status_record int
if Exists(select * from Deleted where checksum(StatusRecord) In (select Checksum(StatusRecord) from Inserted))
select #Result_check_status_record= 1--одинаковые
else
select #Result_check_status_record= 0--разные
DECLARE cursor_inserted_trpList_Inserted_Updated_Delete_logs CURSOR LOCAL FOR select id, StatusRecord, INN, TabNumber, Company from inserted
OPEN cursor_inserted_trpList_Inserted_Updated_Delete_logs
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value, #status_record,#inn, #tabnumber, #Company
WHILE ##FETCH_STATUS = 0
BEGIN
if (#inn<>'')
begin
if Exists(select id from plist where (id<> #id_value) and (INN=#inn))
begin
RollBack
RAISERROR('Данный INN уже имеется в базе', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
end
if (#tabnumber<>'') and (#tabnumber<>'0')
begin
if #Company = 0
begin
if Exists(select id from plist where (id<> #id_value) and (TabNumber=#tabnumber) and (Company<=0))
begin
RollBack
RAISERROR('Данный TabNumber уже имеется в базе', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
end
else
begin
if Exists(select id from plist where (id<> #id_value) and (TabNumber=#tabnumber) and (Company=#Company))
begin
RollBack
RAISERROR('Данный TabNumber уже имеется в базе в данном подразделении', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
end
end
if ((#status_record&1)>0)
begin
if (#Result_check_status_record=0)
begin
Execute GustIsRelease #id_value
update guest set IDNoFace=0 where PListID=#id_value
Declare #dmtm datetime
if Exists(select id from plist where (id=#id_value) and (IsNull(DateTimeInArchive, '')=''))
begin
Update plist set DateTimeInArchive=GetDate() where (id=#id_value) and (IsNull(DateTimeInArchive, '')='')
end
end
end
else
begin
if Exists(select id from plist where (id=#id_value) and (IsNull(DateTimeInArchive, 1)<>1))
Update plist set DateTimeInArchive=Null where (id=#id_value) and (IsNull(DateTimeInArchive, 1)<>1)
end
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value, #status_record,#inn, #tabnumber, #Company
END
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
END
if (#stateRecord=2)
BEGIN
DECLARE cursor_inserted_trpList_Inserted_Updated_Delete_logs CURSOR LOCAL FOR select id from deleted
OPEN cursor_inserted_trpList_Inserted_Updated_Delete_logs
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value
WHILE ##FETCH_STATUS = 0
BEGIN
if Exists(select id from pmark where owner=#id_value)
begin
RollBack
RAISERROR('У сотрудника остались активные пароли', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
if Exists(select id from guest where IDNoFace=#id_value)
begin
RollBack
RAISERROR('Сотрудник привязан к посетителю', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
update guest set IDNoFace=0 where IDNoFace=#id_value
update guest set ReceiveListId=0 where ReceiveListId=#id_value
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value
END
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
END
You could use STUFF
UPDATE myDB.dbo.myTable
SET myNumber=stuff(myNumber, 1,4, '12')
WHERE myNumber LIKE '0000%'
Use can use SUBSTRING/STUFF as below:
SUBSTRING:
UPDATE #tblTest
SET Number='12'+SUBSTRING(Number,5,LEN(NUMBER))
WHERE LEFT(Number,4)='0000'
AND LEN(Number)>4
STUFF:
UPDATE #tblTest
SET Number=STUFF(Number, 1,4, '12')
WHERE LEFT(Number,4)='0000'
AND LEN(Number)>4
Use substring function to accomplish the result u want
UPDATE myDB.dbo.myTable
SET Number='12'+SUBSTRING(myNumber,5)
WHERE SUBSTRING(myNumber,1,4)='0000';

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 Insert multiple records to Triggered table

On SQL Agent job I'm downloading data from main table (X). If the status equal 'WW' or 'WXY' I just want to all records insert into another table (Y) where I have created a trigger. Could you give me advise what should I change in my trigger definition? I receive error message when I try insert multiple records to DB2.Y table (agent job failed)
First code (downloading new data)
DECLARE #STARTTIME datetime
DECLARE #TIME datetime
DECLARE #ENDTIME datetime
SET #TIME=(SELECT MAX(Time) FROM DB2.Y)
SET #STARTTIME=(select dateadd(hour,1,getdate()))
SET #ENDTIME=(SELECT MAX(TIME) FROM DB1.X where TIME is not null)
IF #TIME = #ENDTIME
BEGIN
TRUNCATE TABLE DB2.Y;
INSERT INTO DB2.Y (Time) Values (#TIME)
END
ELSE
BEGIN
TRUNCATE TABLE DB2.Y
INSERT INTO DB2.Y ([Serv],[Status])
SELECT [SERV],[STATUS] FROM DB1.X WHERE TIME > #TIME and [SERV]='Description' and ([STATUS]='WW' or [STATUS]='WXY') ;
UPDATE DB2.Y
SET [Time]= #ENDTIME
END
The trigger code:
USE DB2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT AS
DECLARE #SERV varchar(40)
DECLARE #STATUS varchar(3)
SET #SERV=(SELECT [SERV] FROM inserted)
SET #STATUS=(SELECT [STATUS] FROM inserted)
IF #STATUS in ('WW', 'WXY')
BEGIN
DECLARE #MSG varchar(500)
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
END
INSERTED can contain multiple rows for multi-row INSERTs - it runs once per operation, not once per row.
Try a trigger like this instead:
USE DB2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT AS
DECLARE #SERV varchar(40)
DECLARE #STATUS varchar(3)
IF EXISTS(SELECT [Status] FROM Inserted WHERE [STATUS] in ('WW', 'WXY'))
BEGIN
DECLARE #MSG varchar(8000)
INSERT INTO JobLog(Serv, Status)
SELECT Serv, Status FROM Inserted WHERE [STATUS] in ('WW', 'WXY')
SET #MSG = CAST(##ROWCOUNT as nvarchar) + 'Job(s) failed - see log for details'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
END
SELECT
Try something like this...
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SERV varchar(40),#STATUS varchar(3), #MSG varchar(500)
Select [SERV], [STATUS] INTO #Temp
FROM inserted
Where [STATUS] IN ('WW', 'WXY')
Declare Cur CURSOR FOR
SELECT [SERV], [STATUS] FROM #Temp
OPEN Cur
FETCH NEXT FROM Cur INTO #SERV, #STATUS
WHILE ##FETCH_STATUS = 0
BEGIN
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com'
, #body= #MSG
, #subject = #MSG
, #profile_name = 'profilename'
FETCH NEXT FROM Cur INTO #SERV, #STATUS
END
CLOSE Cur
DEALLOCATE Cur
END
You could use a cursor to resolve your error. The cursor below iterates over all inserted records with a STATUS of either WW or WXY and sends out an email for each of them.
DECLARE error_cursor CURSOR FOR
SELECT [SERV],[STATUS] FROM inserted
WHERE [STATUS] in ('WW', 'WXY')
OPEN error_cursor
FETCH NEXT FROM error_cursor
INTO #SERV, #STATUS
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE MSG varchar(500)
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
FETCH NEXT FROM vendor_cursor
INTO #SERV, #STATUS
END
CLOSE error_cursor;
DEALLOCATE error_cursor;

Resources