Oracle vs PostgreSQL,研发注意事项(13) - UPDATE语句

在应用开发中,取序列号时除了利用数据库提供的sequence之外,还可以通过使用序列表,每取一个值,值加一.
比如:

-- Oracle语法
-- 获取序列号
drop table t_seq purge;
create table t_seq(id int);
insert into t_seq values(0);
commit;
create or replace function func_getid return int
is
  v_id int;
begin
  update t_seq set id = id+1 returning id into v_id;
  return v_id;
  dbms_output.put_line('ID = '||v_id);
end;
/

其中t_seq是序号表,函数func_getid对id加一并返回新值.
使用该函数更新业务表t_result


drop table t_result purge;
create table t_result(id int);
insert into t_result values(1);
declare
begin
  for i in 1..4 loop
    insert into t_result select * from t_result;
  end loop;
end;
/
update t_result set id = func_getid;

在Oracle中,多个会话同时执行update语句,t_result的ID是可以保证连续的,但在PG中却会出现”跳号”
Oracle

-------------------- Session 1
SQL> update t_result set id = func_getid;
已更新 16 行。
SQL> commit;
提交完成。
SQL>
SQL> select * from t_result;
        ID
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        ID
----------
        12
        13
        14
        15
        16
已选择 16 行。
--------------------- Session 2
SQL> update t_result set id = func_getid;
已更新 16 行。
SQL> select * from t_result;
        ID
----------
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        ID
----------
        28
        29
        30
        31
        32
已选择 16 行。
SQL>

PostgreSQL
创建基表


drop table if exists t_seq;
create table t_seq(id int);
insert into t_seq values(0);
CREATE OR REPLACE FUNCTION func_getid() RETURNS int
LANGUAGE plpgsql
AS
$func_getid$
DECLARE 
  v_id int;
BEGIN
  update t_seq 
  set id = id + 1
  returning id into v_id;
  RETURN v_id;
END;
$func_getid$;
drop table t_result;
create table t_result(id int);
insert into t_result select generate_series(1,16);

更新数据

------------- Session 1
[local]:5014 pgmaster@testdb=# begin;
BEGIN
Time: 0.299 ms
[local]:5014 pgmaster@testdb=#* update t_result set id = func_getid();
UPDATE 16
Time: 1.132 ms
[local]:5014 pgmaster@testdb=#* select * from t_result;
 id
----
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
(16 rows)
Time: 0.676 ms
[local]:5014 pgmaster@testdb=#*
[local]:5014 pgmaster@testdb=#* commit; ---- 在Session 执行update后执行
COMMIT
Time: 4.250 ms
[local]:5014 pgmaster@testdb=#
------------- Session 2
[local]:5014 pgmaster@testdb=# begin;
BEGIN
Time: 0.445 ms
[local]:5014 pgmaster@testdb=#* update t_result set id = func_getid();
UPDATE 16
Time: 2959.112 ms (00:02.959)
[local]:5014 pgmaster@testdb=#* select * from t_result;
 id
----
 18
 20
 22
 24
 26
 28
 30
 32
 34
 36
 38
 40
 42
 44
 46
 48
(16 rows)
Time: 0.465 ms
[local]:5014 pgmaster@testdb=#*

“序号”出现了跳号的情况,原因是什么?后续有时间写个源码解读.

请使用浏览器的分享功能分享到微信等