在SQL数据库中自动生成唯一列

时间:2014-02-26 07:15:12

标签: sql sql-server

我使用主键(TicketID)作为identity列,每次生成票证时都会自动递增。一切顺利,然后我开始看到我的TicketID从5,6跳到1007,1008。

通过Google搜索,我在SQL Server 2012中找到了这个设计:

http://connect.microsoft.com/SQLServer/feedback/details/743300/identity-column-jumps-by-seed-value

现在我想自定义创建一个列,它会像标识列一样自动递增,但不会跳转并留下空白(我不想要identity列)

我该怎么做?我认为触发器是我正在寻找的,但由于我之前从未使用过触发器,我真的很感激这里的一些帮助。

或者我应该使用计算列吗?

4 个答案:

答案 0 :(得分:2)

创建自己的自动增量机制是一个坏主意。

查看SEQUENCE对象http://technet.microsoft.com/en-us/library/ff878091.aspx

但如果您仍想这样做,一种可能的解决方案

CREATE TABLE dbo.TicketNumber
(
    Number INT NOT NULL
)

INSERT INTO dbo.TicketNumber(Number) VALUES(0)

CREATE PROCEDURE dbo.sp_GenerateTicketNumber
(
    @Number INT OUT
)
AS
BEGIN

    DECLARE @Number INT 
    DECLARE @CurrentNumber INT

    BEGIN TRANSACTION

        SELECT
            @CurrentNumber = Number
        FROM dbo.TicketNumber WITH(UPDLOCK)

        SET @Number = @CurrentNumber + 1

        UPDATE dbo.TicketNumber 
        SET Number = @Number

    COMMIT TRANSACTION

END

dbo.sp_GenerateTicketNumber 的替代实现可能看起来像

DECLARE @number TABLE(number INT);

UPDATE dbo.TicketNumber
SET 
    [Number] = [Number] + 1
OUTPUT INSERTED.Number INTO @number;

SELECT * FROM @number       

您想要的解决方案,可能是

CREATE PROCEDURE dbo.sp_RegisterTicket
(
    @PersonName varchar(255),
    @TicketNumber INT OUT
)
AS
BEGIN

    BEGIN TRAN

        SELECT
            @TicketNumber = MAX(TicketId) + 1
        FROM dbo.Tickets WITH(UPDLOCK)

        INSERT INTO dbo.Tickets VALUES(@TicketNumber, @PersonName)

    COMMIT TRAN

END

使用示例:

DECLARE @Number INT
EXEC dbo.sp_RegisterTicket 'Vasya', @Number OUT

SELECT @Number

答案 1 :(得分:1)

我刚刚使用AFTER INSERT触发器解决了我的问题。 这就是我所做的。

     ALTER TRIGGER [dbo].[tid2]
     ON [dbo].[tblPrac2]
     AFTER INSERT
     AS
     declare @nid int;

     set @nid = ( select MAX(TicketID) from [tblPrac2] );

     if(@nid is null)
     begin
         set @nid = 1;
     end
     else
         set @nid = @nid + 1;

update tblPrac2 set TicketID = @nid where ID in (select ID from inserted)

答案 2 :(得分:0)

我认为您可以使用唯一标识符。

http://technet.microsoft.com/en-us/library/ms187942.aspx

但当然需要更多空间。

答案 3 :(得分:0)

您无法操纵IDENTITY列以保持无间隙。 为了实现您的需求,您必须使用具有单列和行的表来存储TicketID的当前最大值以及用于访问此值的存储过程,如果插入发生则将其增加1,如果发生删除则减1 。 当然,这会影响性能,而不是使用IDENTITY列并忽略差距。