为我的应用程序生成自定义ID

时间:2016-07-13 04:07:53

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

我想为我的应用程序中的某个功能生成自定义ID。这是执行此操作的过程:

CREATE PROCEDURE [dbo].[GetNextVendorInvoiceNo]
AS
BEGIN

    Declare @StartingVendorInvoiceNo    int = 0

    Select @StartingVendorInvoiceNo = MAX(StartingVendorInvoiceNo) + 1
        From SystemSettings WITH (TABLOCK)

    Update SystemSettings
            Set StartingVendorInvoiceNo = @StartingVendorInvoiceNo  


    Select @StartingVendorInvoiceNo 

END

如果多个用户最终调用此过程,是否会出现任何问题。显然,我不希望多个用户拥有相同的ID。我正在使用TABLOCK,但不确定这是否正确,或者其他任何东西都是必需的。

1 个答案:

答案 0 :(得分:1)

SQL Server 2012具有SEQUENCE功能,对于多用户环境来说绝对安全。但它基于整数类型。

如果您有一个生成“下一个”ID的复杂过程,并且您希望确保在任何时刻只运行该过程的一个实例(以吞吐量为代价),我将使用`sp_getapplock' 。它易于使用和理解,您无需担心放置正确的查询提示。

您的程序如下:

CREATE PROCEDURE [dbo].[GetNextVendorInvoiceNo]
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    BEGIN TRANSACTION;
    BEGIN TRY

        DECLARE @VarLockResult int;
        EXEC @VarLockResult = sp_getapplock
            @Resource = 'GetNextVendorInvoiceNo_app_lock',
            @LockMode = 'Exclusive',
            @LockOwner = 'Transaction',
            @LockTimeout = 60000,
            @DbPrincipal = 'public';

        Declare @StartingVendorInvoiceNo int = 0;

        IF @VarLockResult >= 0
        BEGIN
            -- Acquired the lock, generate the "next" ID
            Select @StartingVendorInvoiceNo = MAX(StartingVendorInvoiceNo) + 1
            From SystemSettings;

            Update SystemSettings
            Set StartingVendorInvoiceNo = @StartingVendorInvoiceNo;

        END ELSE BEGIN
            -- TODO: handle the case when it takes too long to acquire the lock,
            -- i.e. return some error code
            -- For example, return 0
            SET @StartingVendorInvoiceNo = 0;
        END;

        Select @StartingVendorInvoiceNo;

        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
        -- TODO: handle the error
    END CATCH;

END
你写的

简单TABLOCK绝对不够。您需要将所有内容包装到事务中。然后确保锁定一直持续到事务结束,请参阅HOLDLOCK。然后确保你获得的锁是正确的。您可能需要TABLOCKX。因此,总体而言,您需要非常好地理解所有这些提示以及锁定的工作原理。使用这些提示肯定可以达到相同的效果。但是,如果程序中的逻辑比简化示例更复杂,那么很容易变得非常难看。

在我看来,sp_getapplock很容易理解和维护。