POSTGRES序列TRIGGER非主键

时间:2017-02-21 08:24:27

标签: postgresql triggers count sequence

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

表格UserComments的创建方式如下:

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

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

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

userId | commentNr | comment
-------|-----------|---------
1      |   1       | blabla
1      |   2       | more bla
2      |   1       | myownbla
1      |   3       | evenmorebla

我已经找到了“触发器”和“窗口函数”的一些答案,但由于我不允许更改表,因此没有一个对我有用。 最佳解决方案是每个INSERT自动counts /计算commentNr的触发器,以便我可以使用

添加新条目
insert into user(userId, comment) values ('1', 'bla');

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

对于这样的简单情况,没有必要创建触发器。可以在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
);

答案 1 :(得分:0)

要自动计算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