0

我进行了很多搜索,但无法找到我的查询的答案。但是,我要问的可能是不可能的:

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

文章文章 ID 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 中的约束和检查而不是代码,但我猜这可能是不可能的。

4

1 回答 1

2

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

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

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

CREATE SEQUENCE page_number_sequence;

如果您需要调整分配大小,开始等看这里

那么:在定义“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();
于 2012-10-10T13:47:28.543 回答