Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would you enforce DRY (Don't Repeat Yourself) in a SQL script?

Tags:

sql

oracle

dry

I'm changing a database (oracle) with a script containing a few updates looking like:

UPDATE customer
SET status = REPLACE(status,   'X_Y',   'xy')
WHERE status LIKE '%X_Y%'
 AND category_id IN
  (SELECT id
   FROM category
   WHERE code = 'ABC');

UPDATE customer
SET status = REPLACE(status,   'X_Z',   'xz')
WHERE status LIKE '%X_Z%'
 AND category_id IN
  (SELECT id
   FROM category
   WHERE code = 'ABC');

-- More updates looking the same...

In this case, how would you enforce DRY (Don't Repeat Yourself)?

I'd particularly interested in solving the two following recurring problems:

  • Define a function, available from this script only, to extract the subquery SELECT id FROM category WHERE code = 'ABC'

  • Create a set of replace rules (that could look like {"X_Y": "yx", "X_Z": "xz", ...} in a popular programming language) and then iterate a single update query on it.

Thanks!

like image 434
Sébastien RoccaSerra Avatar asked Dec 23 '22 12:12

Sébastien RoccaSerra


2 Answers

I would reduce it to a single query:

UPDATE customer
SET status = REPLACE(REPLACE(status, 'X_Y', 'xy'), 'X_Z', 'xz')
WHERE status REGEXP_LIKE 'X_[YZ]'
 AND category_id IN
  (SELECT id
   FROM category
   WHERE code = 'ABC');
like image 183
soulmerge Avatar answered Mar 09 '23 00:03

soulmerge


First of all, remember that scripting is not the same thing as programming, and you don't have to adhere to DRY principles. Scripts like this one are usually one-offs, not a program to be maintained over a long time.

But you could use PL/SQL to do this:

declare
   type str_tab is table of varchar2(30) index by binary_integer;
   from_tab str_tab;
   to_tab str_tab;
begin
   from_tab(1) := 'X_Y';
   from_tab(2) := 'X_Z';
   to_tab(1) := 'xy';
   to_tab(2) := 'xz';

   for i in 1..from_tab.count loop

      UPDATE customer
      SET status = REPLACE(status,   from_tab(i),   to_tab(i))
      WHERE status LIKE '%' || from_tab(i) || '%'
       AND category_id IN
        (SELECT id
         FROM category
         WHERE code = 'ABC');

   end loop;
end;
like image 24
Tony Andrews Avatar answered Mar 08 '23 23:03

Tony Andrews