在动态SQL中使用时,USE DATABASE_NAME不会更改数据库

时间:2013-05-06 08:06:41

标签: sql sql-server sql-server-2008 tsql

我可以使用以下查询检索单个数据库

Select Table_catalog[Instance Name],
Table_name[Database Table],
Column_name[Column],
Data_type[Column Type] 
FROM information_schema.columns
where Data_type in ('varchar')
Order by Table_name,Data_type

但我想列出服务器中所有可用数据库

  Declare @I int =1,@Qry nVarchar(1000),@DatabaseName nvarchar(100)
   Declare @TempTable Table
(
 Sno Int Identity(1,1),
  DatabaseName Varchar(100)
 )
    Insert into @TempTable
    Select name 
    from sys.databases
    where database_id>4
 Select * from @TempTable
    While(@i<=(Select max(sno) from @TempTable))
        Begin

            Select @DatabaseName=DatabaseName from @TempTable where sno=@i

                Select @DatabaseName
             set  @Qry='Use '+ @DatabaseName
             **exec sp_executesql @Qry**
             set  @Qry= '
                        Select  Table_catalog[Instance Name],
                                Table_name[Database Table],
                                Column_name[Column],
                                Data_type[Column Type] 
                                FROM information_schema.columns
                        where Data_type in (''datetime'',''date'',''time'',''smalldatetime'')
                        Order by Table_name,Data_type'
                 exec sp_executesql @Qry


        Set @i=@i+1
        End

它没有工作,因为使用databasename实际上并没有更改数据库并重复当前正在使用的数据库的结果集..对此有任何建议,

3 个答案:

答案 0 :(得分:2)

动态SQL总是在自己的范围内执行,因此您的USE语句对第二个动态查询没有影响。

这应该适合你(你的循环是不必要的和笨拙的):

declare @Database sysname, @sql nvarchar(max)
declare Databases cursor local fast_forward
for select name from sys.databases where database_id > 4

open Databases
fetch next from Databases into @Database
while @@fetch_status = 0
begin
    set @sql =  'Select  
                    Table_catalog [Instance Name],
                    Table_name [Database Table],
                    Column_name [Column],
                    Data_type [Column Type] 
                FROM 
                    ' + quotename(@Database) + '.information_schema.columns
                where 
                    Data_type in (''datetime'',''date'',''time'',''smalldatetime'')
                Order by 
                    Table_name,
                    Data_type'

    exec sp_executesql @sql

    fetch next from Databases into @Database    
end
close Databases
deallocate Databases

答案 1 :(得分:1)

您可以在此任务中使用未记录的过程sp_MSforeachdb。刚刚在我的环境中进行了测试,它完美无缺。

修改

正如Pondlife指出的那样,数据库部分缺少三部分名称语法。添加,现在正常工作。还添加了WHERE子句,以避免在mastermsdbtempdbmodel上搜索不必要的数据库。

EXEC sp_MSforeachdb 
 'SELECT Table_catalog[Instance Name],
         Table_name[Database Table],
         Column_name[Column],
         Data_type[Column Type] 
    FROM ?.information_schema.columns
  WHERE Data_type in (''varchar'')
        AND ''?'' NOT IN (''master'',''msdb'',''tempdb'',''model'')
  ORDER BY Table_name,Data_type'

如果您想了解有关此无证程序的更多信息,请检查herehere。请记住,无证件意味着正式的Microsoft不支持此过程,因此它可能会更改,恕不另行通知。

AdventureWorks2008R2数据库的示例结果:

 Instance Name        Database Table        Column              Column Type
AdventureWorks2008R2    Customer          AccountNumber            varchar
AdventureWorks2008R2    Password          PasswordHash             varchar
AdventureWorks2008R2    Password          PasswordSalt             varchar
AdventureWorks2008R2    SalesOrderHeader  CreditCardApprovalCode   varchar

答案 2 :(得分:0)

感谢@pondlife根据你的建议我可以进行小的更改(从动态查询范围之外传递数据库名称)并且查询返回结果而不是我在循环中使用的游标

      Declare @I int =1,@Qry nVarchar(1000),@DatabaseName nvarchar(100)
       Declare @TempTable Table
    (
     Sno Int Identity(1,1),
      DatabaseName Varchar(100)
     )
        Insert into @TempTable
        Select name 
        from sys.databases
        where database_id>4
     Select * from @TempTable
        While(@i<=(Select max(sno) from @TempTable))
            Begin

                Select @DatabaseName=DatabaseName from @TempTable where sno=@i

                     Select @DatabaseName
                 --set  @Qry='Use '+ @DatabaseName
                 -- exec sp_executesql @Qry**
                 set  @Qry= '
                            Select  Table_catalog[Instance Name],
                                    Table_name[Database Table],
                                    Column_name[Column],
                                    Data_type[Column Type] 
                                    FROM'+quotename(@DatabaseName)+ '. information_schema.columns
                            where Data_type in (''datetime'',''date'',''time'',''smalldatetime'')
                            Order by Table_name,Data_type'
                     exec sp_executesql @Qry


            Set @i=@i+1
            End