【问题标题】:POSTGRES sequence TRIGGER on non primary key非主键上的 POSTGRES 序列触发
【发布时间】:2017-02-21 08:24:26
【问题描述】:

我有一个 PostgreSQL 数据库版本 9.5.0。

UserComments 的创建方式如下:

create table UserComments (  
  userId integer, 
  commentNr integer, 
  comment text,  
  UNIQUE (userId, commentNr)
);

表格无法更改,也无法添加额外的表格。

我想根据userId 条目的数量在commentNr 上创建一个序列(换句话说:一个自动递增的值)。 对于具有相同userId 的每个新条目,其值应递增。
示例:

用户名 |评论编号 |评论 -------|-----------|--------- 1 | 1 |废话 1 | 2 |更多 bla 2 | 1 |我的名字 1 | 3 |甚至更多bla

我已经找到了一些关于“触发器”和“窗口函数”的答案,但没有一个对我真正有用,因为我不允许更改表格。 最好的解决方案是在每个INSERT 上触发一个自动counts/计算commentNr 的触发器,这样我就可以添加一个新条目

insert into user(userId, comment) values ('1', 'bla');

任何帮助将不胜感激。

【问题讨论】:

  • primary key(id), :: 您的表中没有 id 列。请贴出真实代码。
  • 你是对的——这个例子不需要主键。

标签: postgresql triggers count sequence


【解决方案1】:

要自动计算 commentNr 字段,您可以使用 TRIGGER:

CREATE INDEX i1 ON UserComments (userId, commentNr DESC);

CREATE OR REPLACE FUNCTION set_commentNr() RETURNS TRIGGER AS $sql$
BEGIN
    NEW.commentNr = coalesce(max(commentNr) + 1, 1) FROM UserComments WHERE UserId = NEW.userID;
    RETURN NEW;
END;
$sql$ LANGUAGE plpgsql STABLE;


CREATE TRIGGER ins_comment BEFORE INSERT ON UserComments FOR EACH ROW EXECUTE PROCEDURE set_commentNr();

小测试:

insert into userComments (userId, comment) values ('1', 'bla');
insert into userComments (userId, comment) values ('1', 'bla');
insert into userComments (userId, comment) values ('2', 'bla');
insert into userComments (userId, comment) values ('1', 'bla');
insert into userComments (userId, comment) values ('2', 'bla');

SELECT * FROM userComments;

 userid | commentnr | comment 
--------+-----------+---------
      1 |         1 | bla
      1 |         2 | bla
      2 |         1 | bla
      1 |         3 | bla
      2 |         2 | bla
(5 rows)

创建索引 i1 以提高计算下一个值的性能:

                                                             QUERY PLAN                                                              
-------------------------------------------------------------------------------------------------------------------------------------
 Result  (cost=4.17..4.18 rows=1 width=4) (actual time=0.032..0.032 rows=1 loops=1)
   InitPlan 1 (returns $0)
     ->  Limit  (cost=0.15..4.17 rows=1 width=4) (actual time=0.026..0.026 rows=1 loops=1)
           ->  Index Only Scan using i1 on usercomments  (cost=0.15..24.27 rows=6 width=4) (actual time=0.021..0.021 rows=1 loops=1)
                 Index Cond: ((userid = 1) AND (commentnr IS NOT NULL))
                 Heap Fetches: 1
 Planning time: 0.238 ms
 Execution time: 0.095 ms

【讨论】:

    【解决方案2】:

    对于这种简单的情况,没有必要创建触发器。可以在 CTE 或子查询中计算并插入正确的序列。

    注意:如果使用下面的sql,插入的userId必须指定两次

    INSERT INTO "user" ("userId", "commentNr", "comment") (
    WITH 
      nextval AS (
      SELECT COALESCE(MAX("commentNr"),0)+1 commentNr
      FROM "user"
      WHERE "userId" = '1'
    )
    SELECT '1', nextval.commentNr, 'bla'
    FROM nextval
    );
    

    【讨论】:

      猜你喜欢
      • 2020-06-04
      • 1970-01-01
      • 1970-01-01
      • 2018-04-03
      • 2017-09-06
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      • 2013-12-02
      相关资源
      最近更新 更多