2

我们有一个使用标准模式填充代理键的 Oracle 应用程序。我们有一系列外部行(具有代理键的特定值)和其他具有内部值的行。我们使用以下 Oracle 触发器片段来确定如何处理插入时的代理键:

IF :NEW.SurrogateKey IS NULL THEN

 SELECT SurrogateKey_SEQ.NEXTVAL INTO :NEW.SurrogateKey FROM DUAL;

END IF;

如果提供的代理键为空,则从指定的序列中获取一个值,否则将提供的代理键传递给该行。

我似乎找不到一个简单的方法来做到这一点是 T-SQL。有各种各样的方法,但没有一种方法像 Oracle 和其他符合 SQL-92 的数据库那样使用序列生成器的概念。

有人知道在 SQL Server T-SQL 中执行此操作的一种非常有效的方法吗?顺便说一句,如果有帮助的话,我们正在使用 SQL Server 2008。

4

3 回答 3

2

您可能想查看 IDENTITY。这为您提供了一个列,当您插入该行时将确定该列的值。

这可能意味着您必须插入行,然后使用 SCOPE_IDENTITY() 确定值。

这里还有一篇关于在 SQL Server 中模拟 Oracle 序列的文章:http ://www.sqlmag.com/Articles/ArticleID/46900/46900.html?Ad=1

于 2009-02-27T06:48:06.087 回答
0

身份是一种方法,尽管它会在每个表级别生成唯一标识符。

另一种方法是使用唯一标识符,特别是使用 NewSequantialID() 确保生成的 id 总是大于最后一个。这种方法的问题是您不再处理整数。

模拟 oracle 方法最接近的方法是拥有一个带有计数器字段的单独表,然后编写一个用户定义的函数来查询该字段,将其递增并返回值。

于 2009-02-27T06:56:26.910 回答
0

这是一种使用表格来存储您的最后一个序列号的方法。存储过程非常简单,里面的大部分东西都是因为我很懒,如果我忘记了什么不喜欢惊喜,所以......这里是:

----- 创建序列值表。

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[SequenceTbl]
(
  [CurrentValue] [bigint]
) ON [PRIMARY]

GO

-----------------创建存储过程

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE procedure [dbo].[sp_NextInSequence](@SkipCount BigInt = 1)
AS

BEGIN

  BEGIN TRANSACTION

    DECLARE @NextInSequence BigInt;

    IF NOT EXISTS
    (
      SELECT
        CurrentValue
      FROM
        SequenceTbl
    )

    INSERT INTO SequenceTbl (CurrentValue) VALUES (0);

    SELECT TOP 1
      @NextInSequence = ISNULL(CurrentValue, 0) + 1
    FROM
      SequenceTbl WITH (HoldLock);

    UPDATE SequenceTbl WITH (UPDLOCK)
      SET CurrentValue = @NextInSequence + (@SkipCount - 1);

  COMMIT TRANSACTION

  RETURN @NextInSequence
END;
GO

--------使用 Sql Manager 中的存储过程来检索测试值。

declare @NextInSequence BigInt

exec @NextInSequence = sp_NextInSequence;

--exec @NextInSequence = sp_NextInSequence <skipcount>;

select NextInSequence = @NextInSequence;

-----显示当前表值。

select * from SequenceTbl;

精明的人会注意到存储过程有一个参数(可选)。这是为了允许调用者在调用者有多个需要唯一 id 的记录的情况下保留一个 ID 块 - 使用 SkipCount,调用者只需调用一次即可,但需要许多 ID。如果您记得在创建表时插入一条记录,则可以删除整个“IF EXISTS...INSERT INTO...”块。如果您还记得使用值插入该记录(您的种子值 - 一个永远不会用作 ID 的数字),您还可以删除选择的 ISNULL(...) 部分并仅使用 CurrentValue + 1。现在,在任何人发表评论之前,请注意我是软件工程师,而不是dba!所以,任何建设性的欢迎批评使用“Top 1”、“With (HoldLock)”和“With (UPDLock)”。我不知道这将如何扩展,但到目前为止这对我来说还可以......

于 2010-07-25T22:47:23.760 回答