昨天下午技术部java开发人员报告说 线上数据库无法删除数据,要我查看下数据库是否有什么锁住. 我还以为是死锁或者是什么阻塞之类了.
折腾下没有发现!
叫它把语句发来,他就把表名,而且是截图发过来的!
根据表名去找 删除的语句
select sql_id,piece,sql_textfrom v$sqltext_with_newlineswhere sql_id in(select sql_idfrom v$sqltext_with_newlineswhere 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||',')>02014-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||'')>02014-3-13 17:45:02,3319,fpkt91ujqu853:delete from paynum_element e where instr(:1,','||e.ple_pl_id||',')>02014-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 331 233 1331 13319 12279 02282 02281 02280 0
instr(源字符串, 目标字符串, 起始位置, 匹配序号)
在oracle/plsql中,instr函数返回要截取的字符串在源字符串中的位置。只检索一次,就是说从字符的开始
发现了什么没?对没错误 狗屎的家伙 居然写反了 instr(',3319,',''||pl_id||'')
正常写法是instr(''||pl_id||'', ',3319,')
正常设计是:
delete from paynum paynum where paynum.pl_id=to_number(:?)
