Sql server Oracle序列,但在MS SQL Server中

Sql server Oracle序列,但在MS SQL Server中,sql-server,oracle,sequence,Sql Server,Oracle,Sequence,在Oracle中,有一种生成序列号的机制,例如: CREATE SEQUENCE supplier_seq MINVALUE 1 MAXVALUE 999999999999999999999999999 START WITH 1 INCREMENT BY 1 CACHE 20; 然后执行该语句 supplier_seq.nextval 检索下一个序列号 如何在MS SQL Server中创建相同的功能 编辑:我不是在寻找自动为表记录生成键的方法。我需

在Oracle中,有一种生成序列号的机制,例如:

CREATE SEQUENCE supplier_seq

    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;
然后执行该语句

supplier_seq.nextval
检索下一个序列号

如何在MS SQL Server中创建相同的功能


编辑:我不是在寻找自动为表记录生成键的方法。我需要生成一个唯一的值,可以用作进程的(逻辑)ID。所以我需要Oracle提供的精确功能。

没有精确匹配

等效的标识可以在创建表时设置为数据类型。SQLSERVER将在插入期间自动创建一个运行序列号。 最后插入的值可以通过调用SCOPE_IDENTITY()或通过查阅系统变量@IDENTITY(正如Frans所指出的)来获得

如果需要完全相同的值,则需要创建一个表,然后编写一个过程来重新运行下一个值和其他操作。请参阅Marks对此陷阱的回应

编辑:
SQL Server实现了与Oracle类似的序列。有关更多详细信息,请参阅此问题


将该字段设置为标识字段。该字段将自动获取其值。您可以通过调用SCOPE_IDENTITY()或查阅系统变量@IDENTITY来获取最后插入的值


SCOPE_IDENTITY()函数是首选函数。

正如DHeer所说,绝对没有精确匹配。如果您试图构建自己的过程来实现这一点,您将不可避免地阻止应用程序进行扩展

Oracle的序列具有高度可扩展性

好的,我稍微收回一点。如果你真的愿意关注并发性,并且你愿意用序列尽可能地将数字打乱顺序,那么你就有机会了。但由于您一开始似乎对t-sql相当不熟悉,所以在(将Oracle应用程序移植到MSSS-这就是您正在做的事情)时,我会开始寻找其他一些选项

例如,只需在“nextval”函数中生成GUID。这将扩大规模


哦,不要对所有的值使用一个表,只是在缓存中保留最大值。您必须将其锁定,以确保提供唯一的值,这就是停止缩放的地方。您必须找出是否有办法在内存中缓存值,并通过编程访问某种轻量级锁—内存锁,而不是表锁。

我希望SQL Server具有此功能。这会让很多事情变得更容易

以下是我如何处理这件事的

创建一个名为tblidenties的表。在此表中,列出最小值和最大值以及序列号应重置的频率。还要输入一个新表的名称(称为tblMySeqNum)。这样做可以使以后添加更多的序列号生成器变得相当容易

tblMySeqNum有两列。ID(一个int标识)和InsertDate(一个日期时间列,默认值为GetDate())

当您需要一个新的seq num时,调用一个插入到此表中的存储过程,并使用SCOPE_IDENTITY()创建标识。确保未超过TBlidenties的最大值。如果有,则返回一个错误。如果没有,请返回序列号

现在,重置和清理。根据需要定期运行作业,检查tblIdentites中列出的所有表(目前仅一个),以查看是否需要重置这些表。如果它们达到了重置值或时间,则对行中列出的表名调用DBCC IDENT RESEED(本例中为tblMySeqNum)。这也是清除表中不需要的额外行的好时机

不要在获取标识的存储过程中进行清理或重新播种。如果这样做,那么序列号生成器将无法很好地伸缩

正如我所说的,在SQL Server中使用此功能会使很多事情变得更简单,但我发现它可以很好地处理函数


瓦卡诺

这可能早就有答案了。。。但从SQL 2005开始,您可以使用
行数
函数。。。例如:

select ROW_NUMBER() OVER (ORDER BY productID) as DynamicRowNumber, xxxxxx,xxxxx
在我的情况下,
OVER
语句使用
orderby
作为唯一主键


希望这有助于。。。不再有临时表或奇怪的连接

Identity是最好的、可扩展性最好的解决方案,但是,如果您需要一个不是递增int的序列,比如00A、00B、00C或某些特殊序列,那么还有第二个最好的方法。如果实现正确,它可以扩展,但是如果实现不好,它的扩展就很差。我不太愿意推荐,但您要做的是:

  • 您必须在表中存储“下一个值”。该表可以是一个简单的、一行一列的表,只包含该值。如果您有多个序列,它们可以共享该表,但如果每个序列都有单独的表,则可能会减少争用
  • 您需要编写一条update语句,将该值以1个间隔递增。您可以将更新放在存储过程中,以使其易于使用,并防止在不同位置的代码中重复更新
  • 正确地使用序列,以便它能够合理地伸缩(不,不,以及一致性:-)需要两件事:a。update语句有一个专门针对这个问题的语法,它将在一个语句中递增并返回值;B您必须在事务开始之前从自定义序列中获取值,并且不在事务范围内。这就是标识可伸缩的原因之一——对于任何尝试的插入,无论事务范围如何,它都会返回一个新值,但在失败时不会回滚。这意味着它不会阻塞,也意味着您将有失败事务的间隙
  • 特殊的update语法因版本而异,但要点是在同一语句中对变量和update进行赋值。2008年,伊兹克·本·甘有一个简洁的解决方案:

    老派2000及以后的方法
    CREATE SEQUENCE supplier_seq
        AS DECIMAL(38)
        MINVALUE 1
        MAXVALUE 999999999999999999999999999
        START WITH 1
        INCREMENT BY 1
        CACHE 20;
    
    SELECT NEXT VALUE FOR supplier_seq
    SELECT NEXT VALUE FOR supplier_seq
    SELECT NEXT VALUE FOR supplier_seq
    SELECT NEXT VALUE FOR supplier_seq
    SELECT NEXT VALUE FOR supplier_seq
    
    ---------------------------------------
    1
    
    (1 row(s) affected)
    
    
    ---------------------------------------
    2
    
    (1 row(s) affected)
    
    
    ---------------------------------------
    3
    
    (1 row(s) affected)
    
    
    ---------------------------------------
    4
    
    (1 row(s) affected)
    
    
    ---------------------------------------
    5
    
    (1 row(s) affected)