Вставьте значение в сериализованное поле таблицы 1, а затем вставьте это сериализованное значение в таблицу 2, если существуют уникальные ограничения

#sql #postgresql

Вопрос:

Это мои столы:

 CREATE TABLE networks (  network_id SERIAL UNIQUE PRIMARY KEY,  network_name TEXT NOT NULL UNIQUE );  CREATE TABLE addresses (  address_id SERIAL UNIQUE NOT NULL,  network_id integer REFERENCES networks (network_id),  address TEXT NOT NULL UNIQUE,  PRIMARY KEY (address_id, network_id) );  

Я пытаюсь вставить значение в networks , а затем вставить автоматически сгенерированное network_id в другую таблицу.

Этот запрос работает для значений, которые не существуют, networks и выполняет то, что я ищу:

 WITH par_key AS (  INSERT INTO networks (network_name) VALUES ('ethereum')  RETURNING network_id ) INSERT INTO addresses (network_id, address) VALUES (  (select par_key.network_id from par_key),  'address1' )  

Однако этот запрос приводит к повторяющейся ошибке:

 WITH par_key AS (  INSERT INTO networks (network_name) VALUES ('ethereum')  RETURNING network_id ) INSERT INTO addresses (network_id, address) VALUES (  (select par_key.network_id from par_key),  'address2' )  
 ERROR: duplicate key value violates unique constraint "networks_token_name_key" DETAIL: Key (network_name)=(ethereum) already exists.  

Я бы хотел, чтобы запрос выполнялся addresses с network_id помощью, если значение уже существует networks .

Изменить: пришлось переименовать token_name в приведенной выше таблице в network_name .

Ответ №1:

Вы можете сделать это с помощью двух запросов и повторять одну и ту же сеть с разными адресами столько раз, сколько потребуется.

 insert into networks (token_name) VALUES ('ethereum') on conflict do nothing;   insert into addresses (network_id, address) values  (  (select network_id from networks where token_name = 'ethereum'),  'address2' );  

Если вам нужен один запрос, используйте эту функцию SQL:

 create or replace function the_function(arg_token text, arg_address text)  returns bigint language sql as $  insert into networks (token_name) VALUES (arg_token) on conflict do nothing;  insert into addresses (network_id, address)  values  (  (select network_id from networks where token_name = arg_token),   arg_address  ) returning network_id; $; -- Use as select the_function('ethereum', 'address1'); select the_function('ethereum', 'address2');  

Комментарии:

1. Очень признателен, спасибо!

2. Принять ответ?