Snowflake存储过程使用传入变量插入表数据时报invalid Identifier错误
错误原因
- 列名处理逻辑异常:获取到表的列名数组后,多余对第一个列名执行了「空格替换为逗号」的操作,会破坏列名的正确拼接格式,实际直接将列名数组用逗号拼接即可。
- 字符串值未加单引号:将属性行的空格替换为逗号后,
DATABASE VARCHAR 1会变为DATABASE,VARCHAR,1,插入语句中字符串值没有用单引号包裹,Snowflake会将这些值识别为字段标识符而非字符串,直接触发invalid identifier报错。 - 仅处理单条属性:传入的字符串按逗号分割为数组后,只取了第一个元素处理,多条属性会被遗漏。
- 缺少循环插入逻辑:没有遍历所有分割后的属性条目,一次调用只能插入单条数据。
修复后完整代码
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".ADD_ATTRIBUTES_SESSION_META ("P_ATTRIBUTE_DATATYPE_FLAG" VARCHAR(16777216)) RETURNS VARCHAR LANGUAGE JAVASCRIPT COMMENT='Add Attributes to the table SESSION_ATTRIBUTES_META' EXECUTE AS CALLER AS $$ // 拆分传入的属性串,去除每条前后多余空格 const arr_list = P_ATTRIBUTE_DATATYPE_FLAG.split(',').map(item => item.trim()); const arr_col_att = []; // 动态获取目标表列名 let v_sqlCode = `SELECT * FROM ADMINDB.TOOLKIT.SESSION_ATTRIBUTES_META LIMIT 0`; try{ let sqlStmt = snowflake.createStatement({sqlText : v_sqlCode}); let sqlRS = sqlStmt.execute(); for (i = 1; i <= sqlStmt.getColumnCount(); i++) { arr_col_att.push(sqlStmt.getColumnName(i)); } }catch(err){ let errMessage = "Failed: Code: " + err.code + "\n State: " + err.state; errMessage += "\n Message: " + err.message + " | SQL: " + v_sqlCode; errMessage += "\nStack Trace:\n" + err.stackTraceTxt; throw '执行查询列名SQL出错: \n' + errMessage; } const v_col_att = arr_col_att.join(','); // 遍历所有属性条目批量插入 for(let item of arr_list){ // 拆分单条属性的三个值,给字符串字段加单引号,同时转义值内的单引号 const [attr, datatype, flag] = item.split(/\s+/); const v_value = `'${attr.replace(/'/g, "''")}','${datatype.replace(/'/g, "''")}',${flag}`; const insert_sql = `INSERT INTO ADMINDB.TOOLKIT.SESSION_ATTRIBUTES_META(${v_col_att}) VALUES(${v_value})`; try{ let sqlStmt = snowflake.createStatement({sqlText : insert_sql}); sqlStmt.execute(); }catch(err){ let errMessage = "Failed: Code: " + err.code + "\n State: " + err.state; errMessage += "\n Message: " + err.message + " | SQL: " + insert_sql; errMessage += "\nStack Trace:\n" + err.stackTraceTxt; throw '执行插入SQL出错: \n' + errMessage; } } return "SUCCESS!"; $$; -- 调用测试 CALL "ADMINDB"."TOOLKIT".ADD_ATTRIBUTES_SESSION_META('DATABASE VARCHAR 1,SCHEMA VARCHAR 1,TIMESTAMP TIMESTAMP 0');
注意事项
- 代码内置了单引号转义逻辑,避免属性值包含单引号时触发语法错误
- 调用时传入的属性串需严格遵循
属性名 数据类型 0/1的格式,多条属性用英文逗号分隔 - 若表结构固定为
ATTRIBUTE、DATATYPE、FLAG三个字段,可省略动态获取列名的步骤,直接写死列名即可提高执行效率
内容的提问来源于stack exchange,提问作者RMC_DEV
相关产品推荐
相关产品推荐

