使用绑定和接收错误在 Snowflake 中将 DB 和 Schema 名称作为参数传递
Posted
技术标签:
【中文标题】使用绑定和接收错误在 Snowflake 中将 DB 和 Schema 名称作为参数传递【英文标题】:Passing DB and Schema name as parameters in Snowflake using binds and receiving error 【发布时间】:2021-11-12 18:03:12 【问题描述】:我在使用绑定的雪花存储过程中将数据库和模式名作为参数传递,不确定我看到的语法错误是什么。请求您的帮助。
代码:
CREATE OR REPLACE PROCEDURE repo(DB_SCHEMA VARCHAR)
RETURNS string
LANGUAGE javascript
AS
$$
var sql_command = ` CREATE TABLE :1.TEST_KK AS SELECT * FROM :1.DIM_ACTIVITY_HIER`;
snowflake.execute(sqlText: sql_command, binds: [DB_SCHEMA]);
return 'success';
$$;
call repo('DB_DEV.DMS')
我尝试使用将数据库和架构名称存储在一个变量中并绑定该变量,如下所示,我也得到了错误。
CREATE OR REPLACE PROCEDURE repo(DB_SCHEMA STRING)
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
var DB_SC = DB_SCHEMA;
var sql_command = ` CREATE TABLE ?.TEST_KK AS SELECT * FROM ?.DIM_ACTIVITY_HIER`;
snowflake.execute(sqlText: sql_command, binds: [DB_SC]);
return DB_SC;
$$;
call repo('DB_DEV.DMS')
其他方式:
CREATE OR REPLACE PROCEDURE repo(DB_SCHEMA STRING)
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
var DB_SC = DB_SCHEMA;
var sql_command = ` CREATE TABLE :1.TEST_KK AS SELECT * FROM :1.DIM_ACTIVITY_HIER`;
snowflake.execute(sqlText: sql_command, binds: [DB_SC]);
return DB_SC;
$$;
call repo('DB_DEV.DMS')
我得到如下语法错误:
对于第二个代码:存储过程 REPO 中的执行错误:
SQL 编译错误:位置 14 的第 1 行语法错误意外'?'。 位置 24 处的语法错误第 1 行意外“AS”。 位置 41 的第 1 行语法错误意外“?”。 在 Snowflake.execute 中,第 5 行位置 13
对于第三个代码:存储过程 REPO 中的执行错误:
SQL 编译错误:位置 14 的第 1 行语法错误意外 ':'。 位置 25 处的语法错误第 1 行意外“AS”。 位置 42 的第 1 行语法错误意外 ':'。 在 Snowflake.execute 中,第 5 行位置 13
【问题讨论】:
抱歉,尝试使用绑定:[DB_SCHEMA],粘贴的代码有错字,但我仍然遇到相同的错误。谢谢 【参考方案1】:您不能将绑定变量用于部分对象名称。您可以使用 IDENTIFIER() SQL 函数将它们用于整个对象名称(三部分或使用上下文)。
如果您想使用部分名称,最简单的方法是在 JavaScript 中使用模板文字。这仅在您使用反引号打开和关闭字符串时才有效,就像您在示例代码中所做的那样:
CREATE OR REPLACE PROCEDURE repo(DB_SCHEMA VARCHAR)
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
var sql_command = ` CREATE TABLE $DB_SCHEMA.TEST_KK AS SELECT * FROM $DB_SCHEMA.DIM_ACTIVITY_HIER`;
snowflake.execute(sqlText: sql_command);
return 'success';
$$;
call repo('DB_DEV.DMS')
【讨论】:
像 `var sql_command = ` CREATE TABLE $DB_SCHEMA.TEST_KK AS` 这样的模板的使用很容易被过度使用,例如CALL repo('DB_DEV.DMS.TEST_KK AS SELECT * FROM any_other_table --')
.
这是需要注意的事情,但是 SQL 注入攻击只有在它允许用户执行他或她无法执行的操作时才有意义。使该攻击无关紧要的一种方法是使用execute as caller
定义SP。另一种方法是仅将使用权授予拥有 SP 的角色,这很常见。【参考方案2】:
非常感谢@Greg Pavlik。我尝试了以下方法,它也有效。
CREATE OR REPLACE PROCEDURE repo(DB_SCHEMA STRING)
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
var DB_SC = DB_SCHEMA;
var sql_command ="CREATE TABLE "+ DB_SC +".TEST_KK " + "AS SELECT * FROM " + DB_SC+ ".DIM_ACTIVITY_HIER";
snowflake.execute(sqlText: sql_command, binds: [DB_SC]);
return DB_SC;
$$;
【讨论】:
以上是关于使用绑定和接收错误在 Snowflake 中将 DB 和 Schema 名称作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章
使用“?::TIMESTAMP_NTZ”在查询中指定类型时,Snowflake JDBC 批量插入失败并显示“绑定变量?未设置”