如何在FreeSWITCH的Lua脚本中捕获Dbh执行SQL的异常错误?
在FreeSWITCH Lua脚本中捕获SQL唯一键约束异常
错误背景
执行SQL更新时触发唯一键约束错误,错误日志如下:
2025-01-21 20:45:59.832751 90.95% [ERR] switch_odbc.c:529 ERR: [update tbl_channel set msisdn = 100 where chan_name = 'CH001']
[STATE: 23000 CODE 2601 ERROR: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Cannot insert duplicate key row in object 'dbo.tbl_channel' with unique index 'idx_msisdn'. The duplicate key value is (100).
]
原因是SQL Server中dbo.tbl_channel表的idx_msisdn唯一索引限制msisdn字段不可重复,更新操作违反了该约束。
Lua脚本捕获异常的实现
FreeSWITCH的Dbh:query()方法执行SQL出错时会抛出Lua异常,可通过Lua的pcall或xpcall函数捕获异常,还能通过错误信息中的错误码(2601)或SQL状态码(23000)精准判断是否为唯一键约束错误。
方式1:使用pcall捕获异常
local dbh = freeswitch.Dbh(DSN) -- 用pcall包裹query调用,捕获执行异常 local success, err = pcall(function() dbh:query("update tbl_channel set msisdn = 100 where chan_name = 'CH001'") end) if not success then -- 判断是否为唯一键约束冲突 if string.find(err, "CODE 2601") or string.find(err, "STATE: 23000") then freeswitch.consoleLog("err", "唯一键约束冲突:msisdn=100已存在\n") else freeswitch.consoleLog("err", "SQL执行错误:" .. err .. "\n") end end dbh:release()
方式2:使用xpcall自定义错误处理
local function handleSqlError(err) -- 针对性处理唯一键约束错误 if string.find(err, "CODE 2601") or string.find(err, "STATE: 23000") then freeswitch.consoleLog("err", "唯一键约束冲突:msisdn=100已存在\n") else freeswitch.consoleLog("err", "SQL执行错误:" .. err .. "\n") end end local dbh = freeswitch.Dbh(DSN) -- xpcall将异常传递给自定义处理函数 xpcall(function() dbh:query("update tbl_channel set msisdn = 100 where chan_name = 'CH001'") end, handleSqlError) dbh:release()
关键说明
pcall返回两个值:布尔值表示执行是否成功,第二个值为成功时的返回结果或失败时的错误信息。xpcall需要传入自定义错误处理函数,异常发生时会自动调用该函数处理。- 匹配错误信息中的
CODE 2601(SQL Server唯一键重复错误码)或STATE: 23000(SQL标准约束冲突状态码),可精准识别唯一键约束异常,避免误处理其他SQL错误。
内容的提问来源于stack exchange,提问作者user28466051
相关产品推荐
相关产品推荐

