如果行违反主键,则插入错误 table
Insert into error table if the rows violates primary key
我有这个 table:
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)
)
现在我正在尝试使用
向这个table中插入一些值
INSERT INTO SELECT ...
数据中会有重复项。如何仅在一个 table 中插入唯一值并在另一个 table 中插入重复值。例如,如果我执行以下
INSERT INTO TEST
SELECT '1','90','PARIS'
UNION ALL
SELECT '1','90','PARIS'
UNION ALL
SELECT '2','90','PARIS'
我想在 TEST
中插入 1st
行和 3rd
行,在 TEST_ERROR
中插入 2nd row
行。 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
批量插入时,是全有或全无操作。您不能专门将错误行发送到错误文件。如果你想在行级别做,你必须有 CURSOR 来发送错误行。
但是,您可以应用 ROW_NUMBER() 并过滤重复数据并发送至错误 table。
--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
您可以在 TEST
上创建 INSTEAD OF INSERT
触发器。使用 ROW_NUMBER()
window 函数来识别那些重复项,并且仅将其中一行插入 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
我有这个 table:
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)
)
现在我正在尝试使用
向这个table中插入一些值INSERT INTO SELECT ...
数据中会有重复项。如何仅在一个 table 中插入唯一值并在另一个 table 中插入重复值。例如,如果我执行以下
INSERT INTO TEST
SELECT '1','90','PARIS'
UNION ALL
SELECT '1','90','PARIS'
UNION ALL
SELECT '2','90','PARIS'
我想在 TEST
中插入 1st
行和 3rd
行,在 TEST_ERROR
中插入 2nd row
行。 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
批量插入时,是全有或全无操作。您不能专门将错误行发送到错误文件。如果你想在行级别做,你必须有 CURSOR 来发送错误行。
但是,您可以应用 ROW_NUMBER() 并过滤重复数据并发送至错误 table。
--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 |
您可以在 TEST
上创建 INSTEAD OF INSERT
触发器。使用 ROW_NUMBER()
window 函数来识别那些重复项,并且仅将其中一行插入 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