SQL 使用 UNIQUE 约束插入多个值

zui*_*iqo 3 sql-server constraint insert sql-server-2012 unique-constraint

我有一个 MS SQL Server 2012 和下表:

CREATE TABLE dzp.contractid (
id bigint PRIMARY KEY IDENTITY(1,1),
VNR char(18) NOT NULL,
CONSTRAINT UC_VNR UNIQUE (VNR))
Run Code Online (Sandbox Code Playgroud)

对于上下文,VNR 表示字符串形式的唯一合同编号。

我想导入一个包含合同信息的 csv 文件,每个合同可能有多行。为了避免查询 char(18),我尝试在加载时使用临时表的 INSERT-Trigger 规范化数据。

流程是:

csv-file --> staging table --> insert trigger --> normalized tables
Run Code Online (Sandbox Code Playgroud)

在我的触发器中,我正在尝试以下操作:

BEGIN TRY
    INSERT INTO dzp.contractid(VNR)
    SELECT VNR
    FROM dzp.accounts_stage
END TRY

BEGIN CATCH
-- ignore unique constraint violation error, raise otherwise
IF ERROR_NUMBER() <> 2627
    RAISERROR ('blah', 16, 1)
END CATCH
Run Code Online (Sandbox Code Playgroud)

所以我希望实现的基本上是:

  1. 从临时表中获取所有合同号
  2. 将所有这些数字添加到规范化表中
  3. 忽略违反唯一约束时抛出的错误
  4. 正常工作时,我现在有一张包含所有唯一 VNR 的表格

问题:

Uniqueness-Constraint 似乎阻止了整个 INSERT,而不仅仅是实际重复的值。

是否有某种方法可以逐行插入数据,或者告诉约束逐行处理它?

这甚至是正确的方法吗?我很高兴完全改变方法,因为我无法想象我是第一个遇到这个问题的人......对于上下文,这本质上是一个每天批量输入一次的报告数据库,总共有大约 100 万行(来自 csv-table),并且有大约 5 个用户不时运行查询。

感谢您的输入!

mus*_*cio 6

SQL 约束违规会影响整个语句,您不能忽略单个行。

可以做的是仅插入不违反约束的行。有几种方法可以做到这一点,例如

INSERT INTO dzp.contractid(vnr)
SELECT DISTINCT vnr FROM dzp.accounts_stage s 
WHERE NOT EXISTS (SELECT 1 FROM dzp.contractid WHERE vnr = s.vnr)
Run Code Online (Sandbox Code Playgroud)

您还可以使用MERGE

MERGE dzp.contractid AS t
USING dzp.accounts_stage AS s
ON (t.vnr = s.vnr) 
WHEN NOT MATCHED BY TARGET 
THEN INSERT(vnr) VALUES(s.vnr)
Run Code Online (Sandbox Code Playgroud)