相同update语句在MySQL,Oracle的不同表现(r12笔记第30天)

时间:2022-05-05
本文章向大家介绍相同update语句在MySQL,Oracle的不同表现(r12笔记第30天),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

今天有个朋友问我一个SQL问题,大体是一个update语句,看起来逻辑没有问题,但是执行的时候却总是报错。

语句和报错信息为:

UPDATE payment_data rr SET rr.penalty_date = '2017-4-12' where rr.id = (SELECT min(r.id) FROM payment_data r where data_no = (SELECT data_no FROM user_debt WHERE out_trade_no = 'bestpay_order_no1491812746329')); ERROR 1093 (HY000): You can't specify target table 'rr' for update in FROM clause

对于这个问题,如果不想使用中间表,那么可以改写为下面的形式,就是中间做了一个包装来规避这个问题。

UPDATE payment_data rr SET rr.penalty_date = '2017-4-12' where rr.id = (SELECT min(t.id) FROM (select id,data_no from payment_data r) t where t.data_no = (SELECT data_no FROM user_debt WHERE out_trade_no = 'bestpay_order_no1491812746329'));

但是这个问题才是开始,我对比了一下在两个数据库的表现,还是有很大的差别,我们先在MySQL复现一下。

创建两个表如下:

create table payment_data(id int,data_no varchar(30), penalty_date date); create table user_debt(out_trade_no varchar(30), data_no varchar(30));

在Oracle中数据类型稍有变化。

create table payment_data(id int,data_no varchar2(30), penalty_date date); create table user_debt(out_trade_no varchar2(30), data_no varchar2(30));

然后我会逐个运行下面的4个语句,同时标识在MySQL,Oracle的表现。

1)语句1

UPDATE payment_data rr SET rr.penalty_date = '2017-4-12' where rr.id = (SELECT min(r.id) FROM payment_data r where data_no = (SELECT data_no FROM user_debt WHERE out_trade_no = 'bestpay_order_no1491812746329')); MySQL: 会报错,提示DML语句不能同时查询同一个表。

Oracle:无报错,可以正确解析和执行。

2)语句2

UPDATE payment_data rr SET rr.penalty_date = '2017-4-12' where rr.id = (SELECT min(t.id) FROM (select id,data_no from payment_data r) t where t.data_no = (SELECT data_no FROM user_debt WHERE out_trade_no = 'bestpay_order_no1491812746329'));

MySQL:执行成功

Oracle: 执行成功

3)语句3

UPDATE payment_data rr, (SELECT min(r.id) id FROM payment_data r where data_no = (SELECT data_no FROM user_debt WHERE out_trade_no = 'bestpay_order_no1491812746329')) t SET rr.penalty_date = '2017-4-12' where rr.id =t.id;

MySQL:能够正确执行

Oracle:解析出错

4)语句4 UPDATE payment_data rr SET rr.penalty_date = '2017-4-12' where rr.id = (SELECT min(r.id) FROM payment_data r inner join user_debt b on r.data_no = b.data_no WHERE b.out_trade_no = 'bestpay_order_no1491812746329');

MySQL:执行失败

Oracle:执行正常