Simple way to read an email to username mapping an

2019-07-26 13:48发布

问题:

I am migrating a data from table1 to table2 and replacing email with username for definition_string column in the table2 table.

Tables are like:-

CREATE TABLE table1
(
    table1_id bigint NOT NULL DEFAULT nextval('table1_id_seq'::regclass),
    definition_string text COLLATE pg_catalog."default",
    CONSTRAINT table1_pkey PRIMARY KEY (table1_id)
)

CREATE TABLE table2
(
    table2_id bigint NOT NULL DEFAULT nextval('table2_id_seq'::regclass),
    definition_string text COLLATE pg_catalog."default",
    CONSTRAINT table2_pkey PRIMARY KEY (table2_id)
)

Value in definition_string column is like following:-

definition_string = 'SEND open TO abc@gmail.com'
definition_string = 'SEND open TO def@gmail.com ghi@gmail.com'

One email can have multiple usernames from users table.

For ex:

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

OUTPUT:

username: testabc, blablabla

If it contain multiple usernames then I want a selected username only to be the part of new table.

For that I have a list to map:

'abc@gmail.com','testabc'
'def@gmail.com','testdef'

The data is too large and I don't want multiple IF ELSE conditions as you see in the below function to map email with username-

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;
      IF emaili = 'abc@gmail.com' THEN
            prefix := prefix || ' ' || 'testabc';
      ELSE IF emaili = 'def@gmail.com' THEN
            prefix := prefix || ' ' || 'testdef';
      ELSE
            prefix := prefix || ' ' || user_id;
      END IF;
    end loop;

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

Is there a simple way to read an email to username mapping and if present then simply use the value instead of multiple IF ELSE conditions ?

回答1:

The only good way I found is this one-

create or replace function update_table() returns void as $$
declare
  rw table2%rowtype;
  js jsonb := '{"abc@gmail.com": "testabc", "def@gmail.com": "testdef"}';
  i record;
  prefix text;
  emails text;
  emaili text;
  user_id text;
  userByJson 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
      found = false;
      select username
      into user_id
      from users where email = emaili;
      userByJson = (SELECT elem->> emaili FROM jsonb(js) elem);
      IF userByJson is not null THEN
        prefix := prefix || ' ' || userByJson;
        ELSE
        prefix := prefix || ' ' || user_id;
      END IF;   
    end loop;

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