Перенос существующих данных таблицы в новую таблицу и изменение значения столбца, основанного на результате запроса, на другую таблицу - PullRequest
0 голосов
/ 18 февраля 2019

Итак, у меня есть 2 идентичные таблицы table1 и table2.Я хочу перенести данные из таблицы1 в таблицу2.

Я могу использовать этот запрос: -

insert into table2(table2_id, definition_string, description, active) 
select nextval('table2_id_seq'), definition_string, description, active from table1;

Но есть еще некоторые изменения, которые нужно сделать в столбце definition_string.

Столбец definition_string новой таблицыtable2 теперь должны иметь электронные письма, замененные именами пользователей, которые были в table1.

Например -

table1

Definition_string =

SEND open TO abc@gmail.com
SEND close TO abc@gmail.com
SEND open TO def@gmail.com ghi@gmail.com
SEND close TO def@gmail.com ghi@gmail.com
SEND open TO jkl@gmail.com
SEND close TO jkl@gmail.com

Вышеприведенная строка Definition должна быть заменена на -

table2

Definition_string =

SEND open TO usera
SEND close TO usera
SEND open TO userb userc
SEND close TO userb userc
SEND open TO userd
SEND close TO userd

Замена электронной почты на имя пользователя должна основываться на поиске в таблице user -

select username from user where email = 'abc@gmail.com';

РЕЗУЛЬТАТ:

username =

usera
userx
usery

Приведенный выше запрос может привести к одному или нескольким именам пользователей.Если запрос приводит к более чем одному имени пользователя, то мы будем рассматривать только первое имя для замены.

Хотя это и не правильно, но я попробовал это -

update 
  table2 
set 
  definition_string = case when definition_string = 'SEND open TO abc@gmail.com' then (
    select 
      username 
    from 
      user 
    where 
      email = 'abc@gmail.com'
  ) when definition_string = 'SEND close TO def@gmail.com ghi@gmail.com' then (
    select 
      username 
    from 
      user 
    where 
      email = 'def@gmail.com' || 'ghi@gmail.com'
  ) else definition_string -- don't change anything
  end;

Я думал написатьцикл for, который перебирает все строки table1.Но кажется, что это не эффективно зацикливаться?

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Обычно я бы уклонялся от процедурных циклов, но проблема не слишком хорошо подходит для чисто SQL-решения (по крайней мере, я этого не вижу), поэтому я думаю, что цикл - это путь.Вот пример того, как вы могли бы просто выполнить перевод из table1 в table2, с преобразованием на месте:

create or replace function update_table() returns void as $$
declare
  rw table2%rowtype;
  prefix text;
  emails text;
  emaili text;
  user_id text;
begin
  for rw in select * from table1
  loop
    prefix := substring (rw.definition_string from '(SEND \w+ TO) ');
    emails := substring (rw.definition_string from 'SEND \w+ TO (.+)');

    foreach emaili in array string_to_array (emails, ' ')
    loop
      select username
      into user_id
      from users where email = emaili;

      prefix := prefix || ' ' || user_id;
    end loop;

    insert into table2 values
    (nextval ('table2_id_seq'), prefix);
  end loop;
end;
$$
language plpgsql;

В качестве альтернативы вы можете использовать ту же концепцию и разделить перевод в функции:

create or replace function email_to_user(email_address text) returns text as $$
declare
  prefix text;
  emails text;
  emaili text;
  user_id text;
begin
  prefix := substring (email_address from '(SEND \w+ TO) ');
  emails := substring (email_address from 'SEND \w+ TO (.+)');

  foreach emaili in array string_to_array (emails, ' ')
  loop
    select username
    into user_id
    from users where email = emaili;

    prefix := prefix || ' ' || user_id;
  end loop;

  return prefix;
end;
$$
  language plpgsql;

Простое подтверждение концепции:

select id, definition_string, email_to_user(definition_string) from table1

Или:

insert into table2(table2_id, definition_string, description, active) 
select
  nextval('table2_id_seq'), email_to_user (definition_string), description, active 
from table1;

Или, если вы действительно хотите обновить существующие записи, независимо от того, как они туда попали:

update table2
set definition_string = email_to_user (definition_string)
where definition_string != email_to_user (definition_string)
0 голосов
/ 18 февраля 2019

Просто запустите update дважды (или столько раз, сколько пользователь может появиться в строке:

update table2 
    set replace(definition_string, u.email, u.username)
    from users u
    where definition_string like '%' + u.email + '%';

Это будет медленно, но ваша таблица небольшая.

Проблема в том, что только одно обновление электронной почты вступает в силу на каждой итерации для каждого определения, поэтому вам придется делать это несколько раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...