内部应用程序需要根据一些提供的标准动态创建SQL表。这个应用程序有多个消费者。
IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'SomeTableName'))
BEGIN
-- Create table in here.
END
要做到这一点,我在sproc中有上面的基本结构。我知道可能的竞争条件,所以我的第一个解决方案是向SELECT语句添加一些锁定提示,以确保在其他事务完成之前阻止检查表存在的所有其他事务。但是,无论我使用哪种提示,这都行不通。
我的下一个解决方案是将表创建包装在TRY..CATCH中,这样即使它确实失败了,我也可以忽略错误。但是,CREATE TABLE语句的失败会导致事务失败,所以即使我忽略了错误,也无法继续。
我的最后一个解决方案是使用TRY..CATCH构造,如果出现错误,那么GOTO创建一个新事务的sproc顶部,一切都很顺利,因为表存在于第二轮
我对解决方案不满意,因为它看起来像是黑客攻击。谁知道这个问题的干净解决方案的任何SQL大师?
为了澄清一点,我上面讨论的解决方案对性能影响不大,所以我真的在寻找一个没有大的性能影响的干净解决方案。
答案 0 :(得分:2)
使用信号量(又名手动锁定)和sp_getapplock(代码顶部)和sp_releaseapplock(代码底部)来确保只有一个进程。
第二个进程将根据您的sp_getapplock参数失败或等待或超时