6

I'm trying create a update for a new structure of tables from a old table, but not using functions. I'm trying create a script to it. The old table is like this:

Old table (OldTable)

name col_a col_b col_c
ABC 0 NULL 1
DEF 1 1 1
GHI NULL 1 0

And, the new tables:

Users:

ID NAME
1 ABC
2 DEF
3 GHI

Rules:

ID RULE_NAME
1 col_a
2 col_b
3 col_c
4 col_d

UserRule

ID_USER ID_RULE

So, I'm needing populate the table UserRules with the result from a select on TableMix where the user name is equals to the user name on table User and the value for column <col_name> in TableMix is equals 1. (select <col_name> from OldTable where OldTable.name = Users.name). Well, I'm trying this:

DO $$
 DECLARE rules CURSOR FOR SELECT column_name FROM information_schema.columns
 WHERE table_schema = 'public' AND table_name = 'OldTable' 
 AND data_type = 'numeric' AND column_name NOT IN ('foo','bar'); 
 -- "foo" and "bar" are another numeric cols, but not define rules.
 DECLARE users CURSOR FOR SELECT name FROM public.Users;
 BEGIN
 FOR ruleName IN rules LOOP
 FOR userName IN users LOOP
 EXECUTE format('SELECT COALESCE(%I,col,1ドル) FROM public.OldTable 
 WHERE name = ''2ドル''', ruleName, username); 
 -- insert on... populate the table Rules after get the id of the rule in table Rules if the result of select in OldTable equals 1 (or true if has a "where ... = 1")
 END LOOP;
 END LOOP;
END $$

After this, I don't have progress.

UPDATE

This way I can get the real value:

DO $$
DECLARE 
 rules CURSOR FOR SELECT column_name FROM information_schema.columns
 WHERE table_schema = 'public' AND table_name = 'oldtable' AND data_type = 'numeric'
 AND column_name NOT IN ('foo','bar');
 names CURSOR FOR SELECT username FROM public.users;
 res integer;
BEGIN
 FOR rulename IN rules LOOP 
 EXECUTE format('SELECT %s FROM oldtable WHERE nome = %L', rulename, 'USER NAME') INTO res;
 -- IF res > 0 THEN
 RAISE NOTICE '%', res;
 --END IF;
 END LOOP;
END $$

Result the real integer value.

But if I use a loop for usernames, it's doesn't work.

DO $$
DECLARE 
 rules CURSOR FOR SELECT column_name FROM information_schema.columns
 WHERE table_schema = 'public' AND table_name = 'oldtable' AND data_type = 'numeric'
 AND column_name NOT IN ('foo','bar');
 names CURSOR FOR SELECT username FROM public.users;
 res integer;
BEGIN
 FOR name IN names LOOP
 FOR rulename IN rules LOOP 
 EXECUTE format('SELECT %s FROM oldtable WHERE nome = %L', rulename, name) INTO res;
 -- IF res > 0 THEN
 RAISE NOTICE '%', res;
 --END IF;
 END LOOP;
 END LOOP;
END $$

So, the result is always . Where am I going wrong?

asked Sep 30, 2014 at 14:00
3
  • Copied and pasted to stackoverflow.com/q/26122833/398670 Commented Sep 30, 2014 at 14:06
  • PS: The first error occurs because the column name is printed with parentheses. "SELECT (<col_name>) from ...." Commented Sep 30, 2014 at 14:07
  • Yes, because there are people who are not in both groups. Commented Sep 30, 2014 at 14:11

1 Answer 1

4

I think you might be looking for the USING clause:

EXECUTE format('SELECT COALESCE(%I,col,1ドル) FROM public.TableMix 
 WHERE name = 2ドル', ruleName)
 USING (username, whateverTheSecondParameterIs); 

You use 1ドル, 2ドル, etc for placement-parameters, passed by USING. You use %I for itentifiers expanded by format.

Update: If you want to coalesce the column name ruleName if it's null, perhaps you want something more like:

EXECUTE format('SELECT %I FROM public.TableMix 
 WHERE name = 1ドル', coalesce(ruleName, 'col'))
 USING (username); 

??

You need to think about order of evaluation. What's part of the generated SQL, and what's evaluated in order to create that SQL?

answered Sep 30, 2014 at 14:28
6
  • Thanks! But the initial problem persist: column name is printed with parentheses. "SELECT COALESCE(<col_name>) from ...." Commented Sep 30, 2014 at 14:49
  • @GustavoAdolfo Hang on, are you trying to coalesce the column name, i.e. "if the column name is null, use the column name col instead"? If so, you have to do that outside the dynamic SQL string, in the format argument list. Commented Sep 30, 2014 at 14:57
  • pfff!! Yes man! Just the obvious... :) Sorry guys, after a while I could not see the obvious... And, I do not even know pgsql (yet). :( Now... how get the result and progress this work? I no have idea how to do this without giving a lot of laps. Commented Sep 30, 2014 at 15:13
  • @GustavoAdolfo EXECUTE ... INTO. See the pl/pgsql manual, "dynamic SQL" section. Commented Sep 30, 2014 at 15:28
  • @GustavoAdolfo Probably best accept this answer if it's helped then, and follow up with a new question if you're stuck on something else later. Commented Oct 1, 2014 at 1:46

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.