# Tabelle als Variable abfragen

**URL:** <https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609>\
**Category:** PL/pgSQL\
**Created:** [9. Dezember 2019 um 11:13 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609 "2019-12-09T11:13:25Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nexx](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/n/58f4c7/32.png) [@Nexx](https://www.pg-forum.de/u/Nexx)\
**Post date:** [9. Dezember 2019 um 11:13 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/1 "2019-12-09T11:13:25Z")

</div>

Hallo zusammen,

ich bin auf diesem Gebiet relativ frisch unterwegs und alles andere als ein Fachmann.  
Hier mein Problem:

Ich möchte zwei Daten (Datum) von einander abziehen um die zeitliche Differenz zu bestimmen. Das klappt auch wunderbar.  
Jetzt ist es aber so, dass ich die aktuelle Tabelle in einer Variablen vorliegen habe. Wie bekomme ich in meiner Abfrage das so hin, dass ich das Schema und die Variable verknüpfe?

Beispiel:  
select current\_date - max(Spalte) from schema. **tabelle** where …value into variable;

Das fett dargestellte tabelle ist eine Variable. Ich habe alles abgesucht. Vielleicht auch falsch gesucht, jedoch finde ich nichts hilfreiches dazu.

Danke vorab.

Gruß  
Nexx

---

<div class="post-metadata">

**Author:** ![akretschmer](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/a6a055/32.png) [@akretschmer](https://www.pg-forum.de/u/akretschmer)\
**Post date:** [9. Dezember 2019 um 11:19 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/2 "2019-12-09T11:19:54Z")

</div>

wo liegt diese Variable vor, in Deiner Applikation oder schon in der datenbank?

Falls letzteres: [https://www.postgresql.org/docs/12/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN](https://www.postgresql.org/docs/12/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN)

---

<div class="post-metadata">

**Author:** ![Nexx](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/n/58f4c7/32.png) [@Nexx](https://www.pg-forum.de/u/Nexx)\
**Post date:** [9. Dezember 2019 um 11:28 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/3 "2019-12-09T11:28:06Z")

</div>

Die Variable wird erst in der Abfrage gefüllt.

---

<div class="post-metadata">

**Author:** ![akretschmer](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/a6a055/32.png) [@akretschmer](https://www.pg-forum.de/u/akretschmer)\
**Post date:** [9. Dezember 2019 um 11:29 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/4 "2019-12-09T11:29:35Z")

</div>

Ja, dann wirst das als dynamisches Statement ausführen müssen.

Alternativ das derzeitige Konzept prüfen. Warum meinst Du, daß das so sein muß?

---

<div class="post-metadata">

**Author:** ![Nexx](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/n/58f4c7/32.png) [@Nexx](https://www.pg-forum.de/u/Nexx)\
**Post date:** [9. Dezember 2019 um 11:39 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/5 "2019-12-09T11:39:58Z")

</div>

Das ist wirklich mein erstes Projekt in diesem Bereich.

Das Ganze liegt als Oracle Programmierung fertig vor.  
Ich muss das in Postgresql migrieren.

Daher will ich bei diesem Programm nicht das ganze Konzept ändern.

Wie sieht denn ein dynamisches Statement aus, wenn das Schema feststeht, die Tabelle jedoch als Variable vorliegt?

---

<div class="post-metadata">

**Author:** ![akretschmer](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/a6a055/32.png) [@akretschmer](https://www.pg-forum.de/u/akretschmer)\
**Post date:** [9. Dezember 2019 um 11:46 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/6 "2019-12-09T11:46:50Z")

</div>

schau dir einfach die Beispiele in dem Link an, den ich Dir schon geschickt habe.

---

<div class="post-metadata">

**Author:** ![castorp](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/c/e99b99/32.png) [@castorp](https://www.pg-forum.de/u/castorp)\
**Post date:** [9. Dezember 2019 um 12:01 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/7 "2019-12-09T12:01:29Z")

</div>

Warum zeigst Du uns nicht einfach mal den PL/SQL Code der Oracle Prozedur? Dann müssten wir nicht raten, was genau da passieren soll.

---

<div class="post-metadata">

**Author:** ![Nexx](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/n/58f4c7/32.png) [@Nexx](https://www.pg-forum.de/u/Nexx)\
**Post date:** [9. Dezember 2019 um 12:42 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/8 "2019-12-09T12:42:47Z")

</div>

Hier ist der Quellcode. Das wird als Funktion aufgerufen und bekommt vier Werte übergeben (tab\_name, tab\_id\_name, tab\_id\_value, hist\_cause).  
Danke euch.

Mit den Informationen aus deinem Link komme ich nicht weiter.

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  
select count(_) from information\_schema.tables where table\_name = (vtab\_hist) and table\_schema = ‘awb’ into icount;  
IF (icount \> 0) THEN  
select current\_date - max(hist\_date) from vtab\_hist where schemaname = ‘awb’ and tab\_id\_name = tab\_id\_value into ielapsedtime;  
IF (ielapsedtime_86400 \< itimespan) THEN  
return;  
END IF;  
END IF;  
END IF;  
END;

---

<div class="post-metadata">

**Author:** ![Nexx](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/n/58f4c7/32.png) [@Nexx](https://www.pg-forum.de/u/Nexx)\
**Post date:** [9. Dezember 2019 um 12:44 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/9 "2019-12-09T12:44:00Z")

</div>

Quellcode des betroffenen Abschnittes der Oracle DB

if(hist\_CAUSE \<\> ‘D’) then  
EXECUTE IMMEDIATE 'select count(_) from ’ || vtab\_Hist || ’ where ’ || tab\_ID\_NAME || ’ = ‘’’ || tab\_ID\_VALUE || ‘’’’ into iCount ;  
if (iCount \> 0) then  
EXECUTE IMMEDIATE ‘select SYSDATE-MAX(HIST\_DATE) from ’ || vtab\_Hist|| ’ where ’ || tab\_ID\_NAME || ’ = ‘’’ || tab\_ID\_VALUE || ‘’’’ into iElapsedTime;  
if(iElapsedTime_86400 \< iTimeSpan) then  
return;  
end if;  
end if;  
end if;

---

<div class="post-metadata">

**Author:** ![akretschmer](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/a/a6a055/32.png) [@akretschmer](https://www.pg-forum.de/u/akretschmer)\
**Post date:** [9. Dezember 2019 um 12:54 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/10 "2019-12-09T12:54:57Z")

</div>

Nun, du bekommst ja schon tab\_name übergeben. In deinen EXECUTE-statements siehst auch wie das dynamisch zusammengestzt wird, das kannst Du direkt als Vorlage nehmen. Dazu dann das durchlesen, was ich Dir als Link geschickt habe.

---

<div class="post-metadata">

**Author:** ![Nexx](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/n/58f4c7/32.png) [@Nexx](https://www.pg-forum.de/u/Nexx)\
**Post date:** [9. Dezember 2019 um 12:56 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/11 "2019-12-09T12:56:28Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![castorp](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/c/e99b99/32.png) [@castorp](https://www.pg-forum.de/u/castorp)\
**Post date:** [9. Dezember 2019 um 13:02 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/12 "2019-12-09T13:02:14Z")

</div>

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:

```nohighlight
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.

---

<div class="post-metadata">

**Author:** ![pogomips](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/p/bbe5ce/32.png) [@pogomips](https://www.pg-forum.de/u/pogomips)\
**Post date:** [9. Dezember 2019 um 19:12 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/13 "2019-12-09T19:12:02Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![castorp](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/c/e99b99/32.png) [@castorp](https://www.pg-forum.de/u/castorp)\
**Post date:** [11. Dezember 2019 um 07:16 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/14 "2019-12-11T07:16:27Z")

</div>

Dann verwende einen weiteren Platzhalter. Wenn Du eine Variable “table\_schema” hast in der das Schema drinsteht, geht das so:

```nohighlight
execute format('select count(*) from %I.%I where %I = $1', table_schema, vtab_hist, tab_id_name)
...

```

---

<div class="post-metadata">

**Author:** ![pogomips](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/p/bbe5ce/32.png) [@pogomips](https://www.pg-forum.de/u/pogomips)\
**Post date:** [11. Dezember 2019 um 19:07 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/15 "2019-12-11T19:07:22Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![laterne](https://www.pg-forum.de/letter_avatar_proxy/v4/letter/l/c89c15/32.png) [@laterne](https://www.pg-forum.de/u/laterne)\
**Post date:** [21. Januar 2020 um 22:51 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/16 "2020-01-21T22:51:44Z")

</div>

Danke mal für eure Hilfe, habe auch nach einer Antwort dazu gesucht! 🙂

---

<div class="post-metadata">

**Author:** ![system](https://www.pg-forum.de/uploads/default/original/1X/dc97a981dd26692d5fb52e8b8fc7c090d7b9559a.png) [@system](https://www.pg-forum.de/u/system)\
**Post date:** [21. Februar 2021 um 07:10 UTC](https://www.pg-forum.de/t/tabelle-als-variable-abfragen/609/17 "2021-02-21T07:10:23Z")

</div>


