【问题标题】:T-SQL Insert into in the BEGIN CATCHT-SQL 在 BEGIN CATCH 中插入
【发布时间】:2021-12-02 22:17:14
【问题描述】:

提前感谢您的帮助。

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

在这段代码中,选择的结果可以为 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

【问题讨论】:

  • 您当前的构造无法完成您想要的工作。 catch 块是一个不同的语句,因此您不能只从合并中获取值。而且这个概念违反了 ACID 的原子部分。这意味着您不能任意插入一些数据而不是其他数据。这都是同一个交易的一部分。
  • 我不认为你可以这样做,instead of 触发器可能会给你你需要的控制。
  • @SeanLange 我害怕这个回复。我实际上已经考虑过这一点,但如果有其他选择,我想要反馈:/我想我需要创建一个实际上避免异常的过程。还是谢谢!

标签: sql-server exception upsert


【解决方案1】:

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

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

  • 请注意缺少错误处理,并包含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

【讨论】:

    猜你喜欢
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2018-09-30
    • 2011-08-26
    • 2011-01-17
    相关资源
    最近更新 更多