Tabelle als Variable abfragen

Fragen und Probleme zu PL/pgSQL.
Nexx
Neuer Benutzer
Beiträge: 8
Registriert: Mo 9. Dez 2019, 12:03

Re: Tabelle als Variable abfragen

Beitrag von Nexx »

Vielen Dank für die Hilfe. Ich muss jetzt los. Schaue mir das morgen früh weiter an. Vielleicht bekomme ich es dann hin.

castorp
Erfahrener Benutzer
Beiträge: 1202
Registriert: Sa 27. Jun 2009, 22:24
Wohnort: Bayern

Re: Tabelle als Variable abfragen

Beitrag von castorp »

Dynamisches SQL macht man in Postgres am besten mit format() dann bleibt das eigentlich SQL noch lesbar und mit den passenden Platzhaltern muss man sich auch nicht um das Quoting kümmern. Parameter übergibt man auch als solche, die sollte man nicht in den SQL String "kopieren" (das war aber auch schon unter Oracle eine schlechte Idee).

Basierend auf Deinem Code, würde ich mal vermuten, dass Du sowas hier suchst:

Code: Alles auswählen

DECLARE
  tmpsql character varying(2000);
  tmpcols_tabold character varying(1000);
  tmpcols_tabnew character varying(1000);
  icount integer;
  vtab_hist character varying(30);
  itimespan integer;
  ielapsedtime integer;
  
BEGIN
  select count(*) 
     into icount 
  from awb.hist_config where 
  table_name = upper(tab_name);

  IF icount <> 1 THEN
    RAISE EXCEPTION '!! Kein Hist-Tabellenname in der Taballe HIST_CONFIG angegeben !!';
    return;
  ELSE
    select table_hist, delete_time 
        into vtab_hist, itimespan 
    from awb.hist_config 
    where table_name = upper(tab_name);
  END IF;

  vtab_hist := lower(vtab_hist);

  select count(*) 
    into icount 
  from information_schema.tables 
  where table_name = vtab_hist
    and table_schema = 'awb';

  IF (hist_cause <> 'D') THEN
  
    execute format('select count(*) from %I where %I = $1', vtab_hist, tab_id_name) 
      into icount 
     using tab_id_value; --<< übergibt den Wert für Parameter $1
    
    IF (icount > 0) THEN
      execute format('select current_date - max(hist_date::date) from %I where %I = $1', vtab_hist, tab_id_name)
        into ielapsedtime
      using tab_id_value;
      
      IF (ielapsedtime*86400 < itimespan) THEN
        return;
      END IF;
      ....
    END IF;
  END IF;
END;
Der Platzhalter %I für die format() Funktion setzt an der Stelle einen "Identifier" ein (Tabellen- bzw. Spaltennamen). Das $1 ist ein Parameter Platzhalter für das EXECUTE. Der Parameter wird dann via USING beim EXECUTE übergeben.
A SQL query walks into a bar and sees two tables. He walks up to them and says 'Can I join you?'

pogomips
Erfahrener Benutzer
Beiträge: 129
Registriert: Fr 18. Nov 2016, 09:55

Re: Tabelle als Variable abfragen

Beitrag von pogomips »

Format ist wahrscheinlich eine vertretbare Lösung. Die Frage wäre ja, was der Schaden sein könnte, wenn man falsche, ungeplante Werte (tabellennamen) reinschmuggelt. Die Antwort ist hier übersichtlich.

Die Frage wäre aber auch, was der reale Anwendungsfall ist. Warum sind es wechselnder History Tabellen und wieviel können es denn eigentlich in der Realität sein? 2 oder 3? Oder 50 oder N>50? Also warum gibt es diesen Sch...?
Pseudo Partitioning? Pseudo Staging? Oder einfach nur eine Krücke für Developer Tests?
In dem Zusammenhang: Warum ist das eine headless Operation? Und wenn es das ist, kann man die Tabelle nicht schon vorher mit ein wenig "bashing" danymisch ändern?

Jenachdem vielleicht doch lieber alles in geordnete Bahnen* lenken, statt das weiter mitzuschleifen!

*Eine Dimension in der Logtabelle spendieren für verschiedene Umgebungen, Testszenarien oder was auch immer der Trigger für die Varianz ist.

Nexx
Neuer Benutzer
Beiträge: 8
Registriert: Mo 9. Dez 2019, 12:03

Re: Tabelle als Variable abfragen

Beitrag von Nexx »

castorp hat geschrieben:
Mo 9. Dez 2019, 14:02
IF (hist_cause <> 'D') THEN

execute format('select count(*) from %I where %I = $1', vtab_hist, tab_id_name)
into icount
using tab_id_value; --<< übergibt den Wert für Parameter $1

IF (icount > 0) THEN
execute format('select current_date - max(hist_date::date) from %I where %I = $1', vtab_hist, tab_id_name)
into ielapsedtime
using tab_id_value;


Der Platzhalter %I für die format() Funktion setzt an der Stelle einen "Identifier" ein (Tabellen- bzw. Spaltennamen). Das $1 ist ein Parameter Platzhalter für das EXECUTE. Der Parameter wird dann via USING beim EXECUTE übergeben.
Guten Morgen,

gestern war ich leider krank, daher keine Antwort von mir.

Vielen Dank an alle für die Unterstützung.

Speziell jetzt zu dem Fall im Zitat:
Das ist eine sehr gute Lösung, die ich sogar vertsehe :), jedoch sagt der mir wieder, dass die gesuchte Tabelle nicht existiert.

execute format('select count(*) from %I where %I = $1', vtab_hist, tab_id_name)
Der braucht das Schema "awb" vor dem vtab_hist.
Ich weiss, aber nicht wie ich das Schema mit der Variablen Tabelle verknüpfe.

Falls ich auf dem Schlauch stehe bitte ich das zu entschuldigen :)

Gruß
Nexx

castorp
Erfahrener Benutzer
Beiträge: 1202
Registriert: Sa 27. Jun 2009, 22:24
Wohnort: Bayern

Re: Tabelle als Variable abfragen

Beitrag von castorp »

Dann verwende einen weiteren Platzhalter. Wenn Du eine Variable "table_schema" hast in der das Schema drinsteht, geht das so:

Code: Alles auswählen

execute format('select count(*) from %I.%I where %I = $1', table_schema, vtab_hist, tab_id_name)
...
A SQL query walks into a bar and sees two tables. He walks up to them and says 'Can I join you?'

Nexx
Neuer Benutzer
Beiträge: 8
Registriert: Mo 9. Dez 2019, 12:03

Re: Tabelle als Variable abfragen

Beitrag von Nexx »

pogomips hat geschrieben:
Mo 9. Dez 2019, 20:12
Format ist wahrscheinlich eine vertretbare Lösung. Die Frage wäre ja, was der Schaden sein könnte, wenn man falsche, ungeplante Werte (tabellennamen) reinschmuggelt. Die Antwort ist hier übersichtlich.

Die Frage wäre aber auch, was der reale Anwendungsfall ist. Warum sind es wechselnder History Tabellen und wieviel können es denn eigentlich in der Realität sein? 2 oder 3? Oder 50 oder N>50? Also warum gibt es diesen Sch...?
Pseudo Partitioning? Pseudo Staging? Oder einfach nur eine Krücke für Developer Tests?
In dem Zusammenhang: Warum ist das eine headless Operation? Und wenn es das ist, kann man die Tabelle nicht schon vorher mit ein wenig "bashing" danymisch ändern?

Jenachdem vielleicht doch lieber alles in geordnete Bahnen* lenken, statt das weiter mitzuschleifen!

*Eine Dimension in der Logtabelle spendieren für verschiedene Umgebungen, Testszenarien oder was auch immer der Trigger für die Varianz ist.
Es sind ca. 30 Tabellen.

Das war der Teil den ich verstanden habe. Deine Fragen anschließend sind mir nicht ganz klar.

Wie man merkt sind meine Fähigkeiten bzw. Erfahrungen recht begrenzt. Ich hoffe das ändert sich mit der Zeit.
Nur den ganzen Text auf den Kopf zu stellen würde ich mir einfach mal gar nicht zutrauen.

pogomips
Erfahrener Benutzer
Beiträge: 129
Registriert: Fr 18. Nov 2016, 09:55

Re: Tabelle als Variable abfragen

Beitrag von pogomips »

Ok also es gibt 30 (mögliche) Historie Tabellen?!

Meine Fragen gehen in verschiedene Richtungen.
"Developer Kram" wurde mal eingebaut, um was zu testen, es wird aber produktiv nicht genutzt, also wird aus 30 Tabellen 1, Problem erledigt.

Dann aus fachlicher Sicht: Was ist der Sinn einer Historie Tabelle? [..Bedenkzeit..]
Was ist der Sinn von 30 Historietabellen? [..Bedenkzeit..]
Wenn der Mechanismus dazu da ist, unterschiedliche "Wirklichkeiten" bzw. eben "Historien" eines gegebenen Status Quo zu liefern, ist es einfach sehr fraglich. Wenn es für verschiedene Umgebungen genutzt wird, ist es verständich (dev, stage, prod) und kann vielleicht anders gelöst werden (30 dev stage prod sind aber ungewöhnlich..)
30 Historietabellen für 30 verschiedene Muttertabellen wäre wiederum was anderes.

"Headless"
Du schreibst, es sei eine Funktion. Was Du zeigst ist aber keine Funktion. Es ist ein anonymer Block. Der ist nur aufrufbar
- interaktiv per command line oder IDE (wo spontan geändert werden könnte)
- aus einem Clientprogramm heraus (wo er zusammengesetzt werden könnte)
- aus dem Betriebssystem (wo er zusammengesetzt werden könnte)

in allen Fällen ist der Code, der ausgeführt wird, eigentlich variabel und kann schon vor der Ausführung so "geschrieben" werden, dass die richtige Tabelle verwendet wird, statt sie erst im Code zu tauschen.

Wie gesagt, Format bzw. der Code von Castorp sind sicher eine gute Lösung, wenn Deine und meine (Fern)Sicht, nicht fundiert genug sind.

laterne
Neuer Benutzer
Beiträge: 1
Registriert: Mo 20. Jan 2020, 17:57
Wohnort: Egglham
Kontaktdaten:

Re: Tabelle als Variable abfragen

Beitrag von laterne »

Danke mal für eure Hilfe, habe auch nach einer Antwort dazu gesucht! :)
Scham hat es nie wirklich ins Internet geschafft. Das Netz errötet nicht.

Antworten