You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取执行失败的UPDATE语句的OUTPUT结果?

问题:UPDATE语句因非法值失败时如何保留已成功转换的结果?

我需要把十六进制ID列表转成十进制,为了避免用CURSOR写了T-SQL代码,但最后一个ID是非法十六进制值,导致UPDATE执行失败,连已经成功处理的OUTPUT结果也拿不到。想知道怎么在UPDATE失败时还能获取已经成功转换的输出。

原代码如下:

-- 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, '0' + 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

原因分析

T-SQL里的UPDATE是原子操作,只要有一行转换失败,整个UPDATE会被回滚,所以@inserted表不会有任何数据,之前成功转换的行也会被撤销。

解决方案

方案1:用TRY_CONVERT实现容错批量转换(推荐)

利用TRY_CONVERT函数的容错特性,它在转换失败时会返回NULL而不是抛出错误,这样整个UPDATE不会中断,同时还能标记出转换失败的行。

-- Test IDs, last one has an error
DECLARE @hexIDs AS VARCHAR(255) = '00000AAAAAA,00000BBBBBB,00000CCCCCC,X0000DDDDDD';

-- 存储原始ID、转换结果和状态
DECLARE @ids AS TABLE(
    IDHex VARCHAR(11), 
    ID BIGINT,
    ConversionStatus VARCHAR(100)
);

INSERT INTO @ids (IDHex) SELECT * FROM string_split(@hexIDs, ',');

-- 批量转换,失败的行标记状态
UPDATE @ids 
SET 
    ID = TRY_CAST(TRY_CONVERT(VARBINARY, '0' + IDHex, 2) AS BIGINT),
    ConversionStatus = CASE 
        WHEN TRY_CONVERT(VARBINARY, '0' + IDHex, 2) IS NULL THEN '转换失败:非法十六进制格式'
        ELSE '转换成功'
    END;

-- 查看所有行的转换结果
SELECT * FROM @ids;

-- 单独提取成功转换的十进制ID
SELECT ID FROM @ids WHERE ConversionStatus = '转换成功';

方案2:逐行处理(细粒度错误记录)

如果需要记录每个错误的具体信息,可以用WHILE循环逐行处理,捕获单条行的错误,这样即使某行失败,前面的成功行依然保留。

-- Test IDs, last one has an error
DECLARE @hexIDs AS VARCHAR(255) = '00000AAAAAA,00000BBBBBB,00000CCCCCC,X0000DDDDDD';

-- 存储原始ID、转换结果、状态和行号(用于逐行定位)
DECLARE @ids AS TABLE(
    IDHex VARCHAR(11), 
    ID BIGINT,
    ConversionStatus VARCHAR(200),
    RowNum INT IDENTITY(1,1) PRIMARY KEY
);
-- 存储成功转换的ID
DECLARE @inserted AS TABLE(ID BIGINT);

INSERT INTO @ids (IDHex) SELECT * FROM string_split(@hexIDs, ',');

DECLARE @currentRow INT = 1;
DECLARE @maxRow INT = (SELECT MAX(RowNum) FROM @ids);
DECLARE @currentHex VARCHAR(11);

WHILE @currentRow <= @maxRow
BEGIN
    SELECT @currentHex = IDHex FROM @ids WHERE RowNum = @currentRow;
    
    BEGIN TRY
        -- 转换当前行
        UPDATE @ids 
        SET 
            ID = CAST(CONVERT(VARBINARY, '0' + @currentHex, 2) AS BIGINT),
            ConversionStatus = '转换成功'
        WHERE RowNum = @currentRow;
        
        -- 插入成功结果到@inserted表
        INSERT INTO @inserted SELECT ID FROM @ids WHERE RowNum = @currentRow;
    END TRY
    BEGIN CATCH
        -- 记录错误信息
        UPDATE @ids 
        SET ConversionStatus = '转换失败:' + ERROR_MESSAGE()
        WHERE RowNum = @currentRow;
    END CATCH
    
    SET @currentRow = @currentRow + 1;
END

-- 查看所有行的转换状态
SELECT * FROM @ids;
-- 查看成功转换的ID列表
SELECT * FROM @inserted;

内容的提问来源于stack exchange,提问作者SebUhb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:41:34