May 28, 2020 at 6:09 pm
We have the following code in a stored procedure which has a merge statement and an update statement to a different table in an explicit transaction. The merge update does not update any data in the inventory.gtin table but the update statement below it works and data is updated in the import.file_data table when the stored procedure is called in a batch job. But, when the stored procedure is executed manually, the merge works fine and updates/inserts data. Is there anything missing in the code that may be causing this?
DECLARE @targetVendorCode nvarchar(20)
DECLARE gtin_cursor CURSOR FOR
SELECT DISTINCT aVendorCode
FROM #fileData fd
OPEN gtin_cursor
FETCH NEXT FROM gtin_cursor INTO @targetVendorCode
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION;
MERGE [inventory].[gtin] AS target
USING (SELECT * FROM #fileData WHERE ngtin IS NOT NULL AND aVendorCode = @targetVendorCode ) AS source
ON (target.[ngtin] = source.[ngtin])
WHEN MATCHED AND ( ( source.createDateTime > COALESCE(target.fileCreateDateTime,'04/02/1982') ) OR source.[status] = 'override' ) THEN
UPDATE SET
[skuId] = source.[skuId],
[lastUpdateFileId] = source.[fileId],
[vendorCode] = COALESCE(source.[aVendorCode],source.[vendorCode]),
[lastUpdateDateTime] = source.[lastUpdateDateTime],
[fileCreateDateTime]= source.createDateTime
WHEN NOT MATCHED BY TARGET THEN
INSERT (
[skuId],
[lastUpdateFileId],
[vendorCode],
[lastUpdateDateTime],
[fileCreateDateTime]
)
VALUES (
source.[skuId],
source.[fileId],
COALESCE(source.[aVendorCode],source.[vendorCode]),
source.[lastUpdateDateTime],
source.createDateTime
)
SELECT @action = '[{"type":"distribute","actionDateTime":"' + CONVERT(VARCHAR(19), GETUTCDATE(), 120) + '","insertDateTime":"' + CONVERT(VARCHAR(19), GETUTCDATE(), 120) + '","referenceId":' + TRY_CAST(@fileId AS NVARCHAR(20)) + '}]'
UPDATE fd SET [status] = 'processed',[modifiedDateTime] = GETUTCDATE(),[modifiedUserName] = SYSTEM_USER FROM [import].[file_data] fd WHERE fileId = @fileId
IF @@TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION;
END
ELSE
BEGIN
ROLLBACK TRANSACTION;
END
FETCH NEXT FROM gtin_cursor INTO @targetVendorCode
END
CLOSE gtin_cursor
DEALLOCATE gtin_cursor
May 28, 2020 at 6:42 pm
Does the merge insert? The update has additional criteria it is checking. Also, Why are you using a cursor, this looks like a set based operation would work faster? I'd also be worried about the cursor. You are selecting distinct which indicates there could be multiple avendorcode, but then you select from the same temp table by avendorcode, so that could be finding multiple records. Also, a try/catch block would help to find the issues.
For better, quicker answers, click on the following...
http://www.sqlservercentral.com/articles/Best+Practices/61537/
For better answers on performance questions, click on the following...
http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
May 28, 2020 at 7:33 pm
Thank you for the response. The code actually has a try/catch logic wrapped in it which I omitted. There weren't any errors in the batch job when executed. Also, the conditions in the WHEN MATCHED are always true and the cursor is needed to process for each distinct vendor. In regards to selecting from the same temp table by avendorcode, there could definitely be multiple records for that same avendorcode and those records that match the join should be updated. I have read warnings about using merge because there are bugs in it that have not been fixed.
May 28, 2020 at 11:18 pm
As separate statements maybe something like this
set xact_abort on;
begin transaction;
begin try
update g
set
[skuId] = source.[skuId],
[lastUpdateFileId] = source.[fileId],
[vendorCode] = coalesce(source.[aVendorCode],source.[vendorCode]),
[lastUpdateDateTime] = source.[lastUpdateDateTime],
[fileCreateDateTime]= source.createDateTime
from
[inventory].[gtin] g
join
#filedata f on f.aVendorCode=g.vendorCode
and f.[ngtin] = g.[ngtin]
and (f.createDateTime > coalesce(g.fileCreateDateTime,'04/02/1982')
or f.[status] = 'override');
insert [inventory].[gtin]([skuId], [lastUpdateFileId], [vendorCode], [lastUpdateDateTime], [fileCreateDateTime])
select
[skuId], [fileId], coalesce([aVendorCode],[vendorCode]), [lastUpdateDateTime], createDateTime
from
#filedata f
where not exists(select 1
from [inventory].[gtin] g
where f.aVendorCode=g.vendorCode
and f.[ngtin] = g.[ngtin]);
commit transaction;
end try
begin catch
print ('did not work');
rollback transaction;
end catch
Aus dem Paradies, das Cantor uns geschaffen, soll uns niemand vertreiben können
Viewing 4 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic. Login to reply