Home > Enterprise >  What query can I use to retrieve a list of all tables and columns from ALL linked servers?
What query can I use to retrieve a list of all tables and columns from ALL linked servers?

Time:09-30

I'm a complete newbie when it comes to SQL. I found this query that gives me all tables and columns:

SELECT schema_name(tab.schema_id) as schema_name,
    tab.name as table_name, 
    col.column_id,
    col.name as column_name, 
    t.name as data_type,    
    col.max_length,
    col.precision
FROM sys.tables as tab
    INNER JOIN sys.columns as col
        on tab.object_id = col.object_id
    LEFT JOIN sys.types as t
    on col.user_type_id = t.user_type_id
ORDER BY schema_name,
    table_name, 
    column_id;

But it's showing me results from just 1 particular database. It's ignoring a few other linked servers that also have several of their own databases.

Is there a query that will scrape all tables from every visible server/database?

I also read about the sys.servers command which does give me the list of visible servers but I'm not experienced enough with queries to write a statement achieving the above.

CodePudding user response:

You need to use dynamic SQL to select from all databases. You also need to use dynamic SQL to select from all linked servers. So you need dynamic over dynamic.

CREATE TABLE #DBs (dbname nvarchar(515) NOT NULL);

INSERT #DBs (dbname)
SELECT QUOTENAME(d.name)
FROM sys.databases d;

DECLARE @sql nvarchar(max);

SELECT @sql =
  STRING_AGG(CAST(
    '
INSERT #DBs (dbname)
SELECT QUOTENAME('   QUOTENAME(s.name, '''')   ')   ''.''   QUOTENAME(d.name)
FROM '   QUOTENAME(s.name)   '.master.sys.databases d
'   AS nvarchar(max)), '
;
'  )
FROM sys.servers s
WHERE s.server_id > 0;

PRINT @sql;

EXEC sp_executesql @sql;


SELECT @sql = STRING_AGG(CAST(
    '
SELECT
    '''   REPLACE(d.dbname, '''', '''''')    ''' as db_name,
    schema_name(tab.schema_id) as schema_name,
    tab.name as table_name, 
    col.column_id,
    col.name as column_name, 
    t.name as data_type,    
    col.max_length,
    col.precision
FROM '   d.dbname   '.sys.tables as tab
    INNER JOIN '   d.dbname   '.sys.columns as col
        on tab.object_id = col.object_id
    LEFT JOIN '   d.dbname   '.sys.types as t
    on col.user_type_id = t.user_type_id
'  AS nvarchar(max)), '
UNION ALL
'  )
    '
  ORDER BY
    db_name,
    schema_name,
    table_name, 
    column_id;
  '
FROM #DBs d;

PRINT @sql;

EXEC sp_executesql @sql;

DROP TABLE #DBs;

db<>fiddle

  • Related