Sql 将现有表数据迁移到新表,并根据查询结果将列值更改为其他表

Sql 将现有表数据迁移到新表,并根据查询结果将列值更改为其他表,sql,postgresql,for-loop,sql-update,Sql,Postgresql,For Loop,Sql Update,我有两张完全相同的表,表1和表2。我想将数据从表1迁移到表2 我可以使用以下查询:- insert into table2(table2_id, definition_string, description, active) select nextval('table2_id_seq'), definition_string, description, active from table1; 但是在列定义\u string中还有一些更改要做 新表table2的definition\u str

我有两张完全相同的表,表1和表2。我想将数据从表1迁移到表2

我可以使用以下查询:-

insert into table2(table2_id, definition_string, description, active) 
select nextval('table2_id_seq'), definition_string, description, active from table1;
但是在列
定义\u string
中还有一些更改要做

新表
table2
definition\u string
列现在应该将电子邮件替换为
table1
中的用户名

例如-

表1

定义字符串=

上述定义_字符串应替换为-

表2

定义字符串=

将电子邮件替换为用户名应基于在表
user
-

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

用户名=

上述查询可能会产生一个或多个用户名。如果查询导致一个以上用户名,那么我们只考虑替换的第一个。 虽然不正确,但我试过这个-

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循环,循环遍历
表1
的所有行。但是循环似乎效率不高?

只需运行此
更新两次(或用户在字符串中出现的次数:

update table2 
    set replace(definition_string, u.email, u.username)
    from users u
    where definition_string like '%' + u.email + '%';
这会很慢,但是你的桌子太小了


问题是,对于每个定义,每次迭代只有一次电子邮件更新生效,因此您必须多次执行此操作。

我通常会避开过程循环,但问题本身并不适合纯SQL解决方案(至少我看不到),因此我认为循环是可行的。下面是一个示例,说明如何在转换到位的情况下将表1转换为表2:

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
或:

或者,如果您真的想更新现有记录,不管它们是如何到达的:

update table2
set definition_string = email_to_user (definition_string)
where definition_string != email_to_user (definition_string)

表中有多少条记录?我看到了一种方法,但如果有数千万行,这将不是一个好方法。@Hambone-我没有数千万行。我只有2000行。所以请让我知道这种方法。它不起作用。当我用实际值硬编码
u.email
u.username
时,它就不起作用了工作。它现在正在进行一些更改。下面是最后一个查询-
updatetable2 set definition\u string=replace(definition\u string,u.email,u.username)从用户u那里定义字符串,如“%”| | u.email | |“%”
但是一封电子邮件更新一次,两封电子邮件更新两次是问题所在。如果我们使用一些正则表达式来查找每条记录的电子邮件,然后循环使用它来进行更新,这将是一件好事。@MyGod…多个
update
语句。价格昂贵,但可能是最快的我不知道如何处理数据大小。但是,我如何知道第1行需要多少update语句,或者第2行需要多少update语句基于给定的查询,以便我相应地放入循环?感谢您的回复。但是,查询
select id,definition\u string,email\u to\u user(definition\u string)从表1中
email\u to_user
函数提供空值。我认为它没有从
emails:=子字符串(email\u地址从'SEND\w+发送到(+.))
。这将获取整个
定义\u字符串
列值。是的,如果它不符合正则表达式模式,它将返回null。您能列举字符串前缀的所有可能性(在电子邮件之前)吗?好的。你给了我一个提示,问题出在正则表达式中。我在
SEND\w+TO
之前发现了一些单词。所以我在正则表达式中使用了
*SEND\w+TO
,它起了作用。在某些情况下,如果我们产生了多个用户名…那么是否可以将
email\u TO\u user
函数更改为映射到任何用户?例如。-if
abc@gmail.com
结果是
usera
userb
并且我希望
userb
用于此电子邮件,那么我们可以将其映射到该函数本身吗?我使用循环中的
if-else
条件获得它。例如-
if-emaili'abc@gmail.com'然后前缀:=前缀| |''| |'用户B';否则前缀:=前缀| |''| |用户id;
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)