Home > Enterprise >  Dynamic SQL with EXECUTE and nested format()
Dynamic SQL with EXECUTE and nested format()

Time:10-11

I tried doing this with just a normal CTE (no EXECUTE ... FORMAT) and I was able to do it. I basically have a table that has some 5 columns and some data in each column that I wanted to concatenate and such to manifest/generate some data in a new column.

I can do something like this and it works:

WITH cte AS (SELECT *, case 
                        when var1 = '' then ''
                        when var2 = '' then ''
                        else '' end, 'adding_dummy_text_column'
             FROM some_other_table sot
             WHERE sot.type = 'java')

             INSERT INTO my_new_table 
                    SELECT *, 'This is the new column I want to make with some data from my CTE' || c.type
                    FROM cte c;

So this works as I said. I'll end up getting a new table that has an extra column which a hardcoded, concatenated string This is the new column I want to make with some data from my CTE Java

Of course, whatever is in the c.type column for the corresponding row in the CTE as it loads the SELECT is what gets concatenated to that string.

The problem is, as soon as I start using the EXECUTE...FORMAT to make it cleaner and have more power to concatenate/combined different data pieces from my different columns (I have data kind of scattered around in bad formats and I'm populating a fresh new table), it's as if the FORMAT arguments or the variables cannot detect the CTE table.

This is how I'm doing it

EXECUTE FORMAT ('WITH cte AS (SELECT *, case 
                        when var1 = %L then %L
                        when var2 = '' '' then '' ''
                        else '' '' end, ''adding_dummy_text_column''
             FROM some_other_table sot
             WHERE sot.type = ''java'')

             INSERT INTO my_new_table 
                    SELECT *, ''This is the new column I want to make with some data from my CTE %I''
                    FROM cte c', 'word1', 'word2', c.type
             );

OK, so I know I used the empty string '' '' in this example and the %L but i just wanted to show I had no issues with any of that. Its when I try to reference my CTE columns, so you can see I'm trying to do the same concatenation but by leveraging the EXECUTE...FORMAT and using the %I identifiers. So, the first 2 args are just fine, its the c.type that just no matter what column I try, doesn't work. Also, I removed the c alias and didn't get any better luck. It's 100% anytime I reference the columns on the CTE though, as I have removed all that code and it runs just fine without that.

But yeah, is there any work around? I really want to transform some data and now have to do the || for concatenation.

CodePudding user response:

This should do it:

EXECUTE format($f$WITH cte AS (SELECT *, CASE
                        WHEN var1 = %L THEN %L
                        WHEN var2 = ' ' THEN ' '
                        ELSE ' ' END, 'adding_dummy_text_column'
             FROM some_other_table sot
             WHERE sot.type = 'java')

             INSERT INTO my_new_table
                    SELECT *, format('This is the new column I want to make with some data from my CTE %%I', c.type)
                    FROM cte c$f$
           , 'word1', 'word2');

Generates and executes this SQL statement:

WITH cte AS (SELECT *, CASE
                        WHEN var1 = 'word1' THEN 'word2'
                        WHEN var2 = ' ' THEN ' '
                        ELSE ' ' END, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')

INSERT INTO my_new_table
SELECT *, format('This is the new column I want to make with some data from my CTE %I', c.type)
FROM cte c

Which could be simplified and improved to this equivalent:

INSERT INTO my_new_table(co1, col2, ...)  -- provide target column list!
SELECT *
     , CASE WHEN var1 = 'word1' THEN 'word2'
            WHEN var2 = ' ' THEN ' '
            ELSE ' ' END
     , 'adding_dummy_text_column'
     , format('This is the new column I want to make with some data from my CTE %I', sot.type)
FROM   some_other_table sot
WHERE  sot.type = 'java'

About the missing target column list:

  • Related