在存储过程中创建唯一ID以匹配旧数据

时间:2014-07-07 15:24:25

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

创建CRUD程序,复制遗留程序,根据“下一个ID”生成唯一ID。字段在一个单独的表中。我没有复制使用单独的表,而是编写了一个存储过程来读取表中的行数。

CREATE PROCEDURE [TLA_CreateItem] 
    @SiteReference varchar(50)
    ,@ItemID varchar(4)
    ,@NewUniqueID varchar(68) OUTPUT
AS
BEGIN
    DECLARE @Rows varchar(12)
    SET @Rows = (CONVERT(varchar(12), (SELECT Count(UniqueID) FROM [TLA_Items]) + 1))

    SET @NewUniqueID = @ItemID + @SiteReference + @Rows

    INSERT INTO [TLA_Items] ([ItemID], [UniqueID])
    VALUES (@ItemID, @NewUniqueID)

    SELECT @NewUniqueID
END

我已经简化了上面的代码,但未显示的是TLA_Items表还有一个IDENTITY列,并且它需要与SQL Server 2008一起使用。< / p>

UniqueID字段必须与旧版程序的模式匹配:ItemID + SiteReference + (integer representing number of previous records)

然而,在测试这个时,我发现了我的逻辑缺陷。如果删除行,则可以创建与现有行匹配的唯一ID。这在遗留系统中不会发生,因为很少删除行,而单独的表存储序列中的下一个数字。

除了将下一个ID值存储在单独的表中之外,是否有更好的技术来创建与传统​​模式匹配的唯一ID?

3 个答案:

答案 0 :(得分:2)

您可以让您的过程仅将前缀(@ItemID + @SiteReference)存储到UniqueID中,并使用FOR INSERT触发器将IDENTITY值作为组件追加到插入行,如下所示:

CREATE TRIGGER TLA_Items_Adjust
  ON dbo.TLA_Items
  FOR INSERT
AS
BEGIN
  UPDATE t
  SET t.UniqueID = i.UniqueID + CAST(t.IdentityColumn AS varchar(10))
  FROM dbo.TLA_Items AS t
  INNER JOIN inserted AS i
    ON t.IdentityColumn = i.IdentityColumn
  ;
END

要读取并返回新生成的UniqueID值作为OUTPUT参数以及行,您可以在INSERT语句中使用表变量和OUTPUT子句,如下所示:

CREATE PROCEDURE [TLA_CreateItem] 
    @SiteReference varchar(50)
    ,@ItemID varchar(4)
    ,@NewUniqueID varchar(68) OUTPUT
AS
BEGIN
    DECLARE @GeneratedUniqueID TABLE (UniqueID varchar(68));

    INSERT INTO dbo.[TLA_Items] ([ItemID], [UniqueID])
    OUTPUT inserted.UniqueID INTO @GeneratedUniqueID (UniqueID)
    VALUES (@ItemID, @ItemID + @SiteReference);

    SELECT @NewUniqueID = UniqueID FROM @GeneratedUniqueID;

    SELECT @NewUniqueID;
END

虽然不是使用OUTPUT,但您可能只是从与SCOPE_IDENTITY()结果匹配的行中读取值:

CREATE PROCEDURE [TLA_CreateItem] 
    @SiteReference varchar(50)
    ,@ItemID varchar(4)
    ,@NewUniqueID varchar(68) OUTPUT
AS
BEGIN
    INSERT INTO dbo.[TLA_Items] ([ItemID], [UniqueID])
    VALUES (@ItemID, @ItemID + @SiteReference);

    SELECT @NewUniqueID = UniqueID
    FROM dbo.TLA_Items
    WHERE IdentityColumn = SCOPE_IDENTITY();

    SELECT @NewUniqueID;
END

答案 1 :(得分:2)

以下是另一种选择,但请注意会影响现有的UniqueID

如果您可以对表架构进行轻微更改,则可以添加一个名为UniqueIDPrefix的列:

ALTER TABLE dbo.TLA_Items
ADD UniqueIDPrefix varchar(56) NOT NULL;

并将UniqueID列重新定义为计算列:

ALTER TABLE dbo.TLA_Items
DROP COLUMN UniqueID;

GO

ALTER TABLE dbo.TLA_Items
ADD UniqueID AS UniqueIDPrefix + CAST(IdentiyColumn AS varchar(12));

在您的存储过程中,您需要填充UniqueIDPrefix而不是UniqueID(只有@ItemID + @SiteReference的结果)

INSERT INTO dbo.[TLA_Items] ([ItemID], [UniqueIDPrefix])
VALUES (@ItemID, @ItemID + @SiteReference);

并使用OUTPUT或SCOPE_IDENTITY()读取UniqueID的值,如my other answer中所示。

答案 2 :(得分:0)

这听起来像是在使用SQL 2008,但是如果你在2012年,你可以使用一个序列来存储递增值。

从不删除怎么样?您可以在表中添加一个标志以进行逻辑删除。