我试图获得的输出;
(数据库名称=ATT(
- 表名
- 列名
- 最大加载日期=仅此列的最大(加载日期(
loaded_date是数据库中大约50个表中的一列,具有相同的名称和数据类型(Datetime(
select * FROM sys.tables
select * FROM syscolumns
我一直在探索系统表,但运气不好,看了一些帖子,它可能是动态SQL,这是我从未做过的。
您可以编写一个sql来编写sql。。
SELECT REPLACE(
'select ''{tn}'' as table_name, max(loaded_date) as ld from {tn} union all'
,'{tn}',table_name)
FROM
information_schema.columns
WHERE
column_name = 'loaded_date'
运行它,然后将除最后一个UNION all外的所有UNION all从结果窗口复制到查询窗口中,然后再次运行
如果你想把所有这些都放在一个字符串中进行动态执行,我想它看起来像(未经测试的(一个包含以下内容的过程:
DECLARE @x NVARCHAR(MAX);
SELECT @x =
STRING_AGG(
REPLACE(
'select ''{tn}'' as table_name, max(loaded_date) as ld from {tn}'
,'{tn}',table_name)
,' union all ')
FROM
information_schema.columns
WHERE
column_name = 'loaded_date';
EXECUTE sp_executesql @x;
如果你的SQL是旧的,并且没有string_agg,那就有点尴尬了——但有很多例子是"将行转换成CSV";在sql server中,看起来像STUFF..FOR XML PATH
-https://duckduckgo.com/?t=ffab&q=行+到+CSV+SQLS&ia=卷筒纸
我写了一个更永久的脚本类型来实现这一点。它返回当前数据库中表列表的结果集,其中包含一个名为loaded_date
的列,以及每个表的MAX(loaded_date)
结果。该脚本通过在每个表上单独循环和运行查询,并跟踪表变量中每个表的最大值,来单独查询每个表。它还有一个@Debug
变量,允许您查看将要运行而不是实际运行的查询的文本,并实现自定义错误消息以解决任何问题。
/*disable row count messages*/
SET NOCOUNT ON;
/*set to 1 to debug (aka just print queries instead of running)*/
DECLARE @Debug bit = 0;
/*get list of tables to query and assign a unique index to row to assist in looping*/
DECLARE @TableList TABLE(
SchemaAndTableName nvarchar(257) NOT NULL
,OrderToQuery bigint NOT NULL
,MaxLoadedDate datetime NULL
,PRIMARY KEY (OrderToQuery)
);
INSERT INTO @TableList (SchemaAndTableName,OrderToQuery)
SELECT
CONCAT(QUOTENAME(s.name),N'.', QUOTENAME(t.name)) AS SchemaAndTableName
,ROW_NUMBER() OVER(ORDER BY s.name, t.name) AS OrderToQuery
FROM
sys.columns AS c
INNER JOIN sys.tables AS t ON c.object_id = t.object_id
INNER JOIN sys.schemas AS s ON t.schema_id = s.schema_id
WHERE
c.name = N'loaded_date';
/*declare and set some variables for loop*/
DECLARE @NumTables int = (SELECT TOP (1) OrderToQuery FROM @TableList ORDER BY OrderToQuery DESC);
DECLARE @I int = 1;
DECLARE @CurMaxDate datetime;
DECLARE @CurTable nvarchar(257);
DECLARE @CurQuery nvarchar(max);
/*start loop*/
WHILE @I <= @NumTables
BEGIN
/*build text of current query*/
SET @CurTable = (SELECT SchemaAndTableName FROM @TableList WHERE OrderToQuery = @I);
SET @CurQuery = CONCAT(N'SELECT @MaxDateOut = MAX(loaded_date) FROM ', @CurTable, N';');
/*check debugging status*/
IF @Debug = 0
BEGIN
BEGIN TRY
EXEC sys.sp_executesql @stmt = @CurQuery
,@params = N'@MaxDateOut datetime OUTPUT'
,@MaxDateOut = @CurMaxDate OUTPUT;
END TRY
BEGIN CATCH
DECLARE @ErrorMessage nvarchar(max) = CONCAT(
N'Error querying table ', @CurTable, N'.', NCHAR(13), NCHAR(10)
,N'Errored query: ', NCHAR(13), NCHAR(10), @CurQuery, NCHAR(13), NCHAR(10)
,N'Error message: ', ERROR_MESSAGE()
);
RAISERROR(@ErrorMessage,16,1) WITH NOWAIT;
/*on error end loop so error can be investigated*/
SET @I = @NumTables + 1;
END CATCH;
END;
ELSE /*currently debugging*/
BEGIN
PRINT(CONCAT(N'Debug output: ', @CurQuery));
END;
/*update value in our table variable*/
UPDATE @TableList
SET MaxLoadedDate = @CurMaxDate
WHERE
OrderToQuery = @I;
/*increment loop*/
SET @I = @I + 1;
END;
SELECT
SchemaAndTableName AS TableName
,MaxLoadedDate AS Max_Loaded_date
FROM
@TableList;
我更喜欢这个解决方案,因为一次查询一个表比尝试一个大型UNION ALL
查询对系统的影响小得多。同时查询一大组表可能会导致一些严重的资源信号量或锁定争用(取决于数据库的使用情况(。
它的评论相当不错,但如果有什么不清楚的地方,请告诉我。
另外,请注意,动态SQL应该作为最后手段使用。我提供这个脚本是为了回答你的问题,但你应该探索比这样更好的选择。
您可以使用未记录的存储过程sp_MSforeachtable
。但是,不要在生产代码中使用,因为这个存储过程在未来的版本中可能不可用。
阅读sp_MSforeachtable 的详细信息
EXEC sp_MSforeachtable 'SELECT ''?'' as tablename, max(loaded_Date) FROM ?'