主键冲突错误后继续

时间:2009-06-28 10:44:56

标签: sql sql-server database tsql stored-procedures

问题出在导入例程期间从登台表插入数据时。

系统是我继承的遗留系统,短期内我开发更合适的东西我想修补东西以避免数据传输失败。

不幸的是,该工具通过另一个应用程序存在,以创建一个名为CommReceipt的表入口。密钥称为CR_Key。如果发生这种情况,那么当自动例程运行插入时,比如我们需要从另一个已经定义了CR_Key值的系统(不是我的系统)导入1000行,它就会失败。

我看到它的方式我有几种选择,但所有建议都将受到赞赏,以便为此问题提供最佳解决方案(长期和短期修复)。

这是消除流氓应用程序功能的计划的一部分(但这是一个遗留系统,用传统的非语言语言编写,可能需要一些努力)

如何处理主键违规。我可以继续,在运行数据插入后报告违规行为。

更新:主键CR_Key也恰好是一个标识,有没有办法删除不应该存在的行并使用相同的ID插入行。我推测....我关闭身份,然后在'缺失行'中指定唯一值,这是否合理? 我现在不需要自动增加id,插入例程有ID

由于

5 个答案:

答案 0 :(得分:4)

您可以使用而不是插入触发器。在触发器内部,对表进行插入,其中不存在CommReceipt.CR_Key = inserted.CR_Key。

Create trigger T_CommReceiptInsteadOfInsert on CommReceipt
Instead of Insert
As
Begin

--Insert duplicate records into another table
Insert Into CommReceipt_Duplicates(CR_Key, ...)
Select CR_Key, ...
From inserted i
Where exists (select * from CommReceipt c Where c.CR_Key = i.CR_Key)

--Insert non duplicate records
Insert Into CommReceipt(CR_Key, ...)
Select CR_Key, ...
From inserted i
Where not exists (select * from CommReceipt c Where c.CR_Key = i.CR_Key)

End

答案 1 :(得分:1)

也许您可以使用触发器来验证插入是否可以完成(PK不存在)。如果PK已经存在,您可以将一些信息作为日志存储在其他表中,并取消插入以进行回滚并启动异常。

答案 2 :(得分:1)

首先,我假设PK冲突是偶然的,并且新插入的行确实是独立的实体(而不是最好由UPDATE处理的东西。其次,我是假设您不能删除该主键并处理与批量插入后运行的作业的“键”冲突(或者完全使用备用主键)。

如果您在主键列上使用identity,则可以选择一些选项(在这种情况下,您的旧应用必须使用IDENTITY INSERT绕过身份才能获得成功的行) :

  • 您可以使用与CommReceipt相同的架构创建新表,并在该表上放置INSTEAD OF触发器,剥离主键并插入CommReceipt。然后调整遗留应用程序以插入到新表中。

  • 您可以将CommReceipt表上的身份种子调整为遗留应用程序流氓密钥范围之外的大量数据。这应被视为短期解决方案。

如果您没有使用身份,那么我假设您从遗留应用无法访问的其他逻辑中获取您的PK值。如果是这种情况,那么除了修复遗留应用程序之外别无选择,或者为其行使用独立的数据存储。

答案 3 :(得分:0)

违反PK约束是sqlserver中的一个严重错误,根据BOL for sqlserver 2000是14级,因此不被认为是致命的,但这是一个试验/错误系统:错误的严重性级别指示sqlserver将对正在进行的事务执行什么操作:如果严重性级别足够高,它将在服务器级别终止事务,并且您只能从头开始重新启动它。

答案 4 :(得分:0)

我的建议是修改外部导入例程,以便省略外部生成的CR_key,并使用与其他人使用的相同的自动生成密钥。

您可能需要扭曲事物才能获得此结果。例如,您可能必须使外部输入完成到临时表,然后使用触发器插入到真实表中,但您将丢弃的CR_key除外。

以这种方式做事会产生后果,根据要求,它们可能是负面的。通常,主表中的数据与旧系统中的其余数据之间不会存在连接。如果有人尝试跨数据库进行内部联接,那么他们就会遭受粗暴的打击。我可怜他们,但不是很多。

extrnally提供的CR_key中可能有一些信息。这是PK的糟糕设计,但它确实发生了,特别是在遗留系统中。

祝你好运。