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 INTO
和 EXECUTE 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
第二个运行:
目标是删除多个匹配特定命名模式的表,只使用 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 INTO
和 EXECUTE 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
第二个运行: