T-SQL获取具有某些表

时间:2017-02-28 21:00:15

标签: sql sql-server tsql

我试图获取包含两个具有特定名称的独立表格的所有数据库的列表(在这种情况下,' MasterSchedules','用户')。

我尝试的第一件事是用光标做到这一点:

DECLARE dbCursor CURSOR FOR 
     SELECT name 
     FROM sys.databases 
     WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb')

DECLARE @dbname varchar(max)

OPEN dbCursor

FETCH NEXT FROM dbCursor INTO @dbname

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @stmt nvarchar(max)
    SET @stmt = 'USE ' + @dbname + ';';

    EXECUTE sp_executesql @stmt

    SELECT TABLE_CATALOG, TABLE_NAME
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_TYPE = 'BASE TABLE' 
      AND TABLE_NAME in ('MasterSchedules', 'Users')
    ORDER BY TABLE_SCHEMA + '.' + TABLE_NAME

    FETCH NEXT FROM dbCursor INTO @dbname
END

CLOSE dbCursor;
DEALLOCATE dbCursor;

然而,所有这一切都是反复获取相同的数据。

---------------------------------------
|   | TABLE_CATALOG | TABLE_NAME      |
|--------------------------------------
| 1 | QA_CTLG       | MasterSchedules |
---------------------------------------

---------------------------------------
|   | TABLE_CATALOG | TABLE_NAME      |
|--------------------------------------
| 1 | QA_CTLG       | MasterSchedules |
---------------------------------------

---------------------------------------
|   | TABLE_CATALOG | TABLE_NAME      |
|--------------------------------------
| 1 | QA_CTLG       | MasterSchedules |
---------------------------------------

...

我已将其缩小到EXECUTE sp_executesql...显然没有效果的事实。有谁知道为什么会这样或如何解决它?

对于记录,是的,我确实知道这将显示至少有一个表的数据库,而不是那两个表的数据库。

我想过尝试使用某种动态SQL,但我想到的并不是仅仅使用光标。

我还尝试编写一个查询来执行此操作(如下所示):

select 
    name 
from 
    sys.databases 
where 
    name not in ('master', 'tempdb', 'model', 'msdb') 
    and exists (select top 1 TABLE_NAME 
                from [name].INFORMATION_SCHEMA.TABLES 
                where TABLE_NAME = 'Users') 
    and exists (select top 1 TABLE_NAME 
                from [name].INFORMATION_SCHEMA.TABLES 
                where TABLE_NAME = 'MasterSchedules')

不出所料,这会返回错误

  

无效的对象名称' @ name.INFORMATION_SCHEMA.TABLES'

我可以使用name代替ref.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() { @Override public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) { rface = dataSnapshot.child("face").getValue(String.class); } @Override public void onCancelled(DatabaseError databaseError) { } }); 来实现此功能(或修复光标的方法)吗?

3 个答案:

答案 0 :(得分:4)

这是使用动态sql执行此操作的一种非常简单的方法。这将返回具有这两个表名的所有数据库。它不需要循环,游标或临时表。

<a href="#">test</a>

- EDIT-- 您可能希望将架构添加到此查询中。它将作为默认模式中的表的发布工作,但如果具有任一名称的表存在于多个模式中,则这将不会像宣传的那样工作。

答案 1 :(得分:1)

尝试使用这个轻微修改过的代码版本...使用动态SQL而不是脚本化“USE”语句,修复你的ORDER BY以使用逗号而不是点...这似乎对我有用,具体取决于您希望输出的内容:

DECLARE @dbname sysname;

DECLARE dbCursor CURSOR FOR 
    SELECT name FROM sys.databases WHERE name not in ('master', 'tempdb', 'model', 'msdb');
OPEN dbCursor;

FETCH NEXT FROM dbCursor INTO @dbname;

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @stmt nvarchar(max)
    SELECT @stmt = N'SELECT TABLE_CATALOG, TABLE_NAME FROM ' + @dbname + N'.INFORMATION_SCHEMA.TABLES ' + 
                   N'WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_NAME in (''MasterSchedules'', ''Users'') ' + 
                   N'ORDER BY TABLE_SCHEMA, TABLE_NAME';
    EXEC(@stmt);

    FETCH NEXT FROM dbCursor INTO @dbname
END
CLOSE dbCursor;
DEALLOCATE dbCursor;

答案 2 :(得分:0)

您将不得不在此处使用动态sql并遍历每个数据库,而无需知道每个数据库的名称。假设您具有查询服务器上所有数据库的正确访问权限:

    use master

    declare @cursor  table (dbname varchar(150))
    declare @dbname  varchar(150)=''
    declare @sql     nvarchar(500)=''

    if object_id('tempdb..#results') is not null drop table #results
    create table #results (dbname varchar(150), tblname varchar(150))

    set nocount on

    insert into @cursor
    select name
    from sys.sysdatabases db
    where name not in ('master', 'tempdb', 'model', 'msdb')

     select @dbname = min(dbname) from @cursor -- first row

     While @dbname Is Not Null
     Begin

        set @sql = ('   
           insert into #results (dbname, tblname)
           select ' + char(39) +  @dbname + char(39) + ' , name from ' + @dbname + '.sys.tables where name in (''MasterSchedules'', ''Users'')
           ')

           exec sp_executesql @sql

      select @dbname = min(dbname) from @cursor where dbname > @dbname -- next row
     End 

     select * from #results