Snowflake cloud data platform 雪花条件代码:添加新列(幂等脚本)
假设我们有一个包含以下数据的表:Snowflake cloud data platform 雪花条件代码:添加新列(幂等脚本),snowflake-cloud-data-platform,Snowflake Cloud Data Platform,假设我们有一个包含以下数据的表: CREATE TABLE tab(i INT PRIMARY KEY); INSERT INTO tab(i) VALUES(1),(2),(3); SELECT * FROM tab; 现在,我的目标是创建SQL脚本,该脚本将向现有表中添加一个新列: ALTER TABLE IF EXISTS tab ADD COLUMN col VARCHAR(10); 一切按计划进行。除了我希望能够多次运行脚本,但效果应该只发生一次() 如果我再次尝试运行它,我将得到
CREATE TABLE tab(i INT PRIMARY KEY);
INSERT INTO tab(i) VALUES(1),(2),(3);
SELECT * FROM tab;
现在,我的目标是创建SQL脚本,该脚本将向现有表中添加一个新列:
ALTER TABLE IF EXISTS tab ADD COLUMN col VARCHAR(10);
一切按计划进行。除了我希望能够多次运行脚本,但效果应该只发生一次()
如果我再次尝试运行它,我将得到:
SQL编译错误:列COL已存在
通常我会使用以下方法之一: a) 在执行查询之前,使用控制结构IF检查元数据表:
-- (T-SQL)
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='TAB' AND COLUMN_NAME = 'COL')
BEGIN
ALTER TABLE tab ADD col VARCHAR(10);
END;
我在Snowflake的文档中没有找到IF语句
b) 支持的SQL方言(如果不存在)
语法:
-- PostgreSQL
ALTER TABLE IF EXISTS tab ADD COLUMN IF NOT EXISTS col VARCHAR(10);
大多数雪花SQL命令都包含IF EXISTS
/或REPLACE
子句,这意味着它的编写方式允许多次运行脚本
我正在考虑使用如下代码:
CREATE OR REPLACE TABLE tab
AS
SELECT i, CAST(NULL AS VARCHAR(10)) AS col
FROM tab;
另一方面,这种方法会导致不必要的表创建,并且不会保留元数据(如主键)
有没有办法在雪花上达到类似的效果?最好是使用条件代码(例如add column)。尽管Snowflake在SQL实现中实现了DDL和DML的丰富混合,但在过程代码方面,他们似乎依赖JavaScript,至少在这一点上是这样。但是您应该能够通过JavaScript存储过程完成幂等
ALTER
脚本
目前我恐怕缺乏JavaScript技能,无法为您提供一个工作示例。不过,我所在的组织最近采用了Snowflake,因此我将分享我的一些研究成果
以下是最近一篇关于这个问题的博文:
Snowflake关于存储过程的概述文档:
在上面的页面上,当前的第三个链接包含大量的示例代码
您可以使用类似的方法。如果列已经存在,它将报告添加列失败,但它将处理错误,因此不会干扰sql脚本的执行:
create or replace procedure SafeAddColumn(tableName string, columnName string, columnType string)
returns string
language JavaScript
as
$$
var sql_command = "ALTER TABLE IF EXISTS " + TABLENAME + " ADD COLUMN " + COLUMNNAME + " " + COLUMNTYPE + ";";
var strOut;
try {
var stmt = snowflake.createStatement( {sqlText: sql_command} );
var resultSet = stmt.execute();
while (resultSet.next()) {
strOut = resultSet.getColumnValue(1);
}
}
catch (err) {
strOut = "Failed: " + err; // Return a success/error indicator.
}
return strOut;
$$;
CREATE OR REPLACE TABLE tab(i INT PRIMARY KEY);
INSERT INTO tab(i) VALUES(1),(2),(3);
SELECT * FROM tab;
call SafeAddColumn('tab', 'col', 'varchar(10)');
select * from tab;
call SafeAddColumn('tab', 'col', 'varchar(10)');
我认为当前唯一的选择是将逻辑嵌入到存储过程中,存储过程必须用JavaScript编写。这里有一篇关于这个主题的文章,虽然显然是由网络开发人员而不是数据开发人员撰写的。@EricBrandt谢谢你的想法。是的,将该逻辑嵌入一种通用存储过程是一种可能的解决方案。虽然我看到了两个缺点:1)带有附加过程的污染模式(当然,这可以通过清理脚本轻松解决,所以这并不是什么大问题);2)存储过程是用JS编写的(当然这也不是问题,只是它不是纯SQL脚本)。请随意将其作为答案发布,它值得一次投票:)我对评论进行了一些扩展,以使其更适合于答案框。:)很高兴能帮忙!谢谢你的回答