skip to Main Content

I have database that looks like this

CREATE TABLE code (
  id SERIAL, 
  name VARCHAR(255) NOT NULL 
);

INSERT INTO code (name) VALUES ('random_value1_random');
INSERT INTO code (name) VALUES ('random_value123_random');

CREATE TABLE value (
  id SERIAL, 
  name VARCHAR(255) NOT NULL 
);

INSERT INTO value (name) VALUES ('value1');
INSERT INTO value (name) VALUES ('value123');

UPDATE code SET name = REPLACE(name, SELECT name from value , '');

I want to update my table code to remove a portion of a code and that code is coming from another table. My goal is to update all values of code and remove the portion of the string that matches another value. My end goal is to make all code.name in the example look like: random_random removing the value from the value table.

When tried using to replace with a query I get an error:

[21000] ERROR: more than one row returned by a subquery used as an expression

What is a cleaner better way to do this?

2

Answers


  1. This T-SQL (I don’t have Postgres) and isn’t elegant, but it works..

    ;with l as (
        -- Match the longest value first
        select c.id c_id, v.id v_id, ROW_NUMBER () over (partition by c.id order by len(v.name) desc) r
        from code c
        join value v on charindex (v.name, c.name) > 0)
    , l1 as (
        -- Select the longest value first
        select c_id, v_id from l where r = 1
        )
    update c set name = REPLACE(c.name, v.name, '')
    from l1
    join code c on c.id = l1.c_id
    join value v on v.id = l1.v_id
    
    Login or Signup to reply.
  2. You can use REGEXP_REPLACE to replace multiple substrings in a string. You can use STRING_AGG to get the search pattern from the single search values.

    UPDATE code SET name = 
      REGEXP_REPLACE( name,
                      (SELECT '(' || STRING_AGG(name, '|') || ')' from value),
                      ''
                    );
    

    This will leave you with ‘random___random’, not ‘random_random’. If you only want to look for substrings separated with the underline character, then use

    UPDATE code SET name = 
      TRIM('_' FROM 
            REGEXP_REPLACE(name, 
                           (SELECT '(' || STRING_AGG('_?' || name || '_?', '|') || ')' from value),
                           '_'
                          )
          );
    

    Demo: https://dbfiddle.uk/RrOel8Ns

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search