postgresql表中的默认递增值

时间:2012-10-10 12:04:30

标签: postgresql

我进行了大量搜索但无法找到我的查询的答案。然而,我所要求的可能是不可能的:

我有一系列表格,但为了简化,我们假设我有以下

第      articleId SERIAL

ArticlePageNumber      articleId / 引用Article.articleId /      pageNumber Int

这是相当自我解释的,但是可以接受的数据是

 Article
 -------
 articleiId
 1
 2

 ArticlePageNumber
 -----------------
 articleiId   pageNumber
 1            1
 1            2
 1            3
 1            4
 1            5
 1            6
 2            1
 2            3
 2            5
 2            2
 2            4

不可接受的表格是ArticlePageNumber

 ArticlePageNumber
 -----------------
 articleiId   pageNumber
 1            1
 1            1
 1            2
 1            3
 1            4
 1            5
 2            1
 2            3
 2            5
 2            4

我希望ArticlePageNumber.pageNumber的默认值增加类似于serial的方式,但是对于具有该特定articleId的条目,下一个值将依赖于先前的值(如果没有,则为1)。

我更喜欢在SQL中作为约束和检查而不是代码,但我猜这可能是不可能的。

1 个答案:

答案 0 :(得分:2)

您需要的行为并非不可能,但却很棘手:

易于完成 - 一个页码序列,不知道它附加到哪个文章

首先,为页码创建一个序列,如下所示:

CREATE SEQUENCE page_number_sequence;

如果您需要调整分配大小,请启动等look here

然后:在定义“article_page_number”表时,定义pageNumber字段,如下所示:

# omitted boilerplate
pageNumber integer not null default nextval('page_number_sequence')

这将以递增的方式自动为您填写页码。如果您不想要“gappy”序列号,请在设置序列时将增量设置为1(默认值),将缓存设置为1(默认值)。

Trickier - 了解文章的自动增量页码序列

您可以使用每行触发器来侦听文章页码表上的保存,并且:

  • 检查特定于该文章ID的序列是否存在并创建它不存在
  • 如果不存在,则从此序列中分配页码

下面的代码只经过了光测试,但它应该说明这个想法......

CREATE TABLE IF NOT EXISTS article (
  articleId SERIAL PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS article_page_number (
  articleId INTEGER NOT NULL,
  pageNumber INTEGER NOT NULL,
  CONSTRAINT article_fk FOREIGN KEY (articleId)
      REFERENCES article (articleId)
);

CREATE OR REPLACE FUNCTION page_number_trg()
  RETURNS trigger AS
$BODY$ DECLARE 
  seqname VARCHAR(60):= NULL;
BEGIN
  IF (TG_OP = 'INSERT') THEN
    BEGIN
      seqname:= 'pageno_seq_'||NEW.articleId;
      IF NOT EXISTS (SELECT 0 FROM pg_class where relname = seqname) THEN
        EXECUTE 'CREATE SEQUENCE '||seqname;
      END IF;
      IF NEW.pageNumber IS NULL THEN
        NEW.pageNumber := nextval(seqname);
      END IF;
    END;
  END IF;
  IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF; 
END
; $BODY$
LANGUAGE plpgsql;

CREATE TRIGGER page_number_trg
BEFORE INSERT ON article_page_number
FOR EACH ROW
EXECUTE PROCEDURE page_number_trg();