并发表创建

时间:2014-08-27 12:51:44

标签: sql sql-server

有可能从不同的地方创建表格的情况。 所以,我有~10个工作应用程序,可以同时尝试创建一个相同的表。 题。我该如何同步它们?所以我没有任何例外或错误?

应用程序的所有实例都在尝试在当天结束时创建一个新表,所以当有00:00:00这样的时候,他们都会尝试创建它。

对不起,对于可能的'愚蠢的问题',谷歌搜索了一段时间,没有结果。 谢谢。

3 个答案:

答案 0 :(得分:2)

您可以使用sp_getapplock进行任意锁定。您可以在创建表格之前让您的应用程序锁定。像那样:

exec sp_getapplock
if tabledoesnotexist
 create table ...

答案 1 :(得分:0)

正如评论中所提到的,您的第一步是执行存在检查。然后,如果有两个同时创建的可能性,您可以使用TRY...CATCH

IF Object_ID('test', 'U') IS NULL
  BEGIN
    BEGIN TRY
      CREATE TABLE test ( a int )
    END TRY
      BEGIN CATCH
        SELECT Error_Message()
      END CATCH
  END

更新

想要每天创建一个表。认真。这是非常糟糕的数据库设计。

相反,您希望在表格中添加datetime列,以指示每条记录的创建时间。

答案 2 :(得分:-1)

您能否请完成以下代码...使用ISOLATION LEVEL SERIALIZABLE处理并发执行。

     CREATE PROCEDURE [dbo].[GetNextID](
            @IDName nvarchar(255)
        )
        AS
        BEGIN
            /*
                Description:    Increments and returns the LastID value from tblIDs
                for a given IDName
                Author:         Max Vernon
                Date:           2012-07-19
            */

            DECLARE @Retry int;
            DECLARE @EN int, @ES int, @ET int;
            SET @Retry = 5;
            DECLARE @NewID int;
            SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
            SET NOCOUNT ON;
            WHILE @Retry > 0
            BEGIN
                BEGIN TRY
                    BEGIN TRANSACTION;
                    SET @NewID = COALESCE((SELECT LastID FROM tblIDs WHERE IDName = @IDName),0)+1;
                    IF (SELECT COUNT(IDName) FROM tblIDs WHERE IDName = @IDName) = 0 
                        INSERT INTO tblIDs (IDName, LastID) VALUES (@IDName, @NewID)
                    ELSE
                        UPDATE tblIDs SET LastID = @NewID WHERE IDName = @IDName;
                    COMMIT TRANSACTION;
                    SET @Retry = -2; /* no need to retry since the operation completed */
                END TRY
                BEGIN CATCH
                    IF (ERROR_NUMBER() = 1205) /* DEADLOCK */
                        SET @Retry = @Retry - 1;
                    ELSE
                        BEGIN
                        SET @Retry = -1;
                        SET @EN = ERROR_NUMBER();
                        SET @ES = ERROR_SEVERITY();
                        SET @ET = ERROR_STATE()
                        RAISERROR (@EN,@ES,@ET);
                        END
                    ROLLBACK TRANSACTION;
                END CATCH
            END
            IF @Retry = 0 /* must have deadlock'd 5 times. */
            BEGIN
                SET @EN = 1205;
                SET @ES = 13;
                SET @ET = 1
                RAISERROR (@EN,@ES,@ET);
            END
            ELSE
                SELECT @NewID AS NewID;
        END
        GO