You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snowflake Python存储过程报错:'Session'对象无'execute'属性

问题解决:Snowflake Python存储过程报错'Session' object has no attribute 'execute'

问题根源

你的代码存在两个核心问题:

  1. Handler函数参数错误:Snowflake Python存储过程的handler函数第一个参数是snowflake.snowpark.Session实例,而非自定义的context对象。
  2. SQL执行方法错误:Session对象没有execute方法,正确执行SQL的方式是调用session.sql()方法,再通过collect()获取结果集。

修正后的完整代码

CREATE OR REPLACE PROCEDURE TEST_PROCEDURE(
    PAR1 STRING,
    PAR2 STRING,
    PAR3 STRING)
   
    RETURNS STRING
    LANGUAGE PYTHON
    RUNTIME_VERSION = '3.8'
    PACKAGES = ('snowflake-snowpark-python')
    HANDLER = 'filter_by_role'
    EXECUTE AS CALLER
AS
$$

def filter_by_role(session, PAR1, PAR2, PAR3):   
    
    try:
        # Convert comma-separated strings to sets
        par1_set = set(PAR1.split(',')) if PAR1 is not None else None
        par2_set = set(PAR2.split(',')) if PAR2 is not None else None

        # Query to retrieve eligible rows
        main_query = """
        SELECT COL1, COL2 FROM TABLE_MAIN;
        """
        
        # 获取查询结果集,用collect()返回行列表
        eligible_rows = [(row.COL1, row.COL2) for row in session.sql(main_query).collect()]

        for col1, col2 in eligible_rows:
            # 检查过滤条件
            if (par1_set is None or col1 in par1_set) and (par2_set is None or col2 in par2_set):
                # 使用IDENTIFIER()处理动态表名,避免SQL注入和特殊字符问题
                query = f"""
                INSERT OVERWRITE INTO IDENTIFIER('{col1}.{col2}') 
                SELECT * FROM IDENTIFIER('{col1}.{col2}') AT (TIMESTAMP => '{PAR3}'::timestamp)
                """
                # 执行SQL,无需返回结果时直接调用collect()或execute()
                session.sql(query).collect()
            else:
                # 打印跳过日志
                print(f"Skipped due to exclusion criteria: {col1}, {col2}")

        return "Executed successfully!"

    except Exception as e:
        return "Error: " + str(e)
$$;

关键修正点说明

  • 参数替换:将handler函数的第一个参数从context改为session,这是Snowpark存储过程的标准参数约定。
  • SQL执行方式:用session.sql(QUERY).collect()替代context.execute(),collect()会触发SQL执行并返回结果行对象。
  • 动态表名安全处理:使用IDENTIFIER()包裹动态生成的表名{col1}.{col2},避免因表名含特殊字符或SQL注入风险导致的错误。
  • 结果集遍历:Snowpark返回的行对象可以通过属性名(如row.COL1)直接访问列值,比索引访问更直观。

额外建议

若PAR3是用户输入的时间戳,建议使用绑定变量而非字符串拼接,进一步提升安全性:

query = """
INSERT OVERWRITE INTO IDENTIFIER(?) 
SELECT * FROM IDENTIFIER(?) AT (TIMESTAMP => ?::timestamp)
"""
session.sql(query, bindings=[f"{col1}.{col2}", f"{col1}.{col2}", PAR3]).collect()

内容的提问来源于stack exchange,提问作者My80

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:57:24