各位童鞋大家好,今天进行基础sql第三篇,update.在实际dml语句操作中,update应该是除了select使用频率最高的sql语句了吧。
update mytable set age = 22 where name='zhang';
update (select m.flag from mytable m where m.age = 22) set flag = 1;
update mytable T
set T.next_id =
(SELECT o.next_id
FROM mytable2 O
WHERE T.preId = O.preId
);
update mytable r set r.is_check = 1
where r.scan_time > to_date('2020-05-11 12:12:12','yyyy-mm-dd hh24:mi:ss')-1/12 and r.scan_time <= to_date('2020-06-11 12:12:12','yyyy-mm-dd hh24:mi:ss')
and r.is_check = 0
and mod(r.reach_id, 3) = 1;
这些语句都是比较基本的update语句了。在实际工作中,肯定经常会用到。update 语句还是比较简单的。看似复杂点的还是语句的条件本身。比如上例的2,3,4语句,语句2是查询某一个结果集然后对其
全部更新。语句3是两个表根据字段preId(多数情况下唯一)的关联关系进行字段关系。语句4更新语句就是where条件多了一点点。
下面咱们在看一个'update'
select * from mytable where id = 3 for update ;
首先说明下,这是个查询语句。把结果查询出来后,再进行手动更新。然后提交commit。这样就能够保证在查询到修改提交后这段时间段内不会被其他session更新。其本质上就是悲观锁了。for update
语句我在实际工作中使用的不多,毕竟在for update整个过程中查询出来的数据会一直占用锁。如果其他会话也对查询结果集里的数据进行更新就会导致堵塞,情况严重者甚至可能会导致死锁发生。
我们都知道,在更新语句执行时候,会产生表锁(tm) 和行锁(tx)。语句提交前,行锁会一直占用不被释放。这个时候如果其他session也执行相同数据更新就会导致一直堵塞直到获取到锁为止。如果有这么
一个需求,每天定时更新前3天的数据(数据量大概至少几百万),这个时候比较好的处理办法就是根据创建时间比如每5分钟间隔去更新数据。一直到更新完毕跳出循环体。这个时候童鞋们就要注意了,这可是一个
很大的事务,执行时间可能会有几分钟甚至十几分钟。在这么大的一个事务里,而且又有更新语句就要慎用事务了。否则如果有其他会话也处理前3天的数据里面的某部分的话。就很容易出现堵塞甚至死锁。
一个地方出现堵塞,往往会导致其被调用方也会堵塞。这样连锁堵塞就很可怕了。所以更新语句看似简单,在一个比较复杂的系统里面要处理好也并非易事。
update mytable s
set s.age = 23
where s.next_id = 123
and s.create_time > trunc(sysdate) - 2;
next_id建索引,create_time做分区。这样一个update语句执行效率是非常之快的。在大数据量更新时候,索引和分区的作用也少不了。
说到update,咱们还需要再次说说merge into .merge into 是条件不匹配就新增,条件匹配就更新。所以在更新时候,可以考虑merge into语句。
好了,上面update基本用法包括批量更新和单条更新都讲到了。而且提到事务锁这一块。update关键一点是要注意锁的获取和释放,顺便在这补充下insert堵塞的情况吧。insert堵塞情况并不多。其中一个场景
就是在操作一个含有主键表的时候,因为某些原因(比如网络,其他堵塞)同个操作请求了多次。这样就会出现多个请求insert,当一个请求insert的过程中,其他请求会等待。等待结束后,其他请求继续insert,就会
出现唯一约束错误了。这个场景出现的概率还是比较多的。
今天就先聊到这吧。下一篇咱们聊聊delete, 继续咱们基础的sql之旅吧!
(不急,很快的)