Wie kann ich Funktionen nur einmal ausführen? Statische Werte

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
Benutzeravatar
martin.koeditz
Beiträge: 101
Registriert: Sa 31. Mär 2018, 14:35

Mi 4. Jul 2018, 13:41

Hallo zusammen,

ich habe eine Zuweisungstabelle für Mandanten. Hier gibt es einen Quell- und einen Ziel-Mandanten für jede Tabelle im System. Darüber werden abweichende Stammdaten gesteuert. Also zum Beispiel Adressdaten für einen Konzern. Diese werden im Stammmandanten gepflegt und stehen den Kindmandanten zur Verfügung.

Die Tabelle sieht folgendermaßen aus:

Code: Alles auswählen

CREATE TABLE TBL_CLIENT_TABLE
(
  CLIENT_ID Bigint DEFAULT 1 NOT NULL -- ID des anfragenden Mandanten,
  TABLE_NAME Varchar(31) NOT NULL -- Tabellenname,
  CLIENT_ID_DST Bigint NOT NULL -- ID des Zielmandanten,
  CREATOR_ID Bigint,
  CREATE_TIME Timestamp DEFAULT current_timestamp,
  EDITOR_ID Bigint,
  EDIT_TIME Timestamp DEFAULT current_timestamp,
  CONSTRAINT PK_CLIENT_TABLES PRIMARY KEY (CLIENT_ID,TABLE_NAME)
);
Nun habe ich eine Funktion geschrieben, die für jeden Mandanten die Zieltabellen (Ziel-ID) ermittelt. Diese Abfrage ist jedoch sehr langsam:

Code: Alles auswählen

select count(*)
from TBL_ADDRESS_TYPE 
where client_id = FNC_MASTER_CLIENT(3, 'TBL_ADDRESS_TYPE ');
Anscheinend wird für jede Zeile von TBL_ADDRESS_TYPE die Funktion neu ausgeführt, was zur langen Abfrage führt. Die Rückgabe ändert sich ja zu keinem Zeitpunkt. Gibt es einen Weg wie ich einen Wert ermittle und diesen während der Abfrage statisch halten kann?

Dank und Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 92
Registriert: Mo 7. Mai 2018, 18:09

Mi 4. Jul 2018, 19:43

Ab 3.0 kann man eine Funktion als "deterministic" definieren. D.h., dass die Funktion bei gleichen Aufrufparametern nur 1x aufgerufen wird.

Nun weiß ich nicht, was deine Funktion denn tut, aber es gibt 2 Funktionen, die dir ggf. helfen können:
RDB$GET_CONTEXT()
https://firebirdsql.org/refdocs/langref ... ntext.html
RDB$SET_CONTEXT()
https://firebirdsql.org/refdocs/langref ... ntext.html

Wichtig dafür ist das Arbeiten mit Transaktionen (wobei Autocommit auchzulässig wäre).
Beim Aufruf prüfst du, ob die Variable vorhanden ist und bereits den gewünschten Inhalt hat.
Wenn nein, dann führe deine Aktion aus und speichere den Wert in ein er Context-Variablen.
Gib als Ergebnis den Inhalt der Contextvariablen zurück.

Da diese Variablen CHAR sind, must du die beim Setzen in Char casten und beim Lesen in deinen gewünschten Ergebnistyp.

Variante 2:
Du legst eine 1-Satztabelle an, berechnest dein Ergebnis und speicherst diesen in dieser Tabelle.
a) Du machst einen "inner Join Tablle on 1=1" und prüfst den Inhalt gegen deine Variable in der Tabelle.
b) du machst einen "where exists (select * from Tabelle where client_id = Spaltenwert)"
Benutzeravatar
martin.koeditz
Beiträge: 101
Registriert: Sa 31. Mär 2018, 14:35

Do 5. Jul 2018, 09:41

Guten Morgen,

den Deterministic-Schalter habe ich gesucht.

Danke.
Martin Köditz
it & synergy GmbH
Antworten