【问题标题】:PostgreSQL - Insert data into multiple tables simultaneouslyPostgreSQL - 同时将数据插入多个表
【发布时间】:2017-05-26 11:43:20
【问题描述】:

我在通过外键链接的表中遇到数据插入问题。我在某些地方读到有一个“with”命令可以在这些情况下提供帮助,但我不太明白它是如何使用的。

我想将四个用于记录的表放在一起,但是,所有数据都是在一个查询中一次插入的,并且它们与最后一个表相关联,以方便将来的咨询.下面是创建表的代码:

    CREATE TABLE participante
     (
       id serial NOT NULL,
       nome character varying(56) NOT NULL,
       CONSTRAINT participante_pkey PRIMARY KEY (id),
     );

    CREATE TABLE venda
    (
      id serial NOT NULL,
      inicio date NOT NULL,
      CONSTRAINT venda_pkey PRIMARY KEY (id)
    );

    CREATE TABLE item
    (
      id serial NOT NULL,
      nome character varying(256) NOT NULL,
      CONSTRAINT item_pkey PRIMARY KEY (id)
    );


    CREATE TABLE lances_vendas
    (
      id serial NOT NULL,
      venda_id integer NOT NULL,
      item_id integer NOT NULL,
      participante_id integer NOT NULL,
      valor numeric NOT NULL,
      CONSTRAINT lance_vendas_pkey PRIMARY KEY (id),
      CONSTRAINT lances_vendas_venda_id_fkey FOREIGN KEY (venda_id)
        REFERENCES venda (id),
      CONSTRAINT lances_vendas_item_id_fkey FOREIGN KEY (item_id)
        REFERENCES item (id),
      CONSTRAINT lances_vendas_participante_id_fkey FOREIGN KEY (participante_id)
        REFERENCES participante (id)
    );

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:
    WITH par_key AS
            (INSERT INTO participante (nome) VALUES ('Laurenz') RETURNING id),
         ven_key AS
            (INSERT INTO venda (inicio) VALUES (current_date) RETURNING id),
         item_key AS
            (INSERT INTO item (nome) VALUES ('thing') RETURNING id)
    INSERT INTO lances_vendas (venda_id, item_id, participante_id, valor)
       SELECT ven_key.id, item_key.id, par_key.id, numeric '3.1415'
       FROM par_key, ven_key, item_key;
    

    【讨论】:

      【解决方案2】:

      我知道您请求了单个查询,但您可能仍想考虑使用事务:

      BEGIN;
      INSERT INTO participante (nome) VALUES ('Laurenz');
      INSERT INTO venda (inicio) VALUES (current_date);
      INSERT INTO item (nome) VALUES ('thing');
      INSERT INTO lances_vendas (venda_id, item_id, participante_id, valer)
      VALUES (currval('venda_id_seq'), currval('item_id_seq'), currval('participante_id_seq'), 3.1415);
      COMMIT;
      

      事务确保参与者、venda 和 item 中的任何新行保持 currval('X') 的值不变。

      【讨论】:

      • 序列不是事务性的,所以在这里依赖事务是不安全的。
      • 如何不安全? nextval() 的副作用在事务之外立即可见,这就是为什么它(应该是,因为你似乎并不相信)使用它的结果是安全的。
      • 下面的讨论可能会让你更清楚:p stackoverflow.com/questions/2095917/…
      • 这就是我不推荐这个答案的原因,因为你不能保证currval() 会给你正确的价值。也许不安全不是正确的词。
      • 这里是:“因为这是返回一个会话本地值,所以它给出了一个可预测的答案,即自当前会话以来其他会话是否已执行 nextval。” (postgresql.org/docs/current/static/functions-sequence.html)
      【解决方案3】:

      您可以创建一个函数来完成这项工作。看看这个例子:

      CREATE OR REPLACE FUNCTION import_test(p_title character varying, p_last_name character varying, p_first_name character varying, p_house_num integer, p_street character varying, p_zip_code character varying, p_city character varying, p_country character varying)
      RETURNS integer
      LANGUAGE plpgsql
      AS
      $body$
      DECLARE
      
          address_id uuid;
          parent_id uuid;
          ts timestamp;
      
      BEGIN
      
          address_id := uuid_generate_v4();
          parent_id := uuid_generate_v4();
          ts := current_timestamp;
      
          insert into address (id, number, street, zip_code, city, country, date_created) values (address_id, p_house_num, p_street, p_zip_code, p_city, p_country, ts);
          insert into person (id, title, last_name, first_name, home_address, date_created) values (parent_id, p_title, p_last_name, p_first_name, address_id, ts);
      
      RETURN 0;
      END;
      $body$
      VOLATILE
      COST 100;
      
      COMMIT;
      

      注意为address(第一次插入)生成的UUID如何在person-record(第二次插入)中使用

      用法:

      SELECT import_test('MR', 'MUSTERMANN', 'Peter', 'john2@doe.com', 54, 'rue du Soleil', '1234', 'Arlon', 'be');
      SELECT import_test('MS', 'MUSTERMANN', 'Peter 2', 'peter2@yahoo.com', 55, 'rue de la Lune', '56789', 'Amnéville', 'fr');
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-13
        • 1970-01-01
        • 1970-01-01
        • 2016-02-15
        相关资源
        最近更新 更多