问题出在导入例程期间从登台表插入数据时。
系统是我继承的遗留系统,短期内我开发更合适的东西我想修补东西以避免数据传输失败。
不幸的是,该工具通过另一个应用程序存在,以创建一个名为CommReceipt的表入口。密钥称为CR_Key。如果发生这种情况,那么当自动例程运行插入时,比如我们需要从另一个已经定义了CR_Key值的系统(不是我的系统)导入1000行,它就会失败。
我看到它的方式我有几种选择,但所有建议都将受到赞赏,以便为此问题提供最佳解决方案(长期和短期修复)。
这是消除流氓应用程序功能的计划的一部分(但这是一个遗留系统,用传统的非语言语言编写,可能需要一些努力)
如何处理主键违规。我可以继续,在运行数据插入后报告违规行为。
更新:主键CR_Key也恰好是一个标识,有没有办法删除不应该存在的行并使用相同的ID插入行。我推测....我关闭身份,然后在'缺失行'中指定唯一值,这是否合理? 我现在不需要自动增加id,插入例程有ID
由于
答案 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的糟糕设计,但它确实发生了,特别是在遗留系统中。
祝你好运。