繁体   English   中英

从数据库中每个表的每个列获取数据| SQL服务器

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

我已经看到了关于如何从每个表中检索每个列及其数据类型的多个问题,以及许多其他信息,这些信息可以使用此查询以最短的方式进行总结:

SELECT * 
FROM INFORMATION_SCHEMA.COLUMNS

但是,是否有可能从它们所属的列和行中获取所有数据, 从而获得表中的第一行呢? 到目前为止,我还没有找到一种方法。 是否可以这样做,也可能具有WHERE条件,例如在返回表之前检查表是否包含特定列的列表,例如:

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

这将返回表名,列名以及每一行的这些列中包含的数据。

您可以构建动态查询:

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演示

动态查询具有以下结构:

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 

请以它为起点。 您可以使用WHERE条件为每个子查询轻松扩展它,并返回特定的列而不是*。


编辑:

带有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演示2

如果您正在寻找更多的EAV结构

假设我们要查找列名称为ZIPCODE的所有表

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)

返回

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM