SQL Server:USE数据库优先级问题

时间:2013-11-20 17:00:30

标签: sql tsql sql-server-2005

当语句在if..else语句中时,我遇到使用USE Database; GO的问题。我的猜测是USE Database; GO假设在脚本或sql语句的顶部使用。

也许有人可以帮我提出一种不同的方法来解决这个问题,我要做的是,检查特定数据库是否存在,如果它确实从该特定数据库中删除了特定用户访问权限。我想这样做的方式如下......

IF EXISTS(select * from sys.databases where name='MyDB')
 BEGIN
   USE MyDB
   GO
   DROP USER [tester]
   .
   .
   .
 END
ELSE
 PRINT 'MyDB database is not available'

我把sql脚本切成了一个较小的版本所以我不会弄乱这篇文章,所以请注意在DROP USER

之后还有一些其他的逻辑被遗漏了

EDITED: 我已经尝试了各种方法来检查数据库是否存在,所以每个人都知道 试图

if db_id('MyDB') is not null
or
if object_id('MyDB', 'U')

但是,它总是直接转到use MyDb,我不知道为什么以及如何解决它。

2 个答案:

答案 0 :(得分:1)

以下工作对我来说没问题(给出了所有预期的结果,我也在USE之后用一些select语句进行了测试,当找到DB时工作正常,如果DB超出预期的范围则抛出错误)< / p>

USE master
IF EXISTS(select * from sys.databases where name='SomeDatabase') BEGIN
   USE SomeDatabase
   print 'Database available'
END ELSE
 PRINT 'Database is not available'

您能否进一步解释您的期望和所看到的内容?

更新

这也可行:

USE master
IF EXISTS(select * from sys.databases where name='SomeDatabase') BEGIN
   USE SomeDatabase
   print 'Database available'
   print 'more stuff'
   print 'even more stuff'

END ELSE
 PRINT 'Database is not available'

然而:

USE master
IF EXISTS(select * from sys.databases where name='SomeDatabase') BEGIN
   USE SomeDatabase
   print 'Database available'
   print 'more stuff'
   print 'even more stuff'

END ELSE
 PRINT 'Database is not available'
 print 'something else when the db is unavail' -- This line will always print regardless

更新:我也可以这样做(仅供参考我在2008年管理工作室运行)

USE master
IF EXISTS(select * from sys.databases where name='JMCExpenseService')
 BEGIN
   USE SomeDatabase       
   select * from SomeTableInSomeDatabase

   USE AnotherDatabase
   SELECT * FROM TableInAnotherDatabase    

   USE SomeDatabase       
   select * from SomeOtherTableInSomeDatabase

END
ELSE
 PRINT 'MyDB database is not available'

我得到3个带有预期数据的结果集 - 不确定这是否适用于2005年,但我不明白为什么不这样做。你是如何执行查询的?

编辑:

我看到了我的问题 - 如果数据库不存在会死掉,我使用USE SomeDatabase2来测试它,而实际上我确实有一个叫做这个的数据库。如果DB实际上不存在,这完全会窒息!我想动态SQL是完成这项工作的唯一方法(我厌恶动态SQL)

答案 1 :(得分:1)

如评论中所述,您不能将GO置于一组彼此依赖的SQL语句的中间,因为:

  1. GO表示一个已编译批处理的结束和下一个批处理的开始。大多数语句上下文(如IF..ELSE)不能跨越GO。和,

  2. GO甚至不是SQL语句,它是Management Studio / SQLCMD命令,因此在其他任何地方都无法识别。

  3. 您的情况是一种常见的需求,但没有一种解决方案。对于您列出的特定情况,使用动态SQL可能是最好的方法:

    IF EXISTS(select * from sys.databases where name='MyDB')
     BEGIN
       EXEC('
         USE MyDB
         EXEC(''
           DROP USER [tester]
            .
            .
            . 
         '')  
       ')
     END
    ELSE
     PRINT 'MyDB database is not available'
    

    这充分利用了这样一个事实:动态SQL执行每个都构成了自己的批处理,以替换GO的效果(开始新的批处理)并隔离USE与编译器的特殊交互。当然,这很奇怪,因为需要在USE..GO命令之后“双重包装”。

    另请注意,由于这种双重包装,其中的任何字符串都必须是四重引用。