PostgreSQL V10+Python3.6 AFTER INSERT触发器出现'ts'未定义错误
解决PostgreSQL PL/Python触发器中的NameError: 'ts'未定义问题
嘿,这个问题挺有意思的——虽然你看到错误指向的代码行里没显式出现ts,但背后肯定有隐式引用的地方!我来帮你捋捋可能的原因和排查方向:
1. 检查代码行的完整上下文(可能被截断)
回溯信息显示错误在第30行的代码段,但有时候错误提示里的代码会被截断,实际完整代码里可能包含了ts:
- 你是不是用了f-string或字符串格式化,比如写成了
f"... {ts} ..."或者"%s" % (ts, ...),但没定义ts变量? - 该行代码是不是调用了某个函数,比如
log_transaction(..., ts, ...),其中ts作为参数传入但未定义?
2. 检查触发器函数中的时间戳变量拼写
在PL/Python触发器函数中,系统提供了内置的触发器上下文变量,比如触发时间是TG_TIMESTAMP。如果你本来想引用这个内置变量,但不小心写成了ts,就会导致未定义错误。
举个例子,如果你想记录触发器触发的时间,正确的写法是:
# 直接使用内置的触发时间 plpy.execute( "INSERT INTO transaction_log (symbol, price, fee, amount, direction, note, ts) VALUES ($1, $2, $3, $4, $5, $6, $7)", [cashRslt[0]['symbol'], cashRslt[0]['price'], 0.00, tbRow['amount'], const['SW_OUT'], note, TG_TIMESTAMP] )
如果需要自定义时间(比如当前UTC时间),要先导入模块并定义变量:
import datetime ts = datetime.datetime.utcnow() # 之后再在代码中使用ts
3. 检查嵌套函数或外部依赖
如果第30行调用了其他自定义函数(比如你自己写的日志函数),要检查这个被调用的函数内部是否引用了ts,但你没有把这个变量作为参数传递进去。比如:
# 假设你调用了这个函数,但没传ts write_transaction_log(cashRslt[0]['symbol'], cashRslt[0]['price'], ..., note) # 而write_transaction_log内部用到了ts,但没定义 def write_transaction_log(symbol, price, ..., note): plpy.execute(f"INSERT INTO ... VALUES (... {ts} ...)") # 这里ts未定义
4. 检查SQL语句中的占位符误用
如果你用plpy.execute执行SQL时,不小心在SQL语句里写了{ts}(比如误把参数化占位符写成了f-string格式),但实际没有定义ts,也会触发这个错误。正确的参数化查询应该用$1、$2这种占位符,避免直接拼接字符串:
# 错误写法(可能包含未定义的ts) plpy.execute(f"INSERT INTO ... VALUES ({cashRslt[0]['symbol']}, ..., {ts})") # 正确的参数化写法 plpy.execute( "INSERT INTO ... VALUES ($1, $2, $3, $4, $5, $6, $7)", [cashRslt[0]['symbol'], cashRslt[0]['price'], 0.00, tbRow['amount'], const['SW_OUT'], note, TG_TIMESTAMP] )
总结下来,核心就是找到所有隐式或显式引用ts的地方,要么定义它,要么替换成正确的变量(比如TG_TIMESTAMP)。
内容的提问来源于stack exchange,提问作者Crashmeister
相关产品推荐
相关产品推荐

