【问题标题】:creating a table if it doesn't exist如果表不存在则创建表
【发布时间】:2010-12-03 23:20:43
【问题描述】:

鉴于以下情况:

if object_id('MyTable') is null create table MyTable( myColumn int )

两个单独的调用者不可能都将 object_id('MyTable') 评估为 null 并且都尝试创建表。

显然,该场景中的两个调用者之一会失败,但理想情况下,任何调用者都不应该失败,而是一个应该阻塞,另一个应该创建表,然后被阻塞的调用者将看到 object_id('MyTable') 不为 null 并且继续。

我可以在什么情况下应用排他锁,这样我的锁就不会超过绝对需要的?

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql transactions


    【解决方案1】:

    经过初步检查,创建表时使用try catch,如果错误是表已经存在,则继续,如果不存在,则问题更大

    【讨论】:

      【解决方案2】:

      通常CREATE TABLE 是从设置和安装脚本运行的,期望安装脚本允许从单独的连接进行并发安装是不合理的。

      我建议您使用在安装/升级过程开始时获取的会话范围应用锁,请参阅sp_getapplock

      【讨论】:

        【解决方案3】:

        我不认为,你应该担心这个。

        DDL 语句不在事务下运行。此外,如果表已经由第一个调用者的调用创建,那么第二个调用者将失败。

        【讨论】:

        • 不知何故不用担心第二个调用者将失败而感到高兴是一点安慰。我宁愿第二个调用者继续没有错误
        • @Ralph:有道理。这个过程多久执行一次?为什么要在过程中创建表?这是一个表,你会在程序结束时删除吗?如果没有,为什么不预先创建一个真正的表呢?请解释一下你为什么要这样做?
        【解决方案4】:

        我不允许用户创建表。一般来说,这是一个不好的做法。如果他们需要插入数据,表已经存在。如果您担心两个人创建同一张表,您是否还担心他们的数据是否交叉?我不知道你的 proc 做了什么,但如果它在表存在时删除记录然后插入,那么如果两个用户同时打开,你可能会遇到奇怪的结果。不过一般来说,如果您需要在运行时创建 ea 表,这通常表明您的设计需要工作。

        【讨论】:

        • -1 答案是假定设计的优点。然而,问题是实现细节的问题。
        • 当我们看到一个糟糕的设计时,我们有责任指出问题可能出在设计上,而不仅仅是您提出问题的实现细节。
        • @HLGEM 在这种情况下,系统要求是使用此数据库的多线程服务可能会或可能不会配置为在审计表中记录错误信息。如果配置为记录此审计信息,则假定创建表。如果未配置,则错误审计表不应该存在,因为现有但为空的审计表可能表明系统运行正常并且没有记录错误。简而言之,这就是设计要求。
        猜你喜欢
        • 1970-01-01
        • 2013-05-26
        • 2010-09-19
        • 1970-01-01
        • 2014-11-11
        • 2014-03-17
        • 2016-02-15
        • 2016-09-18
        相关资源
        最近更新 更多