Redshift中能否不使用EXECUTE语句执行含变量的CREATE查询?
能不能移除动态SQL(EXECUTE)实现这个动态PIVOT?
首先,你的DROP语句确实可以直接改成静态SQL,不用EXECUTE:
DROP TABLE IF EXISTS some_table_pivot;
但CREATE语句的核心难题是:PIVOT的IN子句必须是提前确定的静态列列表,而你这里是从some_table里动态读取distinct的key值当列——这在标准静态SQL里根本做不到,因为SQL解析的时候就得知道所有列的定义,这些动态列只有运行时才能确定。
那有没有不用EXECUTE的替代路子?分数据库情况看:
- PostgreSQL:可以用
crosstab函数,或者把键值对转成JSON存在一列里,但如果要生成结构化的表,还是绕不开动态SQL; - Oracle:有
XMLPIVOT能动态生成列,但要转成普通表还是得靠动态SQL; - SQL Server:就算用
FOR XML PATH构造列列表,最终还是要通过EXECUTE执行才能建表。
所以结论很明确:完全移除EXECUTE来实现这个动态PIVOT的CREATE语句,根本不可行。不过你可以优化原有的动态SQL写法,让它更安全简洁——比如修正你代码里重复写DROP TABLE的笔误,用数据库自带的格式化函数避免注入风险(以PostgreSQL为例):
BEGIN SELECT INTO row '''' || LISTAGG(DISTINCT key, ''', ''') || '''' AS keys FROM some_table; DROP TABLE IF EXISTS some_table_pivot; -- 用format函数替代字符串拼接,降低注入风险 EXECUTE format( 'CREATE TABLE some_table_pivot AS SELECT * FROM ( SELECT account_id, key, value FROM some_table ) PIVOT (MAX(lower(value)) FOR "key" IN (%s));', row.keys ); END;
如果铁了心要完全不用EXECUTE,那只能放弃生成传统的列转行表,改用JSON/XML类型存键值对。比如PostgreSQL里可以这么写静态SQL:
DROP TABLE IF EXISTS some_table_pivot; CREATE TABLE some_table_pivot AS SELECT account_id, jsonb_object_agg(key, lower(value)) AS pivot_data FROM some_table GROUP BY account_id;
这样每个account_id对应一个JSON对象,里面包含所有key-value对,不用动态SQL,但不是你原来想要的结构化表结构。
内容的提问来源于stack exchange,提问作者Raksha
相关产品推荐
相关产品推荐

