繁体   English   中英

如何使用动态 SQL 在 Azure Synapse 中的表列表上循环 SELECT 语句?

[英]How to loop a SELECT statement on a list of tables in Azure Synapse using Dynamic SQL?

我经常需要找出多个表的记录计数的最新日期。 目前我正在尝试从表列表中找出最大加载日期。

我有以下示例表列表:

TableA
TableB
TableC
TableD

到目前为止,我能够声明一个变量并将单个表名作为参数传递到我的 SQL 状态表中,如下所示:

DECLARE @SQLstmnt varchar(500)
 
DECLARE @tname varchar(200)
SET @tname = 'TableA'
 
SET @SQLstmnt = 'SELECT MAX(loaddate) FROM ' + @tname
 
EXEC (@SQLstmnt)

但我不知道如何传递我的整个表名列表(TableA, TableB, TableC, TableD)并在列表中的每个表上循环上面的 SELECT 语句。

我搜索了一种解决方案,但我似乎找不到适合我的情况的解决方案。

有人可以帮忙吗?

您可以为所有表构建一个动态联合查询并以这种方式执行它:

DECLARE @SQL NVARCHAR(MAX);
SELECT  @SQL = CONCAT('SELECT TableName, Date FROM (',
                STRING_AGG(CONCAT('SELECT TableName = ''', t.Name, ''',  Date = MAX(', c.name, ') 
                                  FROM ', QUOTENAME(s.name), '.', QUOTENAME(t.name)), ' UNION ALL '),
                ') AS t;')
FROM    sys.columns AS c
        INNER JOIN sys.tables AS t
            ON t.object_id = c.object_id
        INNER JOIN sys.schemas AS s
            ON s.schema_id = t.schema_id
WHERE   c.name = 'LoadDate' -- Check Column Exists
AND     t.name IN ('TableA', 'TableB', 'TableC', 'TableD') -- Limit to required tables;
HAVING COUNT(*) > 0

PRINT @sql
EXECUTE sp_executesql @SQL;

这将为您的示例构建一个类似这样的 SQL 语句:

SELECT TableName, Date 
FROM (SELECT TableName = 'TableA',  Date = MAX(LoadDate) FROM dbo.TableA
     UNION ALL 
     SELECT TableName = 'TableB',  Date = MAX(LoadDate) FROM dbo.TableB
     UNION ALL
     SELECT TableName = 'TableC',  Date = MAX(LoadDate) FROM dbo.TableC
     UNION ALL
     SELECT TableName = 'TableD',  Date = MAX(LoadDate) FROM dbo.TableD
    ) AS t;

并将所有表/日期作为一个集合返回:

如果您真的想遍历表,那么我仍然会使用系统视图作为起点来验证 (a) 表是否存在并且 (b) 包含加载日期列,但使用CURSOR来执行语句针对每个表而不是构建单个语句:

DECLARE TableCursor CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR
    SELECT  CONCAT(QUOTENAME(s.name), '.', QUOTENAME(t.name))
    FROM    sys.columns AS c
            INNER JOIN sys.tables AS t
                ON t.object_id = c.object_id
            INNER JOIN sys.schemas AS s
                ON s.schema_id = t.schema_id
    WHERE   c.name = 'LoadDate'
    AND     t.name IN ('TableA', 'TableB', 'TableC', 'TableD') -- Limit to required tables;

DECLARE @TableName SYSNAME;
OPEN TableCursor;
FETCH NEXT FROM TableCursor INTO @TableName;

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @SQL NVARCHAR(MAX) = CONCAT('SELECT TableName = ''', @TableName, ''', Date = MAX(LoadDate) FROM ', @TableName);

    EXECUTE sp_executesql @SQL;
    FETCH NEXT FROM TableCursor INTO @TableName;

END

CLOSE TableCursor;
DEALLOCATE TableCursor;

超级简单...只需使用一个WHILE循环

DECLARE @MyTable TABLE ([Name] varchar(256), Done bit default(0));

INSERT INTO @MyTable ([Name])
VALUES
('TableA'),
('TableB'),
('TableC'),
('TableD');

DECLARE @SQLstmnt nvarchar(max), @tname varchar(200);

WHILE EXISTS (SELECT 1 FROM @MyTable WHERE Done = 0) BEGIN
    SELECT TOP 1 @tname = [Name]
    FROM @MyTable
    WHERE Done = 0;
  
    SET @SQLstmnt = 'SELECT MAX(loaddate) FROM ' + @tname + ';';
 
    -- This is the best practice way to execute dynamic SQL
    -- EXEC sp_executesql @SQLstmnt;
    -- Debug the dynamic SQL
    PRINT(@SQLstmnt);

    UPDATE @MyTable SET Done = 1 WHERE [Name] = @tname;
END;

暂无
暂无

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

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