Snowflake 脚本 - 立即执行多个语句以在没有 loop/cursor 的情况下删除表

Snowflake Scripting - EXECUTE IMMEDIATE multiple statements to drop tables without loop/cursor

目标是删除多个匹配特定命名模式的表,只使用 SQL 而没有 cursors/loops:

设置:

CREATE TABLE tab_1(i INT);
CREATE TABLE tab_2(i INT);
CREATE TABLE tab_3(i INT);
CREATE TABLE tab_4(i INT);
CREATE TABLE tab_5(i INT);

一般先生成查询即可:

SELECT LISTAGG(CONCAT('DROP TABLE IF EXISTS ', TABLE_NAME, ';', CHAR(10)) ,'')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
  AND TABLE_SCHEMA = 'PUBLIC'
  AND TABLE_NAME ILIKE 'TAB!_%' ESCAPE '!'
GROUP BY GROUPING SETS(());
/*
DROP TABLE IF EXISTS TAB_1; 
DROP TABLE IF EXISTS TAB_2; 
DROP TABLE IF EXISTS TAB_3; 
DROP TABLE IF EXISTS TAB_4; 
DROP TABLE IF EXISTS TAB_5; 
*/

则需要复制输出并运行。此手动步骤是不必要的,应避免。

我们的想法是使用 SELECT INTOEXECUTE IMMEDIATE 来调用生成的查询:

DECLARE 
    QUERY STRING;
BEGIN
    SELECT LISTAGG(CONCAT('DROP TABLE IF EXISTS ', TABLE_NAME, ';', CHAR(10)), '')
    INTO :QUERY
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_TYPE = 'BASE TABLE'
      AND TABLE_SCHEMA = 'PUBLIC'
      AND TABLE_NAME ILIKE 'TAB!_%' ESCAPE '!'
    GROUP BY GROUPING SETS(());

  QUERY := COALESCE(QUERY, 'SELECT ''No tables found''');

  EXECUTE IMMEDIATE :QUERY;
  RETURN :QUERY;
END;

这是不可能的:

Multiple SQL statements in a single API call are not supported; use one API call per statement instead.

答案是用 BEGIN END 块包装生成的代码:

DECLARE 
    QUERY STRING;
BEGIN
    SELECT CONCAT('BEGIN', CHAR(10)
             ,LISTAGG(CONCAT('DROP TABLE IF EXISTS ', TABLE_NAME, ';', CHAR(10)), '')
             ,'END')
    INTO :QUERY
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_TYPE = 'BASE TABLE'
      AND TABLE_SCHEMA = 'PUBLIC'
      AND TABLE_NAME ILIKE 'TAB!_%' ESCAPE '!'
    GROUP BY GROUPING SETS(());

  QUERY := COALESCE(QUERY, 'SELECT ''No tables found''');

  EXECUTE IMMEDIATE :QUERY;
  RETURN :QUERY;
END;

输出:

BEGIN
DROP TABLE IF EXISTS TAB_1;
DROP TABLE IF EXISTS TAB_2;
DROP TABLE IF EXISTS TAB_3;
DROP TABLE IF EXISTS TAB_4;
DROP TABLE IF EXISTS TAB_5;
END

SHOW TABLES LIKE 'TAB_%';
-- no resultset

第二个运行: