【问题标题】:Insert into error table if the rows violates primary key如果行违反主键,则插入错误表
【发布时间】:2021-04-26 17:28:38
【问题描述】:

我有这张桌子:

CREATE TABLE TEST 
(
    ID INT NOT NULL,
    C_status INT NOT NULL,
    SS VARCHAR(10),

    CONSTRAINT [PK_TBL] 
        PRIMARY KEY CLUSTERED ([ID] ASC, [C_status ] ASC, [SS ] ASC)
)

现在我正在尝试使用

向此表中插入一些值
INSERT INTO SELECT ...

数据中会有重复。如何仅在一个表中插入唯一值并在另一表中插入重复值。例如,如果我执行以下操作

INSERT INTO TEST
SELECT '1','90','PARIS'
UNION ALL
SELECT '1','90','PARIS'
UNION ALL
SELECT '2','90','PARIS'

我想在TEST2nd row 中插入1st 行和3rdTEST_ERROR。这可能与 SQL 查询。我的预期输出是

TEST

ID C_STATUS SS
1 90 PARIS
2 90 PARIS

TEST_ERROR

ID C_STATUS SS
1 90 PARIS

我已经尝试了类似下面的方法,但它显然不起作用

BEGIN TRY
insert into test
SELECT '1','90','PARIS'
UNION ALL
SELECT '1','90','PARIS'
UNION ALL
SELECT '2','90','PARIS'
END TRY
BEGIN CATCH
insert into test
.........
END CATCH

【问题讨论】:

  • 对传入数据进行分组以从传入数据中删除重复数据,并使用不存在以避免插入重复数据。

标签: sql sql-server sql-server-2012


【解决方案1】:

当您作为批处理插入时,它是全有或全无操作。您不能专门将错误行发送到错误文件。如果你想在行级别做,你必须有 CURSOR 来发送错误行。

但是,您可以应用 ROW_NUMBER() 并过滤重复数据并发送到错误表。

--duplicate data 
;with cte_alldata(id, c_status, ss) as
(
SELECT '1','90','PARIS'
UNION ALL
SELECT '1','90','PARIS'
UNION ALL
SELECT '2','90','PARIS'
)
, cte_distinctdata as
(
SELECT *, row_number() over(partition by id, c_status, ss order by id) as rnk
FROM cte_alldata
)
INSERT INTO Error_Table
SELECT id, c_status, ss from cte_distinctdata where rnk >1
id c_status ss
1 90 PARIS

【讨论】:

    【解决方案2】:

    您可以在TEST 上创建INSTEAD OF INSERT 触发器。使用ROW_NUMBER() 窗口函数来识别那些重复项,并且只将其中一行插入TEST,将那些重复项插入TEST_ERROR

    CREATE TRIGGER TR_TEST 
    ON TEST
    INSTEAD OF INSERT
    AS
    BEGIN
        INSERT INTO TEST (ID, C_status, SS)
        SELECT  ID, C_status, SS
        FROM
        (
            SELECT  ID, C_status, SS
                    RN = ROW_NUMBER() OVER(PARTITION BY ID, C_status, SS ORDER BY ID)
            FROM    INSERTED
        ) i
        WHERE   i.RN    = 1
    
        INSERT INTO TEST_ERROR (ID, C_status, SS)
        SELECT  ID, C_status, SS
        FROM
        (
            SELECT  ID, C_status, SS, 
                    RN = ROW_NUMBER() OVER(PARTITION BY ID, C_status, SS ORDER BY ID)
            FROM    INSERTED
        ) i
        WHERE   i.RN    > 1
    END
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-16
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 2015-04-20
      相关资源
      最近更新 更多