PostgreSQL:条件INSERT INTO来自差异表的多个列

时间:2015-11-25 15:40:55

标签: postgresql plpgsql

拜托,我是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)
);

我的目的是:

  1. 使用下面的触发器函数将记录插入table_main时,将数据从table_main复制到table_copy,并且工作正常:
  2. 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)
    
    1. 我的第二个(也是更重要的)目的是将自定义字符串插入table_copy中的最后一列(当然在同一行中),条件基于table_sub1table_sub2,例如IF table_sub1.sub_ctable_sub2.sub2_d已插入值,自定义字符串(链接)将分别插入table_copy.copy_etable_copy.copy_f
    2. 我在下面尝试了一些解决方案,但都不满足我。

      解决方案1:在table_maintable_sub1table_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 |
      

      如上所述,我是新手,无法找到让梦想成真的解决方案。拜托,这里的任何专家都可以给我一个亮点。

1 个答案:

答案 0 :(得分:1)

谢谢大家的意见和建议。最后,我得到了以下解决方案的工作。

由于table_main.main_a列是pkey的{​​{1}},并且每个table_main中都有一列(不是pkeyfkey)和table_sub1table_sub2具有相同的值。此外,值{(1)}和table_main.main_a 首先,然后来table_sub1(总是)。因此,我的触发功能完美无缺:

table_sub2

这是测试结果:

table_main

为需要的人提供解决方案。

干杯。