如何跳过唯一约束违规

时间:2016-06-12 20:10:45

标签: c# asp.net transactions informix unique-constraint

如果我将bulk insert作为交易的一部分,请执行以下操作:

cmdTxt.Clear();
cmdTxt.Append(" INSERT INTO  sc1pen ");
cmdTxt.Append(" SELECT action_month,action_year,200,emp_num,penalty_action , ");
cmdTxt.Append("  'APPLY ' || penalty_reason || ' day ' , 0 , 0 ");
cmdTxt.Append(" FROM sc2pen WHERE sal_year = ? and sal_month = ? and penalty_type = 1 and pay_type = 0 ");
myIfxCmd.CommandText = cmdTxt.ToString();

myIfxCmd.Parameters.Clear();

myIfxCmd.Parameters.Add("sal_year", IfxType.Integer);
myIfxCmd.Parameters.Add("sal_month", IfxType.Integer);

myIfxCmd.Parameters[0].Value = penaltyDt.Rows[0]["sal_year"];
myIfxCmd.Parameters[1].Value = penaltyDt.Rows[0]["sal_month"];

myIfxCmd.ExecuteNonQuery(); 

如果在此插入期间unique constraint violated如何避免回滚整个事务,我想要而不是跳过导致此唯一约束异常的行并恢复插入过程。

1 个答案:

答案 0 :(得分:1)

有点难以猜测问题中两个表的模式是什么,但我们可以针对这些猜测做出一些猜测和测试代码。

半合理的模式

CREATE TEMP TABLE sc1pen
(
    action_month   INTEGER NOT NULL,
    action_year    INTEGER NOT NULL,
    unidentified_1 INTEGER NOT NULL,
    emp_num        INTEGER NOT NULL,
    penalty_action INTEGER NOT NULL,
    penalty_string VARCHAR(30) NOT NULL,
    unidentified_2 INTEGER NOT NULL,
    unidentified_3 INTEGER NOT NULL
);

CREATE TEMP TABLE sc2pen
(
    action_month   INTEGER NOT NULL,
    action_year    INTEGER NOT NULL,
    unidentified_1 INTEGER NOT NULL,
    emp_num        INTEGER NOT NULL,
    penalty_action INTEGER NOT NULL,
    penalty_string VARCHAR(30) NOT NULL,
    penalty_reason VARCHAR(30) NOT NULL,
    unidentified_2 INTEGER NOT NULL,
    unidentified_3 INTEGER NOT NULL,
    sal_year       INTEGER NOT NULL,
    sal_month      INTEGER NOT NULL,
    penalty_type   INTEGER NOT NULL,
    pay_type       INTEGER NOT NULL
);

INSERT语句的翻译

这是来自问题的INSERT语句的翻译。

INSERT INTO sc1pen 
    SELECT action_month, action_year, 200 AS unidentified_1, emp_num, penalty_action,
           'APPLY ' || penalty_reason || ' day ' AS penalty_string,
           0 AS unidentified_2, 0 AS unidentified_3
      FROM sc2pen
     WHERE sal_year = 2016 AND sal_month = 4 AND penalty_type = 1 AND pay_type = 0;

由于我使用的是命令行工具,而不是嵌入式SQL或类似工具,因此我不得不使用值替换问号 - 2016年为sal_year,4为sal_month

可能的MERGE声明

MERGE INTO sc1pen AS dst
    USING (
        SELECT action_month, action_year, 200 AS unidentified_1, emp_num, penalty_action,
               'APPLY ' || penalty_reason || ' day ' AS penalty_string,
               0 AS unidentified_2, 0 AS unidentified_3
          FROM sc2pen
         WHERE sal_year = 2016 AND sal_month = 4 AND penalty_type = 1 AND pay_type = 0
    ) AS src
    ON dst.action_month = src.action_month AND
       dst.action_year = src.action_year AND
       dst.emp_num = src.emp_num
    WHEN NOT MATCHED THEN INSERT VALUES(src.action_month, src.action_year,
                src.unidentified_1, src.emp_num, src.penalty_action,
                src.penalty_string, src.unidentified_2, src.unidentified_3)
    ;

这主要是阅读手册'在MERGE声明中。

ON条款似乎是半合理的;由于表中没有主键的标识,我们必须猜测连接条件应该是什么。