Wednesday, January 6, 2010

Join-Queries mit temporären Tabellen (und es funktioniert eben doch)

Join-Queries mit temporären Tabellen (und es funktioniert eben doch)

Dieser Beitrag bezieht sich auf den englischsprachigen Artikel Queries with temporary tables (nevertheless it works)

Die Verwendung von temporären Tabellen innerhalb Queries kann ab und an zu Problemen führen; im Speziellen, wenn man die Fehlermeldung "Ein Datensatz in % (%) kann nicht ausgewählt werden. Temporäre Tabellen müssen bei Verknüpfung mit persistenten Tabellen äußere Tabellen sein." erhält. Ein Arbeitskollege hat allerdings eine solche Query zu meinem Erstaunen trotzdem zum Laufen gebracht. Auf der Grundlage seiner Vorarbeit habe ich das Thema mal genauer untersucht.

Die Inhaltsgrundlage dieses Beitrages basiert auf dem Wissen durchgeführten Tests. Die Funktionsweise von Queries mit temporären Tabellen wird hier allein durch Beobachtungen erklärt (auch wenn AX vielleicht anders als angenommen arbeitet).

Der genannte Fehler wird ausgelöst wenn die Datenselektion der jeweiligen Datenquelle nicht auf dem gleichen Tier ausgeführt wird, wie die übergeordnete (parent) Datenquelle. Die erste Datenquelle nimmt allerdings eine Sonderstellung ein. Die Datenquellen werden nämlich auf dem Tier abgearbeitet wo sich der Datenpuffer der Datenquelle befindet. Hat aber der Server-Tier einmal mit der Abarbeitung einer Datenquelle begonnen, kann für die weitere Datenselektion nicht mehr zurück auf den Client-Tier gewechselt werden.

Unter Beachtung einiger Regeln steht für eine Join-Query mit temporären Tabellen aber absolut nichts im Wege. Es gilt zu beachten:
  • Persistente Tabellen werden stets auf dem Server-Tier verarbeitet
  • Temporäre Tabellen werden auf dem Tier verarbeitet, auf den das Handle der Tabelle hinzeigt
    • Temporäre Tabellen, die üblicherweise persistent sind, aber mit der setTmp()-Methode zur Laufzeit temporär gestellt werden, werden auf dem Tier gehalten, wo die setTmp()-Methode angewendet wird

      CustTable custTable
      ;
      custTable.setTmp(); // now the handle will fixed on the current tier

    • Temporäre Tabellen welche bereits auch als solche im AOT definiert sind, werden dort gehalten wo sich auch die Deklaration befindet

      TmpSysQuery
      tmpSysQuery; // the handle is already fixed on the current tier
      ;

  • Die erste Datenquelle in der Query kann ihren Datenpuffer wahlweise vom Client- oder Server-Tier beziehen
  • Alle weiteren, und somit eingebetteten Datenquellen müssen ihren Datenpuffer entweder auf dem gleichen Tier wie ihre übergeordnete (parent) Datenquelle oder aber auf dem Server-Tier halten

Folgende Konstellationen sind demnach möglich oder eben nicht (einige Beispiele):
(Siehe englischer Artikel)

Fazit: Die Meldung "Ein Datensatz in % (%) kann nicht ausgewählt werden. Temporäre Tabellen müssen bei Verknüpfung mit persistenten Tabellen äußere Tabellen sein." würde wohl besser heissen: "Temporäre Datenquelle % bezieht Daten nicht aus dem gleichen Tier wie die übergeordnete Datenquelle % noch vom Server-Tier selbst.".

Hier noch ein paar allgemeine Anmerkungen zur Verwendung der setTmp()-Methode für persistente Tabellen:
  • Die setTmp()-Methode muss immer in derselben Methode wie die Deklaration der Tabelle erfolgen
  • Es darf noch keine Manipulation mit dem Tabellenpuffer erfolgt sein (andernfalls hat die setTmp()-Methode keinen Einfluss mehr auf den Puffer!)
  • Für Datenmanipulationen sollten die Skip-Methoden wie skipDataMethods()/skipDeleteMethods()/skipEvents()/skipDataBaseLog() verwendet werden und mit den Befehlen doUpdate(), doInsert() und doDelete() gearbeitet werden um ungewollte Änderungen an der persistenten Tabelle in der Datenbank zu verhindern


(Inhalt bezieht sich auf das QueryRun Objekt der Versionen AX 3.0 3tier, AX 4.0 und AX 5.0)

No comments:

Post a Comment