将变体数据传递给 Snowflake

Passing variant data to Snowflake

我用Snowflake写了一个存储过程。我从 python lambda 函数调用它并且我已经验证我正在传递有效的 json。我不知道如何在我的插入中使用我传递给存储过程的数据。

插入中带有“值(${variant_data}”的部分给我带来了麻烦。

我读了这个 how to pass variant data into snowflake table using snowflake stored procedure,它说 Snowflake 不完全支持我需要做的事情。显然,我需要将“variant_data”转换为字符串,然后再转换回变体以使用插入内容中的数据,但我不清楚该示例。

这是我的存储过程。

create or replace procedure  MY_STORED_PROCEDURE("variant_data" variant)
    returns string
    language javascript
    strict
    execute as owner
    as
    $$
    var variant_data=variant_data;
    var sql_command = `
    insert into MY_TABLE(MY_VARIANT_DATA) values(${variant_data})
    `
    $$;

如果有人能解释如何在我的插入中使用变体数据,我将不胜感激。

好吧,第一步让我们检查一下我们的基础 SQL 是否采用了 acceptable 形式:

create table MY_TABLE(MY_VARIANT_DATA variant);
insert into my_table(my_variant_data) values 
    (parse_json('{"key1":"value1","key2":1234}'));

Invalid expression [PARSE_JSON('{"key1":"value1","key2":1234}')] in VALUES clause

好的,让我们把它设为 SELECT 和 PARSE_JSON:

insert into my_table(my_variant_data) select 
    (parse_json('{"key1":"value1","key2":1234}'));
number of rows inserted
1

好的,这样就可以用于单个值(这实际上不是你应该如何将数据加载到雪花中的方式,我的意思是如果你每小时有 1 条数据,那很好,但如果你经常这样做,你的 table 会非常零散)..

所以让我们尝试转换为 ::VARIANT

insert into my_table(my_variant_data) values 
   ('{"key1":"value1","key2":1234}'::variant);

Invalid expression [CAST('{"key1":"value1","key2":1234}' AS VARIANT)] in VALUES clause

好的,所以 multi-insert 通过 SELEC FROM VALUES:

insert into my_table(my_variant_data) 
    select parse_json(column1) 
    from values
        ('{"key1":"value1","key2":1234}'),
        ('{"key1":"value2","key2":1235}');
number of rows inserted
2

好的,所以我们现在有几个有效的 INSERT sql..

模式

让我们使用它重新创建过程,这看起来像是“作弊”,因为它是一个完整的工作代码,但我花了很长时间才让事情正常进行。基本上我没有把Felipe的回答看得太深,反正最后我还是接受了字符串连接,这是一个安全风险,所以我真的不会这样做:

create or replace procedure MY_STORED_PROCEDURE("variant_as_string" text)
    returns string
    language javascript
    strict
    execute as owner
    as
    $$
    var sql_command = "insert into my_table(my_variant_data) select (parse_json('"+ variant_as_string +"'));";
    var sql = snowflake.createStatement( {sqlText: sql_command});
    var resultSet = sql.execute();
    return sql_command;
    $$;

有效!虽然可能不应该使用..

-- lets the prior inserts
truncate table MY_TABLE;

-- do new  insert
call MY_STORED_PROCEDURE('{"key1":"value4","key2":1238}');

-- look at the results
select * from my_table;
MY_VARIANT_DATA
{ "key1": "value4", "key2": 1238 }

但这也将输入类型从 variant 更改为 test...

顺便说一句,我调试这些东西的方式是这样注释掉的:

create or replace procedure MY_STORED_PROCEDURE("variant_data" variant)
    returns string
    language javascript
    strict
    execute as owner
    as
    $$
    var sql_command = "insert into my_table(my_variant_data) select (parse_json('"+ JSON.stringify(variant_data) +"'));";
    //var sql = snowflake.createStatement( {sqlText: sql_command});
    //var resultSet = sql.execute();
    return sql_command;
    $$;

并阅读 SQL 看到它让我很高兴,无论如何,这两行未注释掉,适用于变体数据:

call MY_STORED_PROCEDURE(parse_json('{"key1":"value12","key2":12345}'));
select * from my_table;
MY_VARIANT_DATA
{ "key1": "value4", "key2": 1238 }
{ "key1": "value12", "key2": 12345 }

至此,在 table 中插入单行的两种方法。由于 SQL 注入的原因,应该避免这两种可能,为了正确地做到这一点,您应该在另一个问题上使用 Felipe 的回答。

create or replace procedure MY_STORED_PROCEDURE("variant_data" variant)
    returns string
    language javascript
    strict
    execute as owner
    as
    $$
    var sql_command = "insert into my_table(my_variant_data) select (parse_json(:1));";
    var sql = snowflake.createStatement( {sqlText: sql_command, binds:[JSON.stringify(variant_data)]});
    var resultSet = sql.execute();
    return sql_command;
    $$;
call MY_STORED_PROCEDURE(parse_json('{"key1":"value123","key2":123456}'));

给出:

MY_VARIANT_DATA
{ "key1": "value4", "key2": 1238 }
{ "key1": "value12", "key2": 12345 }
{ "key1": "value123", "key2": 123456 }