Instr带来的BUG
昨天下午技术部JAVA开发人员报告说 线上数据库无法删除数据,要我查看下数据库是否有什么锁住. 我还以为是死锁或者是什么阻塞之类了. 折腾下没有发现! 叫它把语句发来,他就把表名,而且是截图发过来的! 根据表名去找 删除的语句 SELECT SQL_ID,PIECE,SQL_TEXTF
昨天下午技术部JAVA开发人员报告说 线上数据库无法删除数据,要我查看下数据库是否有什么锁住. 我还以为是死锁或者是什么阻塞之类了.
折腾下没有发现!
叫它把语句发来,他就把表名,而且是截图发过来的!
根据表名去找 删除的语句
SELECT SQL_ID,PIECE,SQL_TEXT FROM V$SQLTEXT_WITH_NEWLINES WHERE SQL_ID IN( SELECT SQL_ID FROM V$SQLTEXT_WITH_NEWLINES WHERE SQL_TEXT LIKE '%table_name%') ORDER BY SQL_ID,PIECE;发现DELETE开头的语句 共3条 通过语句ID 找出变量
select * from v$sql_bind_capture where sql_id in ('fpkt91ujqu853');
gquw3xgbqvu13: delete from paynum p WHERE INSTR(:1,','||PL_ID||',')>0 2014-3-12 17:44:13 ,3251,3250,3248,3247, 2014-3-11 11:56:18 ,3249, b5yjgrqx6j2dm: delete from paynum paynum WHERE INSTR(:1,''||PL_ID||'')>0 2014-3-13 17:45:02 ,3319, fpkt91ujqu853: delete from paynum_ELEMENT e WHERE INSTR(:1,','||e.ple_pl_id||',')>0 2014-3-13 17:45:02 ,3319, 其中 pay_element 是关联表 该表有paynum的外键 就是这个外键约束报的错误.
从上面看 删除paynum有两条不同的SQL语句 第一个估计是旧的,第二个是最近上线的.
根据变量的值 可以了解 先删除 关联表 输入变量 ',3319,' 然后删除PAYNUM表 同样输入变量',3319,'
我们同样可以看出来参数:1 不仅可以输入单个变量值,还可以输入一串变量的值 比如 ',3251,3250,3248,3247,'
从数据表查询3319值的记录 关联表 paynum_ELEMENT 已经被删除,而 PAYNUM 还存在 !
我们综合下
delete from paynum paynum WHERE INSTR(',3319,',''||PL_ID||'') > 0
对于这样的语句 做为地球普通人的我实在难以理解和猜透. 通过自身努力终于理解了它,来之汪星的写法!
select pl_id, INSTR(',3319,',''||PL_ID||'') from paynum;这样看出先生产个虚拟列,其值 是PL_ID和3319的比较值. 然后这个值是大于0 则删除;
我测试下 它确实能删除记录. 不过线上的行为就表现如下
PL_ID INSTR('3319',''||PL_ID||'') 1 3 31 2 33 1 331 1 3319 1 2279 0 2282 0 2281 0 2280 0INSTR
(源字符串, 目标字符串, 起始位置, 匹配序号)
在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置。只检索一次,就是说从字符的开始
发现了什么没?对没错误 *的家伙 居然写反了 INSTR(',3319,',''||PL_ID||'')
正常写法是INSTR(''||PL_ID||'', ',3319,')
正常设计是:
delete from paynum paynum where paynum.pl_id=to_number(:?)
上一篇: 基于WPF的窗体控件自适应思考
下一篇: group by 语句用法详解