Snowflake存储过程报错:var.DB_NAME附近语法错误,求修复
核心错误点及修复:
游标变量未声明
原代码中FOR var IN (...) DO里的var未在DECLARE段定义,这是触发"incorrect syntax near var.DB_NAME"的直接原因。需在DECLARE中添加var RECORD;(Snowflake中用RECORD类型定义游标变量)。WHERE子句语法错误
两处UPDATE语句的WHERE条件里用逗号分隔条件,正确语法应该用AND,比如将and SCHEMA_NAME = v_schema_name , TABLE_NAME = v_table_name改为and SCHEMA_NAME = v_schema_name AND TABLE_NAME = v_table_name。获取表注释的逻辑错误
查询当前注释的语句中额外添加了AND COMMENT = ''DESCRIPTION''条件,这会过滤掉大部分正常记录,导致无法正确获取目标表的当前注释,需删除该条件。动态SQL绑定变量名不匹配
动态SQL中的:OBJECT_NAME与传入的变量v_table_name语义不匹配,统一改为:table_name,避免混淆。关键字表名问题
原代码中SELECT ... FROM TABLE的TABLE是SQL关键字,需替换为实际存储Excel数据的表名(示例中用EXCEL_TABLE_DESCRIPTIONS,请根据实际情况修改)。对象名拼接的安全处理
原ALTER TABLE语句直接拼接数据库、schema、表名,存在SQL注入风险,改用Snowflake的IDENTIFIER()函数处理对象名,更安全规范。
修复后的完整存储过程代码
CREATE OR REPLACE PROCEDURE TABLE_DESCRIPTIONS() RETURNS VARCHAR LANGUAGE SQL AS $$ DECLARE var RECORD; -- 新增游标变量声明 v_db_name VARCHAR; v_schema_name VARCHAR; v_table_name VARCHAR; v_description VARCHAR; v_current_comment VARCHAR; v_error_message VARCHAR; BEGIN -- 遍历存储Excel数据的表(替换为实际表名) FOR var IN (SELECT DB_NAME, SCHEMA_NAME, OBJECT_NAME, DESCRIPTION FROM EXCEL_TABLE_DESCRIPTIONS) DO v_db_name := var.DB_NAME; v_schema_name := var.SCHEMA_NAME; v_table_name := var.OBJECT_NAME; v_description := var.DESCRIPTION; -- 检查表是否存在 BEGIN EXECUTE IMMEDIATE ' SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG = :db_name AND TABLE_SCHEMA = :schema_name AND TABLE_NAME = :table_name ' USING (v_db_name, v_schema_name, v_table_name); -- 获取当前表注释 BEGIN EXECUTE IMMEDIATE ' SELECT COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG = :db_name AND TABLE_SCHEMA = :schema_name AND TABLE_NAME = :table_name' INTO v_current_comment USING (v_db_name, v_schema_name, v_table_name); -- 注释不匹配则更新 IF v_description != v_current_comment THEN EXECUTE IMMEDIATE ' ALTER TABLE IDENTIFIER(:full_table_name) SET COMMENT :new_comment' USING (v_db_name || '.' || v_schema_name || '.' || v_table_name, v_description); END IF; EXCEPTION WHEN OTHERS THEN -- 记录获取注释时的错误 v_error_message := SQLERRM; UPDATE TABLE_UPDATE_AUDIT SET ERROR_MESSAGE = v_error_message, PROCESSED_INDICATOR = 'N', PROCESSED_TIMESTAMP = CURRENT_TIMESTAMP(), PROCESS_RESULT = 'Fail' WHERE DB_NAME = v_db_name AND SCHEMA_NAME = v_schema_name AND TABLE_NAME = v_table_name; END; EXCEPTION WHEN OTHERS THEN -- 记录表不存在的错误 v_error_message := SQLERRM; UPDATE TABLE_UPDATE_AUDIT SET ERROR_MESSAGE = v_error_message, PROCESSED_INDICATOR = 'N', PROCESSED_TIMESTAMP = CURRENT_TIMESTAMP(), PROCESS_RESULT = 'Fail' WHERE DB_NAME = v_db_name AND SCHEMA_NAME = v_schema_name AND TABLE_NAME = v_table_name; END; END FOR; RETURN 'Procedure executed successfully.'; END; $$;
额外说明
- 请将
EXCEL_TABLE_DESCRIPTIONS替换为你实际存储Excel加载数据的表名。 - 使用
CURRENT_TIMESTAMP()替代getdate(),这是Snowflake的标准时间函数。 - 用绑定变量处理ALTER TABLE的对象名和注释,避免SQL注入并符合Snowflake最佳实践。
内容的提问来源于stack exchange,提问作者jove

