使用绑定和接收错误在 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 名称作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Snowflake 中将 json 转换为表格格式

在 Swift 中将可选绑定转换为错误处理的过程是啥?

Snowflake 中的列绑定变量

使用“?::TIMESTAMP_NTZ”在查询中指定类型时,Snowflake JDBC 批量插入失败并显示“绑定变量?未设置”

雪花存储过程变量绑定错误

在暂存文件#snowflake-cloud-platform 上选择中的列绑定变量