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

带逗号的Decimal值传入PostgreSQL函数的报错问题

问题:PostgreSQL函数调用因逗号小数分隔符导致参数解析错误

错误信息

ERROR: cannot cast type record to numeric 
LINE 1: SELECT controldubbel2('2023-01-05'::date,'DL453453530005300114'::varchar,'HALTEST'::varchar,'Naam: John Doe'::varchar,10,00::numeric, 23686,98::numeric, 'GT'::varchar)
SQL state: 42846

函数定义

CREATE OR REPLACE FUNCTION public.controldubbel2(_datum date, _naamtegen character varying, _tegenrekening character varying, _omschrijving character varying, _bedrag numeric, _saldo numeric, _code character varying)
 RETURNS TABLE(bestaat boolean)
 LANGUAGE plpgsql
AS $function$
BEGIN
    RETURN QUERY
    SELECT EXISTS (SELECT 1 FROM "xxxxxxxxxxxxxxx" WHERE "DATUM"=_datum
    AND "TEGENREKENING_IBAN_BBAN"=_tegenrekening AND
    "NAAM_TEGENPARTIJ"=_naamtegen AND "Omschrijving_1"=_omschrijving AND
    "BEDRAG"=_bedrag AND "saldo"=_saldo AND "CODE"=_code) as bestaat
LIMIT 1;
END
$function$

Python执行代码

cursor.execute(f"SELECT controldubbel2('{datum2}', '{tegenrekening}', '{naamtegen}', '{omschrijving1}', '{bedrag}', '{saldo}', '{code}')")

核心问题

  1. 参数数量不匹配:函数定义仅接受7个参数,但调用时带逗号的数值(如10,00)被PostgreSQL识别为参数分隔符,拆成两个独立参数,导致实际传入参数数量远超函数预期,触发类型转换错误。
  2. 小数分隔符冲突:PostgreSQL默认以.作为小数分隔符,而数据源使用,,直接拼接字符串会引发解析混乱。

解决方法

方法1:使用Python参数化查询(推荐)

参数化查询既能避免SQL注入风险,又能自动处理类型转换,彻底解决分隔符问题:

# 若bedrag/saldo是带逗号的字符串,先转换为数值
bedrag_num = float(bedrag.replace(',', '.'))
saldo_num = float(saldo.replace(',', '.'))

# 用占位符传递参数(psycopg2用%s,其他驱动可能用?)
cursor.execute(
    "SELECT controldubbel2(%s, %s, %s, %s, %s, %s, %s)",
    (datum2, tegenrekening, naamtegen, omschrijving1, bedrag_num, saldo_num, code)
)

方法2:手动处理分隔符后拼接SQL(不推荐,存在SQL注入风险)

如果必须用字符串拼接,先将数值中的逗号替换为点,再转换为numeric:

bedrag_formatted = bedrag.replace(',', '.')
saldo_formatted = saldo.replace(',', '.')

cursor.execute(f"""
SELECT controldubbel2(
    '{datum2}', 
    '{tegenrekening}', 
    '{naamtegen}', 
    '{omschrijving1}', 
    {bedrag_formatted}::numeric, 
    {saldo_formatted}::numeric, 
    '{code}'
)
""")

或者用PostgreSQL的TO_NUMBER函数直接处理带逗号的字符串:

cursor.execute(f"""
SELECT controldubbel2(
    '{datum2}', 
    '{tegenrekening}', 
    '{naamtegen}', 
    '{omschrijving1}', 
    TO_NUMBER('{bedrag}', '999999999D99', 'NLS_NUMERIC_CHARACTERS='',.'''), 
    TO_NUMBER('{saldo}', '999999999D99', 'NLS_NUMERIC_CHARACTERS='',.'''), 
    '{code}'
)
""")

方法3:修改数据库区域设置(全局生效,谨慎操作)

如果整个数据库环境都使用逗号作为小数分隔符,可以修改PostgreSQL的lc_numeric参数为对应区域(如nl_NL.UTF-8),但此设置会影响所有数据库操作,需评估后执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:35:42