sql linked server Insert statement fails inside the cursor - sql
Insert statement fails inside the cursor when I try to insert values in to SQL linked server.
If I run the same insert statement outside cursor then it works fine. Is there any settings to be done while creating linked server?
Error message:
OLE DB provider "SQL...." for linked server "" returned message "The parameter is incorrect.".
This is my Code Linked Server in Cursor
SET NOCOUNT ON;
DECLARE #SUBCATEGORY_NAME AS VARCHAR(100), #CategoryStatus AS BIT, #BRAND_NAME AS VARCHAR(100), #BrandMasterStatus AS BIT, #BrandManfacturerName AS VARCHAR(MAX), #PRODUCT_NAME VARCHAR(100), #ProductStatus AS BIT,
#ProductIsReturnable AS BIT, #PRINT_ON_RECEIPT AS VARCHAR(40), #TenantId INT, #CreationTime DATETIME2, #ParentId INT, #BAR_CODE_NO AS VARCHAR(40),
#TAX_CODE AS VARCHAR(MAX), #TaxName AS VARCHAR(MAX), #TaxInclusive AS BIT, #TAX_PERCENTAGE AS FLOAT, #TaxStartDateTime DATETIME2, #BUSINESS_TYPE VARCHAR(20);
--PRINT '-------- Product table migration --------';
DECLARE Product_Cursor CURSOR FOR
SELECT
SC.SUBCATEGORY_NAME,CASE WHEN SC.DEFUNCT_IND = 'N' THEN 1 ELSE 0 END AS CategoryStatus,
BM.BRAND_NAME,CASE WHEN BM.DEFUNCT_IND = 'N' THEN 1 ELSE 0 END AS BrandMasterStatus,BM.MANUFACTURER AS BrandManfacturerName,
P.PRODUCT_NAME,CASE WHEN P.DEFUNCT_IND = 'N' THEN 1 ELSE 0 END AS ProductStatus,
CASE WHEN P.RETURNABLE = 'Y' THEN 1 ELSE 0 END AS ProductIsReturnable,
P.PRINT_ON_RECEIPT,
--SubCategoryId,
--BrandId,
--1 AS TaxId,
1 AS TenantId,
GETDATE() AS CreationTime,
0 AS ParentId,
P.BAR_CODE_NO,
TS.TAX_CODE,
TS.TAX_DESC AS TaxName,
CASE WHEN TS.TAX_INCLUDED = '1' THEN 1 ELSE 0 END AS TaxInclusive,
TS.TAX_PERCENTAGE,
TS.EFFECTIVE_DATE AS TaxStartDateTime,
P.BUSINESS_TYPE
FROM CISPROD.dbo.PRODUCT AS P
RIGHT OUTER JOIN CISPROD.dbo.SUBCATEGORY AS SC ON SC.SUBCATEGORY_ID = P.SUBCATEGORY_ID
FULL OUTER JOIN CISPROD.dbo.BRANDMSTR AS BM ON BM.BRANDMSTR_ID = P.BRANDMSTR_ID
FULL OUTER JOIN CISPROD.dbo.TAX_SETUP AS TS ON TS.TAX_CODE = P.TAX_GROUP
OPEN Product_Cursor
FETCH NEXT FROM Product_Cursor
INTO #SUBCATEGORY_NAME,#CategoryStatus,#BRAND_NAME, #BrandMasterStatus, #BrandManfacturerName, #PRODUCT_NAME, #ProductStatus, #ProductIsReturnable,
#PRINT_ON_RECEIPT, #TenantId, #CreationTime,#ParentId,#BAR_CODE_NO,#TAX_CODE, #TaxName, #TaxInclusive, #TAX_PERCENTAGE, #TaxStartDateTime, #BUSINESS_TYPE;
BEGIN TRANSACTION
BEGIN TRY
WHILE ##FETCH_STATUS = 0
BEGIN
--PRINT ' '
--DECLARE #message VARCHAR(MAX)
--SELECT #message = '----- Products CISPROD: ' + #PRODUCT_NAME
--PRINT #message
--Insert Product Categories Table
DECLARE #CategoryId INT
IF ISNULL(#SUBCATEGORY_NAME,'') <>''
BEGIN
---IF NOT EXISTS(SELECT [Name] FROM ProductCategories WHERE ISNULL([Name], '') = ISNULL(#SUBCATEGORY_NAME,''))
IF NOT EXISTS(SELECT [Name] FROM [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductCategories WHERE [Name] = #SUBCATEGORY_NAME)
BEGIN
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductCategories([Name],CreationTime,Inactive,ParentId,TenantId) VALUES(#SUBCATEGORY_NAME,#CreationTime,#CategoryStatus,#ParentId,#TenantId)
SELECT #CategoryId = ##IDENTITY
END
ELSE
BEGIN
SELECT #CategoryId = Id FROM [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductCategories WHERE [Name] = #SUBCATEGORY_NAME
END
END
--Insert Product Brand Table
DECLARE #BrandId INT
--DECLARE #DefaultBrandId INT
--SET #DefaultBrandId = 1
IF ISNULL(#BRAND_NAME,'') <>''
BEGIN
--IF NOT EXISTS(SELECT BrandName FROM ProductBrands WHERE ISNULL(BrandName,'') = ISNULL(#BRAND_NAME,''))
IF NOT EXISTS(SELECT BrandName FROM [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductBrands WHERE BrandName = #BRAND_NAME)
BEGIN
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductBrands(BrandName,ManufacturerName,CreationTime,Inactive) VALUES(#BRAND_NAME,#BrandManfacturerName,#CreationTime,#BrandMasterStatus)
SELECT #BrandId = ##IDENTITY
END
ELSE
BEGIN
SELECT #BrandId = Id FROM [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductBrands WHERE BrandName = #BRAND_NAME
END
END
--ELSE
--BEGIN
-- SET #BrandId = #DefaultBrandId
--END
--Insert Tax Table Records
DECLARE #TaxId INT
IF ISNULL(#TAX_CODE,'') <>''
BEGIN
IF NOT EXISTS(SELECT Code FROM [AZUREDATABASE].[sds-pos-storiveo-db].dbo.Taxes WHERE Code = #TAX_CODE)
BEGIN
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.Taxes(Code,Inactive,IsInclusive,[Name],TaxTypeId,TenantId) VALUES(#TAX_CODE,1,#TaxInclusive,#TaxName,1,#TenantId)
SELECT #TaxId = ##IDENTITY
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.TaxSchedules([Percentage],StartDateTime,TaxId) VALUES(#TAX_PERCENTAGE,#TaxStartDateTime,#TaxId)
END
ELSE
BEGIN
SELECT #TaxId = Id FROM [AZUREDATABASE].[sds-pos-storiveo-db].dbo.Taxes WHERE Code = #TAX_CODE
END
END
--Insert Product Table Records
DECLARE #ProductId INT
IF ISNULL(#PRODUCT_NAME,'') <>''
BEGIN
IF (#BUSINESS_TYPE = 'NF')
BEGIN
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.Products([Name],Inactive,IsReturnable,PrintName,
ProductBrandId,ProductCategoryId,TaxId,TenantId,CreationTime)
VALUES(#PRODUCT_NAME,#ProductStatus,#ProductIsReturnable,#PRINT_ON_RECEIPT,#BrandId,#CategoryId,#TaxId,#TenantId,#CreationTime)
END
ELSE
BEGIN
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.FuelProducts([Name],Inactive,PrintName,
ProductCategoryId,TaxId,TenantId,CreationTime)
VALUES(#PRODUCT_NAME,#ProductStatus,#PRINT_ON_RECEIPT,#CategoryId,#TaxId,#TenantId,#CreationTime)
END
SELECT #ProductId = ##IDENTITY
END
--Insert Product Barcode Records
IF ISNULL(#BAR_CODE_NO,'') <>''
BEGIN
IF (#BUSINESS_TYPE = 'NF')
BEGIN
INSERT INTO [AZUREDATABASE].[sds-pos-storiveo-db].dbo.ProductBarcodes(Barcode,Inactive,ProductId)VALUES(#BAR_CODE_NO,#ProductStatus,#ProductId)
END
END
FETCH NEXT FROM Product_Cursor
INTO #SUBCATEGORY_NAME,#CategoryStatus,#BRAND_NAME, #BrandMasterStatus, #BrandManfacturerName, #PRODUCT_NAME, #ProductStatus, #ProductIsReturnable,
#PRINT_ON_RECEIPT, #TenantId, #CreationTime, #ParentId, #BAR_CODE_NO, #TAX_CODE, #TaxName, #TaxInclusive, #TAX_PERCENTAGE, #TaxStartDateTime,#BUSINESS_TYPE
END
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
-- any other logiing or cleanup
END CATCH
IF ##TranCount>0 -- Transaction still open, so must have succeeded. If rolled back, trancount would be 0
COMMIT TRANSACTION
CLOSE Product_Cursor;
DEALLOCATE Product_Cursor;
Related
Creating an Instead of insert Trigger SQL
I am a DBA with my company. I am trying to create trigger that will check any insert statement for duplicates first then if none allow the original insert. Not even sure this can be done. The insert statements may be written by various users so the statements will never be the same. All I have found so far is the check for duplicates but the insert statement is then hard coded in the trigger. My plan is also to check update as well, but it is not important right now. Here is my current code. ALTER TRIGGER [dbo].[BlockDuplicatesOnTable] ON [dbo].[blockduplicates] Instead of INSERT, Update AS BEGIN SET NOCOUNT ON; Declare #ProviderAcctNumber nvarchar(50) Declare #Referredby int Declare #Action as char(1) Declare #Count as int Set #Action = 'I' Select #Count = Count(*) from DELETED IF #Count > 0 Begin Set #Action = 'D' Select #Count = count(*) from INSERTED IF #Count > 0 Set #Action = 'U' IF #Action = 'I' Begin IF not exists (Select 1 from inserted as i inner join dbo.blockduplicates as b on i.ProviderAcctNumber = b.ProviderAcctNumber and i.Referredby = b.Referredby) Begin --execute original insert End Else Begin Print 'Duplicate insert' Raiserror ('Duplicate Entry for Insert',16,1); Return End End Else IF #Action = 'U' Begin Select #ProviderAcctNumber = ProviderAcctNumber, #Referredby = Referredby from inserted IF Not exists (Select 1 from deleted where ProviderAcctNumber = #ProviderAcctNumber and Referredby = #Referredby) Begin Print 'Update Statement is True'; End Else Begin Print 'duplicate' Raiserror ('Duplicate Entry for Update',16,1); Return End End End End;
Azure SQL Database trigger is not running and I cannot seem to figure out why
I'm trying to update the status column of a table when the table has been edited. I use a similar trigger on another table to update this status but when I try to put the trigger on the table itself it will not run. ALTER TRIGGER dbo.tr_Invoice_SetInvoiceStatus_Update ON dbo.Invoice AFTER INSERT, UPDATE AS BEGIN SET NOCOUNT ON; DECLARE #InvoiceID int DECLARE #TotalInvoice DECIMAL(18,2) DECLARE #TotalPayments DECIMAL(18,2) DECLARE #InvoiceStatus NVARCHAR(50) DECLARE #InvoiceStatusID INT SELECT #InvoiceID = ID FROM Inserted i SELECT #TotalPayments = IsNull(Sum(ph.Amount), 0) FROM PaymentHistory ph WHERE InvoiceID = #InvoiceID SELECT #TotalInvoice = ISNULL(Total, 0) FROM Invoice WHERE ID = #InvoiceID IF (#TotalPayments > 0) BEGIN IF (#TotalPayments >= #TotalInvoice) BEGIN SELECT #InvoiceStatus = 'Paid' END ELSE BEGIN SELECT #InvoiceStatus = 'Partially Paid' END END ELSE BEGIN SELECT #InvoiceStatus = 'Open' END SELECT #InvoiceStatusID = ID FROM dbo.InvoiceStatus WHERE [Name] = #InvoiceStatus UPDATE dbo.Invoice SET InvoiceStatusID = #InvoiceStatusID WHERE ID = #InvoiceID END GO Any help would be great?
SQL DB script performance tuning
I need to fix a prod DB issue and the clean up script I've is taking really long. I tried couple of things without any luck, following is the script: DECLARE #ErrorMessage NVARCHAR(4000) DECLARE #ErrorSeverity INT DECLARE #ErrorState INT DECLARE #ErrorProcedure NVARCHAR(50) BEGIN TRY IF OBJECT_ID('tempdb..#SuspectData') IS NOT NULL BEGIN DROP TABLE #SuspectData END CREATE TABLE #SuspectData ( IID INT, CID INT, PID INT ) INSERT INTO dbo.#SuspectData SELECT DL.IID,DL.CID,IT.PID FROM DL INNER JOIN IT ON IT.CID = DL.CID AND IT.IID = DL.IID WHERE DL.Suspect = 1 WHILE (1 = 1) BEGIN BEGIN TRANSACTION UPDATE TOP (5000) TDS SET TDS.DTID = 4 FROM TDS INNER JOIN dbo.#SuspectData SD ON TDS.IID = SD.IID AND TDS.PID = SD.PID WHERE TDS.DTID <> 4 IF ##ROWCOUNT = 0 BEGIN COMMIT TRANSACTION BREAK END COMMIT TRANSACTION END WHILE (1 = 1) BEGIN BEGIN TRANSACTION UPDATE TOP (5000) TDA SET TDA.DTID = 4 FROM TDA INNER JOIN dbo.#SuspectData SD ON TDA.IID = SD.IID AND TDA.PID = SD.PID WHERE TDA.DTID <> 4 IF ##ROWCOUNT = 0 BEGIN COMMIT TRANSACTION BREAK END COMMIT TRANSACTION END DROP TABLE #SuspectData END TRY BEGIN CATCH SELECT #ErrorMessage = ERROR_MESSAGE(), #ErrorSeverity = ERROR_SEVERITY(), #ErrorState = ERROR_STATE(), #ErrorProcedure = ERROR_PROCEDURE() RAISERROR (#ErrorMessage,#ErrorSeverity,#ErrorState,#ErrorProcedure) ; END CATCH I also have following script to update everything at same time but it is also taking really long time like 24 hours or something. DECLARE #ErrorMessage NVARCHAR(4000) DECLARE #ErrorSeverity INT DECLARE #ErrorState INT DECLARE #ErrorProcedure NVARCHAR(50) BEGIN TRY IF OBJECT_ID('tempdb..#SuspectData') IS NOT NULL BEGIN DROP TABLE #SuspectData END CREATE TABLE #SuspectData ( IID INT, CID INT, PID INT ) INSERT INTO dbo.#SuspectData SELECT DL.IID,DL.CID,IT.PID FROM DL INNER JOIN IT ON IT.CID = DL.CID AND IT.IID = DL.IID WHERE DL.Suspect = 1 BEGIN TRANSACTION --Update about 1.5M records UPDATE TDS SET TDS.DTID = 4 FROM TDS INNER JOIN dbo.#SuspectData SD ON TDS.IID = SD.IID AND TDS.PID = SD.PID WHERE TDS.DTID <> 4 COMMIT TRANSACTION BEGIN TRANSACTION --Update about 4.5M records UPDATE TDA SET TDA.DTID = 4 FROM TDA INNER JOIN dbo.#SuspectData SD ON TDA.IID = SD.IID AND TDA.PID = SD.PID WHERE TDA.DTID <> 4 COMMIT TRANSACTION DROP TABLE #SuspectData END TRY BEGIN CATCH SELECT #ErrorMessage = ERROR_MESSAGE(), #ErrorSeverity = ERROR_SEVERITY(), #ErrorState = ERROR_STATE(), #ErrorProcedure = ERROR_PROCEDURE() RAISERROR (#ErrorMessage,#ErrorSeverity,#ErrorState,#ErrorProcedure) ; END CATCH
I'm guessing that TDS table is large. In that case you can speed up join operation between your temp table and TDS (ON TDS.IID = SD.IID AND TDS.PID = SD.PID) by creating index on your temporary table: either primary clustered: CREATE TABLE #SuspectData ( IID INT, CID INT, PID INT, CONSTRAINT pk_temp PRIMARY KEY(IID, PID) ) or not-clustered (if IID-PID pairs are not unique): CREATE INDEX IDX_Temp_SuspectData ON #SuspectData(IID,PID) What you can also do is check execution plan of those queries - it will help you locate which operation takes so long. On the side: I'm generally against using cursors if you can avoid it.
First, is there anything that changes DL.Suspect = 1 to something else? or does your data set just keep getting bigger? I also agree with Sean Lange, does the update have to be all or nothing? I would recommend using a cursor. cursors are a great way to break up large transaction to speed up use and reduce table locks. DECLARE db_cursor CURSOR FOR SELECT DL.IID,DL.CID,IT.PID FROM DL INNER JOIN IT ON IT.CID = DL.CID AND IT.IID = DL.IID WHERE DL.Suspect = 1; DECLARE #first INT; DECLARE #second INT; DECLARE #third INT; OPEN db_cursor; FETCH NEXT FROM db_cursor INTO #first , #second , #third ; WHILE ##FETCH_STATUS = 0 BEGIN -- Do your updates one row at a time here UPDATE TDS SET TDS.DTID = 4 FROM TDS WHERE TDS.IID = #first AND TDS.PID = #third WHERE TDS.DTID <> 4 END; CLOSE db_cursor; DEALLOCATE db_cursor;
Stored Procedure Error - Transaction Count mismatch
I've been doing this stored procedure, however when I execute the stored procedure, I get an infinity execution. This cause a deadlock. This is the error I got, can someone please help me on this?? Thanks. Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 2. Code: ALTER PROCEDURE [dbo].[spMaterialReceivingCreateItemRequirements] #DomainSite nvarchar(8), #ItemNo nvarchar(18), #tReceiving_id integer, #SampleRequired integer, #UserName nvarchar(50) AS BEGIN Declare #ErrorNo integer = '', #New_JobNo integer, #Status nvarchar(50) = 'InProcess', #SPName nvarchar(max) = '', #intSampleNo integer =1, #ErrorMessage nvarchar(max) = '' begin transaction t1 Begin try BEGIN --Generate 1 sample for item requirements set #SampleRequired = 1 WHILE (#intSampleNo <= #SampleRequired) BEGIN insert into tItemRequirements select domainSite, #tReceiving_id, #ItemNo, WorkCenter, tStationsType_id, tSpecTestParameters_descriptions_id, --row_number() OVER (ORDER BY ID) AS CurrentSet, 1 AS CurrentSet, #intSampleNo, 1, 'InComplete', getdate(), #UserName from tspectestparameters where itemno = #ItemNo set #intSampleNo = #intSampleNo +1 end END END TRY Begin catch SELECT #ErrorNo = ERROR_NUMBER(), #SPName = ERROR_PROCEDURE(), #ErrorMessage = ERROR_MESSAGE(); rollback transaction t1 end catch END
BEGIN TRANSACTION t1 BEGIN TRY BEGIN --Generate 1 sample for item requirements SET #SampleRequired = 1 WHILE (#intSampleNo <= #SampleRequired) BEGIN INSERT INTO tItemRequirements SELECT domainSite , #tReceiving_id , #ItemNo , WorkCenter , tStationsType_id , tSpecTestParameters_descriptions_id , --row_number() OVER (ORDER BY ID) AS CurrentSet, 1 AS CurrentSet , #intSampleNo , 1 , 'InComplete' , getdate() , #UserName FROM tspectestparameters WHERE itemno = #ItemNo SET #intSampleNo = #intSampleNo + 1 END END COMMIT END TRY BEGIN CATCH SELECT #ErrorNo = ERROR_NUMBER() , #SPName = ERROR_PROCEDURE() , #ErrorMessage = ERROR_MESSAGE(); ROLLBACK TRANSACTION t1 END CATCH
Merge sql with date condition
I have create merge stored procedures as below, what i am trying to achieve is the following scenario: Merge the new record if ProductTRN is not exist in ProductList table (complete) Only Update the ProductList record in where the PU.CreateDate is bigger than CreateDate of target table which is ProductList (Not Complete) Please advise me how I can achieve the second scenario above, thank you CREATE PROCEDURE [dbo].[usp_ProductList_Merge] AS BEGIN DECLARE #retValue INT BEGIN TRY IF OBJECT_ID('ProductList') IS NOT NULL BEGIN BEGIN TRANSACTION MergeConsumerTable SET NOCOUNT ON; MERGE dbo.ProductList AS target USING ( SELECT PU.ProductTRN, PU.ProductName, PU.ProductDescription, PU.CreateDate FROM dbo.TmpProductList PU WHERE PU.ProductTRN = ProductTRN ) AS source ( ProductTRN, ProductName, ProductDescription CreateDate) ON ( (target.ProductTRN) = LOWER(source.ProductTRN) ) WHEN MATCHED THEN UPDATE SET ProductTRN= source.ProductTRN WHEN NOT MATCHED THEN INSERT ( ProductTRN, ProductName, ProductDescription, CreateDate ) VALUES ( source.ProductTRN, source.ProductName, source.ProductDescription, source.CreateDate, ); DELETE PU FROM dbo.TmpProductList PU COMMIT TRANSACTION MergeProductListTable SET #retValue = 1 SELECT #retValue END ELSE BEGIN SET #retValue = -1 SELECT #retValue END END TRY BEGIN CATCH ROLLBACK TRANSACTION MergeProductListTable DECLARE #ErrorMsg VARCHAR(MAX); DECLARE #ErrorSeverity INT; DECLARE #ErrorState INT; SET #ErrorMsg = ERROR_MESSAGE(); SET #ErrorSeverity = ERROR_SEVERITY(); SET #ErrorState = ERROR_STATE(); SET #retValue = 0 SELECT #retValue -- SELECT 0 AS isSuccess END CATCH END
WITH Source AS ( SELECT ProductTRN ,ProductName ,ProductDescription ,CreateDate FROM dbo.TmpProductList ) MERGE ProductList AS Target USING Source ON Target.ProductTRN = Source.ProductTRN WHEN MATCHED AND Source.CreatedDate > Target.CreatedDate THEN UPDATE SET ProductName = Source.ProductName ,ProductDescription = Source.ProductDescription ,CreateDate = Source.CreatedDate WHEN NOT MATCHED BY TARGET THEN INSERT ( ProductTRN ,ProductName ,ProductDescription ,CreateDate ) VALUES ( Source.ProductTRN ,Source.ProductName ,Source.ProductDescription ,Source.CreatedDate )