拜托,我是PostgreSQL / PLPGSQL的新手,我试图在Google上搜索SO,但找不到具体的解决方案。如果这个问题重复,我会道歉。
我想创建可以从table_main插入值的触发器函数,如果其他子表具有值,则自定义字符串(链接)将插入到与table_main中的数据一致的同一行中。
我有3个由应用程序自动生成的表,类似于:
- table_main
CREATE TABLE table_main
(
main_a character varying(80) NOT NULL,
main_b character varying(255),
main_c character varying(255),
main_d character varying(255),
CONSTRAINT main_a_pkey UNIQUE (main_a)
);
- table_sub1
CREATE TABLE table_sub1
(
sub_a character varying(80) NOT NULL,
sub_b character varying(255),
sub_c character varying(255),
sub_d character varying(255),
CONSTRAINT table_sub1_pkey UNIQUE (sub_a)
);
- table_sub2
CREATE TABLE table_sub2
(
sub2_a character varying(80) NOT NULL,
sub2_b character varying(255),
sub2_c character varying(255),
sub2_d character varying(255),
CONSTRAINT table_sub2_pkey UNIQUE (sub2_a)
);
另外,我有另一个表来存储要从table_main和自定义字符串(链接)复制的数据,如下所示:
- table_copy
CREATE TABLE table_copy
(
id serial NOT NULL,
copy_a character varying(80),
copy_b character varying(255),
copy_c character varying(255),
copy_d character varying(255),
copy_e character varying(255),
copy_f character varying(255),
copy_g character varying(255)
);
我的目的是:
CREATE OR REPLACE FUNCTION save_data()
RETURNS trigger
AS $$
BEGIN
INSERT INTO table_copy (
copy_a,
copy_b,
copy_c,
copy_d)
VALUES (
NEW."main_a",
NEW."main_b",
NEW."main_c",
NEW."main_d"
);
RETURN NEW;
END $$ LANGUAGE plpgsql;
ALTER FUNCTION save_data() OWNER TO postgres;
DROP TRIGGER trigger_save_data ON "table_main";
CREATE TRIGGER trigger_save_data BEFORE INSERT OR UPDATE
ON "table_main" FOR EACH ROW EXECUTE PROCEDURE save_data();
检查并结果:
smart=# INSERT INTO table_main (main_a, main_b, main_c, main_d) VALUES ('aaa', 'bbb', 'ccc', 'ddd');
INSERT 0 1
smart=# SELECT * FROM table_copy;
id | copy_a | copy_b | copy_c | copy_d | copy_e | copy_f | copy_g
----+--------+--------+--------+--------+--------+--------+--------
3 | aaa | bbb | ccc | ddd | | |
(1 row)
table_sub1
和table_sub2
,例如IF table_sub1.sub_c
或table_sub2.sub2_d
已插入值,自定义字符串(链接)将分别插入table_copy.copy_e
或table_copy.copy_f
。 我在下面尝试了一些解决方案,但都不满足我。
解决方案1:在table_main
,table_sub1
和table_sub2
的每个表格上设置每个触发器。结果:它在table_copy
==>中创建了三行不接受。
触发table_sub1:
CREATE OR REPLACE FUNCTION save_data_sub1()
RETURNS trigger
AS $$
BEGIN
INSERT INTO table_copy (copy_e) VALUES ('link_to_sub1_here');
RETURN NEW;
END $$ LANGUAGE plpgsql;
ALTER FUNCTION save_data_sub1() OWNER TO postgres;
CREATE TRIGGER trigger_save_data_sub1 BEFORE INSERT OR UPDATE
ON "table_sub1" FOR EACH ROW EXECUTE PROCEDURE save_data_sub1();
触发table_sub2:
CREATE OR REPLACE FUNCTION save_data_sub2()
RETURNS trigger
AS $$
BEGIN
INSERT INTO table_copy (copy_f) VALUES ('link_to_sub2_here');
RETURN NEW;
END $$ LANGUAGE plpgsql;
ALTER FUNCTION save_data_sub2() OWNER TO postgres;
CREATE TRIGGER trigger_save_data_sub1 BEFORE INSERT OR UPDATE
ON "table_sub2" FOR EACH ROW EXECUTE PROCEDURE save_data_sub2();
测试和结果(上面所有3个触发器):
smart=# INSERT INTO table_sub1 VALUES ('abc', 'bca', 'aaa', 'cba');
INSERT 0 1
smart=# INSERT INTO table_sub2 VALUES ('cvb', 'bvc', 'aaa', 'vcb');
INSERT 0 1
smart=# SELECT * FROM table_copy;
id | copy_a | copy_b | copy_c | copy_d | copy_e | copy_f | copy_g
----+--------+--------+--------+--------+-------------------+-------------------+--------
6 | aaa | bbb | ccc | ddd | | |
7 | | | | | link_to_sub1_here | |
8 | | | | | | link_to_sub2_here |
(3 rows)
smart=#
解决方案2:在上面的触发器功能IF EXISTS (SELECT........ WHERE) THEN INSERT INTO table_copy (copy_e) VALUES ('a link here') END IF;
中使用RETURN NEW;
下面的save_data()
,仍会产生新的行。 ==>也不被接受。
解决方案3:使用相同的IF EXISTS ...... THEN ....上面,==> ERROR。
我想要的是,数据被插入一行(6),而不是生成三行。这是我的期望:
id | copy_a | copy_b | copy_c | copy_d | copy_e | copy_f | copy_g
----+--------+--------+--------+--------+-------------------+-------------------+--------
6 | aaa | bbb | ccc | ddd | link_to_sub1_here | link_to_sub2_here |
如上所述,我是新手,无法找到让梦想成真的解决方案。拜托,这里的任何专家都可以给我一个亮点。
答案 0 :(得分:1)
谢谢大家的意见和建议。最后,我得到了以下解决方案的工作。
由于table_main.main_a
列是pkey
的{{1}},并且每个table_main
中都有一列(不是pkey
或fkey
)和table_sub1
与table_sub2
具有相同的值。此外,值{(1)}和table_main.main_a
首先,然后来table_sub1
(总是)。因此,我的触发功能完美无缺:
table_sub2
这是测试结果:
table_main
为需要的人提供解决方案。
干杯。