2010-07-14 83 views
2

长时间阅读器,第一次海报;-)而不是触发器更新主键

我正在实现一个基于旧系统的系统。新系统使用SQL Server 2008,当尝试在主表中插入新项目时出现问题。这将以两种方式发生:它可以从现有系统导入(1)或可以在新系统(2)中创建。

如果(1)该项目已经有我想保留的ID(int)。如果(2)ID不填写,我想生成一个ID,它是表中最大当前值的+1。这当然也适用于多行插入。

据我所见,解决方案将创建一个INSTEAD OF TRIGGER,但我无法弄清楚这是如何完成的。任何人都可以给我一个提示或者指导我如何做到这一点?

克里斯

回答

1

按照您的请求使用INSTEAD触发这个SQL代码可以让你开始。

CREATE TABLE dbo.SampleTable 
(
    ID INT, 
    SomeOtherValue VARCHAR(100) NULL 
) 
GO 

CREATE TRIGGER dbo.TR_SampleTable_Insert 
    ON dbo.SampleTable 
    INSTEAD OF INSERT 
AS 
BEGIN 

    SET NOCOUNT ON; 

    -- Inserting rows with IDs 
    INSERT INTO dbo.SampleTable (
     ID, 
     SomeOtherValue) 
    SELECT 
     ID, 
     SomeOtherValue 
    FROM 
     Inserted  
    WHERE 
     ID IS NOT NULL 

    -- Now inserting rows without IDs 
    INSERT INTO dbo.SampleTable (
     ID, 
     SomeOtherValue) 
    SELECT 
     (SELECT ISNULL(MAX(ID), 0) FROM dbo.SampleTable) 
      + ROW_NUMBER() OVER(ORDER BY ID DESC), 
     SomeOtherValue 
    FROM 
     Inserted 
    WHERE 
     ID IS NULL 

END 
GO 

INSERT INTO dbo.SampleTable 
SELECT 1, 'First record with id' 
UNION 
SELECT NULL, 'First record without id' 
UNION 
SELECT 2, 'Second record with id' 
UNION 
SELECT NULL, 'Second record without id' 
GO 

SELECT * FROM dbo.SampleTable 
GO 
+0

我完全同意以前的意见,不推荐将旧ID与新ID混合。 – JCallico 2010-07-14 16:14:26

+0

谢谢 - 只是我正在寻找的那种例子:-) 关于ID的混合,我看到了不足之处 - 但是这个项目也给这个方法带来了一些缺点,与这个技术问题无关。 – 2010-07-15 07:26:01

+0

很高兴我能够帮助。这就是为什么我实现了你原来所要求的,而不是立即建议一种替代方法,只是为了跳跃才能获得积分。这些日子似乎是StackOverflow的趋势。 – JCallico 2010-07-15 17:10:53

1

如何使用存储过程做你插入,与主键作为可选的参数。在存储过程中,您可以在主键未通过时进行设置。

我会提醒的是,如果新旧记录插入混合匹配,您的方案可能会失败,因为新记录会在插入旧记录之前变旧。我建议立即获取旧表的最大ID,并在存储过程中将新主键设置为(旧max + 1,当前表最大值)的较大值

+0

我认为这是一种可能性,但我发现触发器解决方案是一个更干净的解决方案,如果有可能实现的话。如果不是的话,我一定会选择存储过程解决方案。 关于ID崩溃 - 我知道这个问题,并且我将生成足够大的新ID以防止崩溃(为了简单起见,我只是将这部分留下了)。或者,至少不会再过75年 - 这应该足以满足明年某个时间废弃堆的系统的需要;-) – 2010-07-14 14:20:10

+0

我想也许我误解了你对新老ID的评论。而且我认为我没有足够好地描述这种情况。旧系统将继续生成新项目,因此即使在新系统投入生产后,旧系统的ID也会继续增加。直到所有功能都移植完毕,旧系统才会被废弃。 – 2010-07-14 14:37:13

+0

@Chris - 对,我刚才问你为什么你不能导入所有的旧记录,并做了它,但这解释了它。 – 2010-07-14 14:40:44

0

其他人已经告诉你如何写这种触发器。

另一种经常推荐的方法是将两个ID都存储在新数据库中。每个记录在新系统中获得新的ID(通过IDENTITY列或其他方式)。此外,如果记录是从另一个系统导入的,则它具有关联的OriginSystem和OriginID。这样您可以保留旧ID以供参考。这种方法的另一个好处是能够支持新的系统从数据库导入数据。当合并或交换数据与另一个系统。

+0

这就是我会如果提出相同的问题。 – JCallico 2010-07-14 16:57:40

+0

感谢您的评论。该解决方案已经考虑。由于这里没有描述项目的细节,这会使数据模型更加复杂(旧系统有其他后备系统也需要处理)。这个问题的最终解决方案尚未决定 - 但很高兴知道触发解决方案似乎是一种可能性。 – 2010-07-15 07:31:48