Get data from every column in every table in a database | SQL Server

一曲冷凌霜 提交于 2020-12-06 11:57:18

问题


I have seen multiple questions on how to retrieve every column from every table along with its data type, among many other pieces of information which can be summarised in the shortest way with this query:

SELECT * 
FROM INFORMATION_SCHEMA.COLUMNS

However, is it possible to get all the data from the columns and the rows they belong to get the first row in the table alongside this? I have not found a way to do so thus far. Is it possible to do such, maybe also having a WHERE condition such as checking if the table contains a list of specific columns before returning it e.g.:

SELECT <AllTablesAndColumns+FirstRow> 
FROM <WhereTheyCanBeSelectedFrom> 
WHERE <TheTableHasTheseSpecificColumns>

Which would return the table name, column name and the data contained within those columns for each row.


回答1:


You could build dynamic query:

DECLARE @sql NVARCHAR(MAX) = 
N'SELECT *
FROM (VALUES (1)) AS s(n)
<joins>';

DECLARE @joins NVARCHAR(MAX)= '';

SELECT @joins += FORMATMESSAGE('LEFT JOIN (SELECT TOP 1 * FROM %s ) AS sub%s
       ON 1=1' + CHAR(10), table_schema + '.' + table_name,
       CAST(ROW_NUMBER() OVER(ORDER BY 1/0) AS VARCHAR(10)))
FROM (SELECT DISTINCT table_schema, table_name
      FROM INFORMATION_SCHEMA.COLUMNS
      -- WHERE ...  -- custom logic based on column type/name/...
     ) s;

SET @sql = REPLACE(@sql, '<joins>', @joins);
PRINT @sql;

EXEC(@sql);

DBFiddle Demo

The dynamic query has structure:

SELECT * 
FROM (VALUES (1)) AS s(n)   -- always 1 row
LEFT JOIN (SELECT TOP 1 * FROM dbo.tab1 ) AS sub1 ON 1=1 -- get single row
LEFT JOIN (SELECT TOP 1 * FROM dbo.tab2 ) AS sub2 ON 1=1 
LEFT JOIN (SELECT TOP 1 * FROM dbo.tabC ) AS sub3 ON 1=1 

Please treat it as starting point. You could easily extend it with WHERE condition for each subquery and return specific columns instead of *.


EDIT:

Version with UNION ALL:

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = COALESCE(@sql + ' UNION ALL', '') + 
FORMATMESSAGE(' SELECT TOP 1 tab_name=''%s'',col_name=''%s'',col_val=%s FROM %s'+CHAR(10) 
      ,table_name, column_name, column_name, table_schema + '.' + table_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_name LIKE 'colV%'; 

PRINT @sql;  
EXEC(@sql);

DBFiddle Demo2




回答2:


If you are looking for more of an EAV structure

Let's say that we're looking for all tables with a column name of ZIPCODE

Example

Declare @S varchar(max) = ''

SELECT @S = @S +'+(Select top 1 SourceTable='''+A.Table_Name+''',* from '+quotename(A.Table_Name)+' for XML RAW)'
 FROM  INFORMATION_SCHEMA.COLUMNS A 
 Where COLUMN_NAME in ('ZipCode')

Declare @SQL varchar(max) = '
Declare @XML xml = '+stuff(@S,1,1,'')+'

Select SourceTable = r.value(''@SourceTable'',''varchar(100)'')
      ,Item        = attr.value(''local-name(.)'',''varchar(100)'')
      ,Value       = attr.value(''.'',''varchar(max)'') 
 From  @XML.nodes(''/row'') as A(r)
 Cross Apply A.r.nodes(''./@*'') AS B(attr)
 Where attr.value(''local-name(.)'',''varchar(100)'') not in (''SourceTable'')
 '
 Exec(@SQL)

Returns



来源:https://stackoverflow.com/questions/52246897/get-data-from-every-column-in-every-table-in-a-database-sql-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!