0

私はたくさんの検索を実行しましたが、私の質問に対する答えを見つけることができません。しかし、私が求めていることは不可能かもしれません:

私は一連のテーブルを持っていますが、簡単にするために、次のものがあると仮定しましょう

記事articleIdSERIAL

ArticlePageNumberarticleId/参照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のデフォルト値を、シリアルと同じようにインクリメントしたいのですが、次の値は、その特定の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')

これにより、ページ番号が段階的に自動的に入力されます。「ギャップのある」シーケンス番号が必要ない場合は、シーケンスを設定するときに、インクリメントを 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 に答える