I’m trying to solve the following problem, but can’t get the output of a failing update statement:
I want to convert a list of hexadecimal IDs into a list of decimal IDs.
To avoid a CURSOR I want to do that with the following flow:
-- Test IDs, last one has an error
DECLARE @hexIDs AS VARCHAR(255) = '00000AAAAAA,00000BBBBBB,00000CCCCCC,X0000DDDDDD';
-- Table which holds hex IDs and converted IDs (necessary for feedback if something fails)
DECLARE @ids AS TABLE(IDHex VARCHAR(11), ID BIGINT);
-- Table to track updated ids
DECLARE @inserted AS TABLE(ID BIGINT);
BEGIN TRY
INSERT INTO @ids (IDHex) SELECT * FROM string_split(@hexIDs, ',');
UPDATE @ids SET ID = CAST(CONVERT(VARBINARY, IDHex, 2) AS BIGINT)
OUTPUT inserted.ID INTO @inserted;
SELECT * FROM @ids;
SELECT * FROM @inserted;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
SELECT * FROM @ids;
SELECT * FROM @inserted;
END CATCH
As expected, the UPDATE fails because the last string ID is no hex value.
If I understand the Microsoft documentation right, the OUTPUT should work. But I can’t figure out how. Can someone tell me how I can get the output of the UPDATE statement even if it fails?
>Solution :
If you read the documentation you find out where you are going wrong. e.g.
- Binary values must be an even number of chars long
- You should always specify the length of
VARBINARYwhenever you use it.
Then you use TRY_CONVERT to only process rows which you can convert.
UPDATE @ids SET ID = CAST(TRY_CONVERT(VARBINARY(6), '0' + IDHex, 2) AS BIGINT)
OUTPUT inserted.ID INTO @inserted
WHERE TRY_CONVERT(VARBINARY(6), '0' + IDHex, 2) IS NOT NULL;