簡體   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