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

如何获取asyncpg执行的填充参数后的完整SQL查询语句?

核心结论

asyncpg 本身没有提供你期望的connection.expected_query这类方法,原因是 asyncpg 采用 PostgreSQL 服务端预处理语句协议,查询模板和参数是分开传输到数据库服务端的,客户端不会提前拼接完整SQL,既可以避免SQL注入风险,也能提升查询性能。你可以通过以下几种方案满足调试需求:


方案1:开启PostgreSQL服务端日志(结果最准确)

修改PostgreSQL配置文件postgresql.conf,调整以下参数:

log_statement = 'all'
log_min_messages = debug1

重启PostgreSQL服务后,所有实际执行的完整SQL语句都会被记录到日志文件中,参数是服务端实际替换后的结果,完全准确无转义误差。


方案2:自定义调试用SQL拼接函数(无需实际执行即可查看)

你可以自己实现一个简单的参数替换函数,适配PostgreSQL的$N占位符规则,调试时传入和execute完全一致的入参即可得到拼接后的SQL,示例实现如下:

def build_debug_pg_query(query_template: str, *args) -> str:
    processed_params = []
    for arg in args:
        if isinstance(arg, str):
            # 转义字符串中的单引号
            escaped_val = arg.replace("'", "''")
            processed_params.append(f"'{escaped_val}'")
        elif arg is None:
            processed_params.append("NULL")
        elif isinstance(arg, (int, float, bool)):
            processed_params.append(str(arg))
        # 其他类型比如日期、二进制等可以根据需求自行扩展处理逻辑
        else:
            processed_params.append(f"'{str(arg)}'")
    # 按顺序替换占位符
    result_query = query_template
    for idx, param in enumerate(processed_params, start=1):
        result_query = result_query.replace(f"${idx}", param)
    return result_query

使用方式和你期望的expected_query完全一致:

query = QUERY_1
param1 = query_params_dict["field_1"]
param2 = int(query_params_dict["field_id"])
# 调试时直接打印查看,不需要执行查询
print(build_debug_pg_query(query, param1, param2))
# 实际执行还是用原生参数绑定,避免注入风险
await connection.execute(query, param1, param2)

注意:这个函数仅用于调试排查问题,不要在生产环境用它拼接SQL后直接执行,会存在SQL注入风险。


方案3:开启asyncpg的DEBUG日志

无需修改数据库配置,只需调整日志级别即可看到分开记录的查询模板和对应参数:

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("asyncpg").setLevel(logging.DEBUG)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:24:04