Postgresql

使用變數來確定 Postgres 中選擇中的列名

  • July 15, 2021

我正在嘗試從舊表中為新的表結構創建更新,但不使用函式。我正在嘗試為它創建一個腳本。舊表是這樣的:

舊表 ( OldTable)

而且,新表:

Users:

Rules:

UserRule

因此,我需要使用 TableMix 上的選擇結果填充表 UserRules,其中使用者名等於表 User 上的使用者名,並且 TableMix 中列 <col_name> 的值等於 1。(選擇 <col_name>來自 OldTable,其中 OldTable.name = Users.name)。好吧,我正在嘗試這個:

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 $$

在這之後,我沒有進展。

更新

這樣我可以獲得真正的價值:

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 &gt; 0 THEN
      RAISE NOTICE '%', res;
   --END IF;
   END LOOP;
END $$

結果是真正的整數值。

但是,如果我對使用者名使用循環,它就不起作用。

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 &gt; 0 THEN
          RAISE NOTICE '%', res;
       --END IF;
       END LOOP;
   END LOOP;
END $$

所以,結果總是 。我哪裡錯了?

我想您可能正在尋找以下USING條款:

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

您使用$1,$2等作為放置參數,由USING. 您%I用於由format.

更新:如果你想合併列名ruleName,如果它是空的,也許你想要更像:

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

??

您需要考慮評估順序。生成的 SQL 的組成部分是什麼,以及為了創建該 SQL 而評估了什麼?

引用自:https://dba.stackexchange.com/questions/78048