3

現在、親テーブルがあります:

CREATE TABLE members (
    member_id SERIAL NOT NULL, UNIQUE, PRIMARY KEY
    first_name varchar(20)
    last_name varchar(20)
    address address (composite type)
    contact_numbers varchar(11)[3]
    date_joined date
    type varchar(5)
);

および 2 つの関連するテーブル:

CREATE TABLE basic_member (
    activities varchar[3])
    INHERITS (members)
);

CREATE TABLE full_member ( 
    activities varchar[])
    INHERITS (members)
);

タイプがテーブルに入力されている場合、またはタイプがテーブルに入力されている場合はfull、詳細が入力されます。私が欲しいのは、更新を実行してタイプを変更するか、タプルが対応するテーブルに入るということです。full_memberbasicbasic_memberbasicfull

次のようなルールでこれを行うことができるかどうか疑問に思っていました:

 CREATE RULE tuple_swap_full
 AS ON UPDATE TO full_member
 WHERE new.type = 'basic'
 INSERT INTO basic_member VALUES (old.member_id, old.first_name, old.last_name,
 old.address, old.contact_numbers, old.date_joined, new.type, old.activities);

...次に、full_member からレコードを削除します

私のルールが近いのか、それとももっと良い方法があるのか​​ 疑問に思っています。

4

1 に答える 1

1
  • あなたは必要ありません

    member_id SERIAL NOT NULL, UNIQUE, PRIMARY KEY
    

    A は自動的に次のことをPRIMARY KEY意味します。UNIQUE NOT NULL

    member_id SERIAL PRIMARY KEY
    
  • ハードコーディングされた最大長varchar(20). text最大長を強制する必要がある場合は、チェック制約を使用して追加するだけです。着替えやすくなりました。

  • の構文INHERITSが壊れています。キーワードは、列を囲む括弧の外に出ます。

    CREATE TABLE full_member ( 
        activities text[]
    ) INHERITS (members);
    
  • テーブル名に一貫性がありません ( members<-> member)。テストケースのどこでも単数形を使用しています。

  • 最後に、タスクに RULE を使用しません。トリガーAFTER UPDATEが望ましいようです。

次のことを考慮してください

テストケース:

テーブル:

CREATE SCHEMA x;  -- I put everything in a test schema named "x".

-- DROP TABLE x.members CASCADE;
CREATE TABLE x.member (
     member_id SERIAL PRIMARY KEY
    ,first_name text
    -- more columns ...
    ,type text);

CREATE TABLE x.basic_member (
    activities text[3]
) INHERITS (x.member);

CREATE TABLE x.full_member ( 
    activities text[]
) INHERITS (x.member);

トリガー機能:

データ変更 CTE ( WITH x AS ( DELETE ..) は、この目的に最適なツールです。PostgreSQL 9.1 以降が必要です。
古いバージョンの場合は、最初INSERTDELETE.

CREATE OR REPLACE FUNCTION x.trg_move_member()
  RETURNS trigger AS
$BODY$
BEGIN

CASE NEW.type
WHEN 'basic' THEN
    WITH x AS (
        DELETE FROM x.member
        WHERE member_id = NEW.member_id
        RETURNING *
        )
    INSERT INTO x.basic_member (member_id, first_name, type) -- more columns
    SELECT member_id, first_name, type -- more columns
    FROM   x;

WHEN 'full' THEN
    WITH x AS (
        DELETE FROM x.member 
        WHERE member_id = NEW.member_id
        RETURNING *
        )
    INSERT INTO x.full_member (member_id, first_name, type) -- more columns
    SELECT member_id, first_name, type -- more columns
    FROM   x;
END CASE;

RETURN NULL;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

引き金:

AFTERこれはトリガーであり、WHEN条件 があることに注意してください。WHEN条件には PostgreSQL 9.0 以降が必要です。以前のバージョンでは、そのままにしておくことができ、トリガー自体の CASE ステートメントがそれを処理します。

CREATE TRIGGER up_aft
  AFTER UPDATE
  ON x.member
  FOR EACH ROW
  WHEN (NEW.type IN ('basic ','full')) -- OLD.type cannot be IN ('basic ','full')
  EXECUTE PROCEDURE x.trg_move_member();

テスト:

INSERT INTO x.member (first_name, type) VALUES ('peter', NULL);

UPDATE x.member SET type = 'full' WHERE first_name = 'peter';
SELECT * FROM ONLY x.member;
SELECT * FROM x.basic_member;
SELECT * FROM x.full_member;
于 2012-04-22T14:42:08.620 に答える