首页 > 解决方案 > T-SQL 在 BEGIN CATCH 中插入

问题描述

在此先感谢您的帮助。

我想要实现的是处理违反 FK(市政代码)的约束,在这种情况下,我想将记录插入到辐射表中。

在这段代码中,select 的结果可以为 null,因此会抛出异常,因为我在目标上有一个 not null 子句。

TARGET.MUNICIPALITYCODE = (SELECT m.MUNICIPALITYCODE FROM MUNICIPALITY m WHERE SOURCE.MUNICIPALITYCODE = m.MUNICIPALITYCODE)

我希望能够处理 BEGIN CATCH 块上的异常并将我在 SOURCE 上使用的值插入到我选择的表中。

有谁知道这是否可能?

CREATE PROCEDURE upsertStagingToStreet
AS
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

    BEGIN TRY

        BEGIN TRAN

           MERGE STREET AS TARGET
           USING STREET_STAGING AS SOURCE
           ON (TARGET.correlationkey = SOURCE.correlationkey)

           WHEN MATCHED 
           THEN UPDATE SET TARGET.Qty = SOURCE.Qty,
                TARGET.MUNICIPALITYCODE = (SELECT m.MUNICIPALITYCODE FROM MUNICIPALITY m WHERE SOURCE.MUNICIPALITYCODE = m.MUNICIPALITYCODE)

           WHEN NOT MATCHED BY TARGET
            THEN INSERT (MUNICIPALITYCODE, STREENAME,STREECODE) VALUE ((SELECT m.MUNICIPALITYCODE FROM MUNICIPALITY m WHERE SOURCE.MUNICIPALITYCODE = m.MUNICIPALITYCODE),SOURCE.STREETCODE,SOURCE.STREETCODE)

        COMMIT
    END TRY
    begin catch
        # I'm not able to figure this part out.
        INSERT INTO STREET_FALLOUT (MUNICIPALITYCODE, STREENAME,STREECODE,ERRORREASON) VALUES (SOURCE.MUNICIPALITYCODE,STREETNAME,STREETCODE,ERROR_MESSAGE())
    end catch

标签: sql-serverexceptionupsert

解决方案


你正在接近这个错误。无法插入某些行并捕获其他行的错误。

相反,只需查询不匹配的行,并仅合并匹配的行。

  • 请注意缺少错误处理,并包含XACT_ABORT ON. 这是正确的方法,因为所有错误都会导致事务回滚。
  • 请注意,SOURCE合并中的表与 预联接MUNICIPALITY,因此只能出现匹配的行。
  • 一个MERGE语句必须有一个分号终止符,无论如何这是一个好习惯。
CREATE PROCEDURE upsertStagingToStreet
AS

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT, NOCOUNT ON;

BEGIN TRAN


INSERT INTO STREET_FALLOUT
    (MUNICIPALITYCODE, STREENAME, STREECODE, ERRORREASON)
SELECT
  SOURCE.MUNICIPALITYCODE,
  SOURCE.STREETCODE,
  SOURCE.STREETCODE,
  'Missing MUNICIPALITYCODE'
FROM STREET_STAGING AS SOURCE
WHERE NOT EXISTS (SELECT 1
    FROM MUNICIPALITY m
    WHERE SOURCE.MUNICIPALITYCODE = m.MUNICIPALITYCODE
);


WITH SOURCE AS (
    SELECT SOURCE.*
    FROM STREET_STAGING AS SOURCE
    JOIN MUNICIPALITY m ON SOURCE.MUNICIPALITYCODE = m.MUNICIPALITYCODE
)
MERGE STREET AS TARGET
USING SOURCE
  ON (TARGET.correlationkey = SOURCE.correlationkey)

WHEN MATCHED THEN
  UPDATE SET
    Qty = SOURCE.Qty,
    MUNICIPALITYCODE = SOURCE.MUNICIPALITYCODE

WHEN NOT MATCHED BY TARGET THEN
  INSERT (MUNICIPALITYCODE, STREENAME, STREECODE)
  VALUES (SOURCE.MUNICIPALITYCODE, SOURCE.STREETCODE, SOURCE.STREETCODE)
;

COMMIT;

GO

推荐阅读