我目前有一个父表:
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)
);
和两个相关的表格:
CREATE TABLE basic_member (
activities varchar[3])
INHERITS (members)
);
CREATE TABLE full_member (
activities varchar[])
INHERITS (members)
);
如果类型为full
,则会在full_member
表中输入详细信息,或者在basic
表中输入basic_member
。我想要的是,如果我运行更新并将类型更改为basic
或full
,则元组将进入相应的表。
我想知道我是否可以通过以下规则来执行此操作:
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中删除记录
只是想知道我的规则是否在附近,或者是否有更好的方法。
答案 0 :(得分:1)
您不需要
member_id SERIAL NOT NULL, UNIQUE, PRIMARY KEY
PRIMARY KEY
自动隐含UNIQUE NOT NULL
:
member_id SERIAL PRIMARY KEY
我不会使用varchar(20)
的硬编码最大长度。如果你真的必须强制执行最大长度,只需使用text
并添加一个检查约束。更容易改变。
INHERITS
的语法被破坏了。关键词出现在列周围的parens之外。
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);
Data-modifying CTEs(WITH x AS ( DELETE ..
)是此目的的最佳工具。需要PostgreSQL 9.1或更高版本
对于旧版本,首先是INSERT
,然后是DELETE
。
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;