The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Quiq::Database::Connection - Verbindung zu einer Relationalen Datenbank

BASE CLASS

Quiq::Hash

DESCRIPTION

Ein Objekt der Klasse repräsentiert eine Verbindung zu einer Relationalen Datenbank.

METHODS

Konstruktor/Destruktor

new() - Öffne Datenbankverbindung

Synopsis

  $db = $class->new(@opt);
  $db = $class->new($udl,@opt);
  $db = $class->new($udlObj,@opt);
  $db2 = $db->new(@opt);

Alias

connect()

Options

-cacheDir => $path

In diesem Verzeichnis werden Ergebnismengen gecacht, wenn dies bei Selektionen angefordert wird.

-handle => $dbh (Default: undef)

Bereits aufgebaute Low-Level Datenbankverbindung zuweisen.

-log => $bool (Default: 0)

Logging von SQL-Statements.

-logfile => $filename (Default: '-')

Logdatei. Wenn nicht angegeben oder '-' wird auf STDOUT gelogged.

-sqlClass => $class (Default: 'Quiq::Sql')

Name der Sql-Klasse zur Statementgenerierung.

-strict => $bool (Default: undef)

Aktiviere oder deaktiviere automatische Fehlerbehandlung.

-utf8 => $bool (Default: 1)

Definiere das clientseitige Character Encoding als UTF-8.

Description

Instantiiere eine Datenbankverbindung und liefere eine Referenz auf dieses Objekt zurück.

Ist $udl nicht angegeben, wird der Wert der Environment-Variable $UDL verwendet.

Wird die Methode als Objektmethode einer bestehenden Datenbankverbindung gerufen, wird eine weitere Verbindung zur selben Datenbank aufgebaut. Dies ist nützlich, wenn eine parallele Transaktion benötigt wird.

newFromSbit() - Instantiiere Quiq::Database::Connection-Datenbankobjekt aus Sbit-Datenbankobjekt

Synopsis

  $db = $class->newFromSbit($db,@opt);

disconnect() - Schließe Datenbankverbindung

Synopsis

  $db->disconnect;
  $db->disconnect($commit);

Alias

destroy()

Description

Schließe Datenbankverbindung. Ist $commit "wahr", committe die Daten vor dem Schließen der Verbindung. Die Methode liefert keinen Wert zurück.

Die Objektreferenz $db ist nach Aufruf der Methode ungültig und kann nicht mehr verwendet werden.

dbExists() - Prüfe, ob Datenbankverbindung aufgebaut werden kann

Synopsis

  $bool = $class->dbExists($udl);

Description

Prüfe, ob Verbindung zur Datenbank $udl möglich ist. Liefere "wahr", wenn dies der Fall ist, andernfalls "falsch".

Akzessoren

maxBlobSize() - Liefere/Setze max. Größe von BLOB/TEXT (Oracle)

Synopsis

  $n = $db->maxBlobSize;
  $n = $db->maxBlobSize($n);

Description

Liefere/Setze die maximale Größe eines BLOB/TEXT-Werts auf $n Bytes. Defaulteinstellung ist 1024*1024 Bytes (1MB).

Dieser Wert ist nur für Oracle relevant und wird bei der Selektion von BLOB/TEXT-Kolumnen benötigt. Ist der Wert einer BLOB/TEXT-Kolumne größer als die angegebene Anzahl an Bytes wird eine Exception ausgelöst.

Bei anderen DBMSen als Oracle hat das Setzen keinen Effekt und der Returnwert der Methode ist immer 0.

strict() - Strict-Modus abfragen oder umschalten

Synopsis

  $bool = $db->strict;
  $bool = $db->strict($bool);

Description

Bei eingeschaltetem Strict-Modus wird im Falle eines Datenbankfehlers eine Exception geworfen.

Example

  my $db = Quiq::Database::Connection->new('dbi#mysql',
      -handle => $main::dbh,
  );
  
  ...
  
  $db->strict(1);
  
  # bei Datenbank-Fehler wird Exception geworfen
  
  $db->strict(0)
  
  # bei Datenbank-Fehler wird keine Exception geworfen

stmt() - Liefere das Sql-Objekt

Synopsis

  $sqlObj = $db->stmt;

Aliases

  • sqlEngine()

  • gen()

Description

Liefere das Sql-Objekt der Datenbankverbindung. Mit dem Sql-Objekt lassen sich SQL-Statements generieren, z.B.

  $stmt = $db->stmt->dropTable($table);

udl() - Liefere das Udl-Objekt

Synopsis

  $udlObj = $db->udl;

Description

Liefere das Udl-Objekt der Datenbankverbindung. Das Udl-Objekt hält Information über die Datenbankverbindung, z.B.

  $user = $db->udl->user;

Time Measurement

startTime() - Liefere Zeitpunkt des Verbindungsaufbaus

Synopsis

  $time = $cur->startTime;

time() - Liefere Dauer seit Beginn des Verbindungsaufbaus

Synopsis

  $time = $cur->time;

DBMS-Tests

Die folgenden Methoden testen auf das DBMS. Sie werden angewendet, wenn DBMS-spezifische Unterscheidungen vorgenommen werden müssen.

dbms() - Liefere den Namen des DBMS

Synopsis

  $dbms = $db->dbms;

dbmsTestVector() - Vektor für DBMS-Tests

Synopsis

  ($oracle,$postgresql,$sqlite,$mysql,$access,$mssql,$jdbc) = $db->dbmsTestVector;

isOracle() - Prüfe auf Oracle-DBMS

Synopsis

  $bool = $db->isOracle;

Description

Liefere "wahr", wenn die Datenbank eine Oracle-Datenbank ist, sonst "falsch".

isPostgreSQL() - Prüfe auf PostgreSQL-DBMS

Synopsis

  $bool = $db->isPostgreSQL;

Description

Liefere "wahr", wenn die Datenbank eine PostgreSQL-Datenbank ist, sonst "falsch".

isSQLite() - Prüfe auf SQLite-DBMS

Synopsis

  $bool = $db->isSQLite;

Description

Liefere "wahr", wenn die Datenbank eine SQLite-Datenbank ist, sonst "falsch".

isMySQL() - Prüfe auf MySQL-DBMS

Synopsis

  $bool = $db->isMySQL;

Description

Liefere "wahr", wenn die Datenbank eine MySQL-Datenbank ist, sonst "falsch".

isAccess() - Prüfe auf Access-DBMS

Synopsis

  $bool = $db->isAccess;

Description

Liefere "wahr", wenn die Datenbank eine Access-Datenbank ist, sonst "falsch".

isMSSQL() - Prüfe auf MSSQL-DBMS

Synopsis

  $bool = $db->isMSSQL;

Description

Liefere "wahr", wenn die Datenbank eine MSSQL-Datenbank ist, sonst "falsch".

isJDBC() - Prüfe auf JDBC-DBMS

Synopsis

  $bool = $db->isJDBC;

Description

Liefere "wahr", wenn die Datenbank eine JDBC-Datenbank ist, sonst "falsch".

Handle

handle() - Lowlevel (DBI-)Handle

Synopsis

  $dbh = $db->handle;

Information

defaultRowClass() - Liefere Namen der Default-Rowklasse

Synopsis

  $rowClass = $this->defaultRowClass($raw);

Description

Liefere den Namen der Default-Rowklasse:

  Quiq::Database::Row::Object  ($raw ist "falsch")
  Quiq::Database::Row::Array   ($raw ist "wahr")

Auf die Default-Rowklasse werden Datensätze instantiiert, für die bei einer Datenbank-Selektion oder einer Instantiierung einer Table-Klasse keine Row-Klasse explizit angegeben wurde.

Logging

Alle Statements einer Session oder ein gewisser Abschnitt kann gelogged werden.

Für die gesamte Session:

  $db = Quiq::Database::Connection->new($udl,-log=>1);

Innerhalb eines Abschnitts:

  $db->openLog;
  ...
  $db->closeLog;

Testen, ob Db-Logging eingeschaltet ist:

  $db->isLog;

Schreiben eigener Meldungen ins Log:

  $db->printLog($msg);

Scheiben von Fortschrittsmeldungen ins Log:

  $db->startProgressLog($n);
  while (...) {
      $db->printProgressLog($msg);
  }
  $db->endProgressLog;

isLog() - Prüfe, ob Logging eingeschaltet ist

Synopsis

  $bool = $db->isLog;

openLog() - Öffne SQL-Log

Synopsis

  $db->openLog;

writeLog() - Schreibe Zeichenkette ins SQL-Log

Synopsis

  $db->writeLog(@str);

Description

Schreibe Argumente @str ins geöffnete SQL-Log. Ist das SQL-Log nicht geöffnet, wird nichts geschrieben. Die Methode liefert keinen Wert zurück.

msgToLog() - Schreibe Meldung ins SQL-Log

Synopsis

  $db->msgToLog($msg);

Alias

printLog()

Description

Schreibe Meldung $msg ins SQL-Log. Die Methode liefert keinen Wert zurück.

Der Logfileeintrag hat folgenden Aufbau:

  <LogMsgSeparator>
  <LogMsgPrefix> <msg>

Mit Defaultwerten:

  ---
  # <msg>

Ist die Meldung mehrzeilig, wird der LogMsgPrefix jeder Zeile vorangestellt.

stmtToLog() - Schreibe SQL Statement ins SQL-Log

Synopsis

  $db->stmtToLog($stmt);

Description

Schreibe SQL Statement $stmt ins SQL-Log. Die Methode liefert keinen Wert zurück.

Der Logfileeintrag hat folgenden Aufbau:

  <LogMsgSeparator>
  <stmt>

Mit Defaultwerten:

  ===
  <stmt>

Ist die Meldung mehrzeilig, wird der LogMsgPrefix jeder Zeile vorangestellt.

timeToLog() - Schreibe Ausführungszeit ins SQL-Log

Synopsis

  $db->timeToLog($time);

Description

Schreibe Ausführungszeit $time ins SQL-Log. Die Methode liefert keinen Wert zurück.

Der Logfileeintrag hat per Default folgenden Aufbau:

  /* <time> */

closeLog() - Schließe SQL-Log

Synopsis

  $db->closeLog;

startProgressLog() - Beginne Fortschrittsmeldungen

Synopsis

  $db->startProgressLog($n);

printProgressLog() - Schreibe Fortschrittsmeldung ins SQL-Log

Synopsis

  $db->printProgressLog($msg);

Description

Schreibe Fortschrittsmeldung $msg ins SQL-Log. Die Methode liefert keinen Wert zurück.

Der Logfileeintrag hat folgenden Aufbau:

  <LogMsgPrefix> <msg>

Mit Defaultwerten:

  # <msg>

Ist die Meldung mehrzeilig, wird sie einzeilig gemacht, indem NEWLINE durch SPACE ersetzt wird.

endProgressLog() - Beende Fortschrittsmeldungs-Folge im SQL-Log

Synopsis

  $db->endProgressLog($msg);

Export/Import

exportTable() - Exportiere Tabelle

Synopsis

  $db->exportTable($table,$file);

Description

Exportiere die Daten der Tabelle $table in Datei $file.

importTable() - Importiere Tabelle

Synopsis

  $db->importTable($table,$file);

Description

Importiere die Daten aus Datei $file in Tabelle $table.

Locking

lockTable() - Locke Tabelle

Synopsis

  $db->lockTable($table);

SQL Execution

sql() - Führe SQL-Statement aus

Synopsis

  $cur = $db->sql($stmt,@opt);

Options

cache => $n (Default: undef)

Cache die Datensätze, die das Statement $stmt liefert, für $n Sekunden. D.h. hole die Datensätze innerhalb dieser Zeitspanne nicht erneut von der Datenbank, sondern lies sie aus dem Cache. Ist $n 0, werden die Datensätze unbegrenzt lange gecacht.

-chunkSize => $n (Default: 500)

Fetche Datensätze in Chunks von $n Sätzen. Diese Option hat aktuell nur bei PostgreSQL und -fetchMode 1 oder 2 eine Bedeutung.

-fetchMode => 0 | 1 | 2 (Default: 1)

Der Parameter hat nur im Falle PostgreSQL eine Auswirkung. Siehe auch Abschnitt "SELECT mit PostgreSQL".

0

Normaler DBI::Pg-Fetchmodus, d.h. die gesamte Ergebnismenge wird zum Client transferiert, bevor dieser den ersten Datensatz erhält. Dieser Modus ist für große Datenmengen schlecht geeignet.

1

Die Datensätze werden in Chunks von -chunkSize Sätzen gefetcht. Dies ist der Default-Modus.

2

Wie 1, wobei zusätzlich eine eigene Connection für die Selektion geöffnet wird. Dies ist notwendig, wenn während der Datensatz-Verarbeitung COMMITs oder ROLLBACKs ausgeführt werden sollen. Eine Cursor-basierte Selektion wird bei PostgreSQL ohne eigene Connection wird mit dem ersten COMMIT oder ROLLBACK ungültig.

-forceExec => $bool (Default: 0)

Forciere die Ausführung des Statement. Dies kann bei Oracle PL/SQL Code notwendig sein, wenn Konstrukte enthalten sind, die von DBI/DBD irrtümlich als Bind-Variablen interpretiert werden. Z.B. bei folgender Trigger-Definition das ":new":

  CREATE OR REPLACE TRIGGER x_before_insert
  BEFORE INSERT
      ON x
      FOR EACH ROW
  BEGIN
      :new.create_date := sysdate;
  END;

Ohne -forceExec=>1 würde das Statement lediglich präpariert, nicht ausgeführt.

-log => 0|1 (Default: -log der Connection)

Schreibe SQL-Statement und Ausführungszeit nach STDOUT.

-raw => $bool (Default: 0)

Fetche die Datensätze als einfache Arrays statt als komplexe Row-Objekte. Als Default-Rowklasse verwende Quiq::Database::Row::Array statt Quiq::Database::Row::Object (der Parameter -rowClass überschreibt diesen Default).

-rowClass => $rowClass (Default: 'Quiq::Database::Row::Object')

Name der Datensatzklasse, auf die die Datensätze der Ergebnismenge geblesst werden.

-tableClass => $tableClass (Default: siehe Text)

Name der Tabellenklasse, die die Ergebnismenge speichert. Bei Raw-Datensätzen ist Quiq::Database::ResultSet::Array der Default, ansonsten Quiq::Database::ResultSet::Object.

Returns

Referenz auf Cursor-Objekt (Quiq::Database::Cursor)

Description

Führe SQL-Statement $stmt über Datenbankverbindung $db aus, instantiiere ein Resultat-Objekt (Cursor), und liefere eine Referenz auf dieses Objekt zurück.

Details

SELECT mit PostgreSQL

Bei PostgreSQL (DBD::Pg) holt ein SELECT erst die gesamte Ergebnismenge zum Client. Das ist für große Ergebnismengen fatal.

Um die Datensätze in Chunks zu holen, muss ein CURSOR verwendet werden:

  DECLARE <cursor> CURSOR FOR <stmt>;
  FETCH <n> FROM <cursor>;
  ...
  CLOSE <cursor>;

Hierbei ist:

  <cursor> der Name des Cursors
  <stmt> das SELECT-Statement
  <n> die Anzahl der zu fetchenden Datensätze

Die Methode $db->sql() implementiert im Falle von PostgreSQL SELECTs durch obige Anweisungsfolge, wenn die Option -fetchMode gesetzt ist.

  -fetchMode=>0|1|2 (Default: 0)
      0=Defaultverhalten, 1=dekl. Cursor, 2=dekl. Cursor + extra Session
  -chunkSize=>$n (Default: 500)
      Fetche Datensätze in Chunks von $n Stück

sqlAtomic() - Führe SQL-Statement atomar aus

Synopsis

  $cur = $db->sqlAtomic($stmt,@opt);

Description

Führe DDL-Statement $stmt aus, instantiiere ein Resultat-Objekt (Cursor), und liefere eine Referenz auf dieses Objekt zurück.

Das Statement wird atomar ausgeführt, d.h. ist das Statement erfolgreich, wird anschließend ein COMMIT ausgeführt, schlägt das Statement fehl, wird ein ROLLBACK ausgeführt.

Dieses Verhalten ist insbesondere im Falle von PostgreSQL wichtig, da bei PostgreSQL praktisch alles einer Transaktionskontrolle unterliegt. Z.B. können erzeugte Objekte nicht zugriffen werden, solange ihre Erzeugung nicht abgeschlossen ist, d.h. der Zugriff auf die erzeugten Objekte wird blockiert. Oder das Setzen von Session-Einstellungen verfällt mit einem ROLLBACK. usw.

execute() - Führe SQL-Statement atomar aus und liefere Ergebnis

Synopsis

  $str = $db->execute($stmt,@opt);

Arguments

SQL-Statement.

Options

Alle Optionen der Methode $db->sql() plus

-color => $bool (Default: 1)

Zeige das Resultat der Statement-Ausführung farbig an.

-limit => $n (Default: 10)

Begrenze die Anzahl der gefetchten Datensätze auf $n.

Returns

Ausführungsergebnis (String)

Description

Führe DDL-Statement $stmt aus und liefere das Ergebnis der Ausführung in Form eines Textes zurück. Im Falle einer Selektion werden die selektierten Datensätze in einer ASCII-Tabelle dargestellt. Die maximale Anzahl der selektierten Datensätze ist per Default auf 10 begrenzt (siehe Option -limit).

Die Methode ist nützlich für die Programmierung von einfachen Terminal-Clients für Ad-Hoc-Abfragen.

Patches

applyPatches() - Wende offene Patches auf Datenbank an

Synopsis

  $n = $db->applyPatches($patchClass);

Arguments

$patchClass

(String) Klasse, die die Patchmethoden enthält.

Returns

(Integer) Anzahl der angewandten Patch-Methoden.

Description

Wende alle offenen Patches auf die Datenbank an. Die Patches sind als Methoden in der Klasse $patchClass implementiert. Die Patch-Methoden haben das Namensmuster

  patchNNN

Hierbei ist NNN der Patchlevel, den die Methode implementiert. Der aktuelle Patchlevel der Datnbank ist der maximale Wert der Kolumne PAT_LEVEL in Tabelle PATCH. Es werden alle Patch-Methoden angewandt, deren Patchlevel größer ist als der aktuelle Patchlevel. Existiert die Tabelle PATCH nicht, wird sie angelegt.

maxPatchLevel() - Liefere maximalen Patchlevel der Patch-Klasse

Synopsis

  $patchLevel = $this->maxPatchLevel($patchClass);

Arguments

$patchClass

Name der Klasse, die die Patchmethoden enthält.

Returns

(Integer) Maximaler Patchlevel.

Description

Ermittele den maximalen Patchlevel, also die höchste Nummer unter allen Patch-Methoden, die in der Klasse $patchClass implementiert sind, und liefere diesen zurück.

patchLevel() - Liefere den aktuellen Patchlevel der Datenbank

Synopsis

  $patchLevel = $db->patchLevel;

Returns

(Integer) Patchlevel der Datenbank.

Description

Ermittele den aktuellen Patchlevel der Datenbank und liefere diesen zurück. Existiert die Tabelle PATCH auf der Datenbank nicht oder hat sie keinen Eintrag, liefert die Methode 0.

patchMethods() - Liefere Liste der Patch-Methoden

Synopsis

  @patchMethods | $patchMehodA = $this->patchMethods($patchClass);

Arguments

$patchClass

Name der Klasse, die die Patchmethoden enthält.

Returns

(Array of Pairs) Liste der Patch-Methoden der Klasse $patchClass. Im Skalarkontext eine Referenz auf die Liste.

Description

Ermittele die Liste der Patch-Mehoden der Klasse $patchClass und liefere diese zurück. Ein Element der Liste ist ein Paar, bestehend aus dem Methoden-Namen und einer Glob-Referenz, über die die Patch-Methode aufgerufen werden kann. Die Liste ist aufsteigend nach Methodenname sortiert.

patchReport() - Liefere Bericht über den Stand der Patches

Synopsis

  $report = $db->patchReport($patchClass);

Arguments

$patchClass

Name der Klasse, die die Patchmethoden enthält.

Returns

(String) Patch-Bericht

Description

Erzeuge einen Bericht über den Stand der Patches auf der Datenbank und liefere diesen zurück. Der Bericht hat den Aufbau:

  NAME001() - DESCRIPTION001 (STATUS001)
  NAME002() - DESCRIPTION002 (STATUS002)
  ...

Hierbei ist:

  NAMEXXX        - Name der Patchmethode des Patch XXX
  DESCRIPTIONXXX - Beschreibung des Patch XXX
  STATUSXXX      - Status des Patch XXX ('applied' oder 'new')

Sessions

setSchema() - Setze Default-Schema

Synopsis

  $cur = $db->setSchema($schema);

Description

Setze das Default-Schema der Session und liefere das Resultat der Ausführung zurück.

Das Datenbank-Objekt merkt sich das Default-Schema. Von mehreren Aufrufen hintereinander mit dem selben Schema, wird nur der erste Aufruf gegenüber dem DBMS ausgeführt, die anderen sind Null-Operationen.

setEncoding() - Definiere Client-Encoding

Synopsis

  $cur = $db->setEncoding($charset);

setDateFormat() - Setze Default-Datumsformat

Synopsis

  $cur = $db->setDateFormat;

setNumberFormat() - Setze Default-Zahlenformat

Synopsis

  $cur = $db->setNumberFormat;

setSearchPath() - Setze Schema-Suchpfad

Synopsis

  $cur = $db->setSearchPath(@schemas);

Description

Setze den Schema-Suchpfad und liefere einen Cursor mit dem Ergebnis der Statementausführung zurück.

PostgreSQL / Greenplum

Der Schema-Suchpfad wird von PostgreSQL genutzt, um Datenbank-Objekte zu finden, die nicht mit einem Schema-Präfix qualifiziert sind. Das erste Schema der Liste ist gleichzeitig das Default-Schema, in dem Datenbank-Objekte erzeugt werden (unabhängig davon, ob sie sich in einem anderen Schema des Suchpfads befinden).

Transactions

runCount() - Anzahl ausgeführter Statements

Synopsis

  $n = $db->runCount;

Description

Liefere die Anzahl der in der aktuellen Transaktion ausgeführten Statements. Diese Information kann z.B. genutzt werden, um zu entscheiden, ob ein COMMIT oder ROLLBACK ausgeführt werden müsste.

begin() - Beginne Transaktion

Synopsis

  $cur = $db->begin;

Description

Beginne Transaktion und liefere das Resultat der Ausführung zurück.

commit() - Bestätige Datenänderungen

Synopsis

  $cur = $db->commit;
  $cur = $db->commit($commit);

Description

Bestätige alle auf der Datenbank durchgeführten Änderungen und liefere das Resultat der Ausführung zurück.

Wird die Methode mit Argument aufgerufen, entscheidet dessen Wahrheitswert, ob ein COMMIT oder ein ROLLBACK ausgeführt wird. Im Falle von "wahr" wird ein COMMIT ausgeführt, im Falle von "falsch" ein ROLLBACK.

rollback() - Verwirf Datenänderungen

Synopsis

  $cur = $db->rollback;

Description

Verwirf alle auf der Datenbank durchgeführten Datenänderungen.

save() - Aktualisiere Datensatz auf Datenbank

Synopsis

  $cur = $db->save($table,$row,@where);

Description

Aktualisiert den Datensatz $row gemäß seines Status auf der Datenbank $db und liefere das Resultat der Statement-Ausführung zurück.

Welche Datenbankoperation konkret ausgeführt wird, ergibt sich aus dem Status des Datensatzes.

Statuswerte

'0' (unverändert)

Es wird keine Datenbankoperation ausgeführt.

'U' (modifiziert)

Es wird eine Update-Operation auf der Datenbank ausgeführt, d.h. es wird die Methode $row->update() gerufen.

'I' (neu)

Es wird eine Insert-Operation auf der Datenbank ausgeführt, d.h. es wird die Methode $row->insert() gerufen.

'D' (zu löschen)

Es wird eine Delete-Operation auf der Datenbank ausgeführt, d.h. es wird die Methode $row->delete() gerufen.

Kolumnentitel

titles() - Liefere Liste der Kolumnentitel

Synopsis

  $titleA|@titles = $db->titles(@select);

Description

Ermittele die Liste der Kolumentitel zum Statement @select und liefere diese zurück. In skalaren Kontext liefere eine Referenz auf die Liste.

Anmerkung: Die Titelliste wird gecacht. Je Statement wird die Datenbank nur einmal befragt. Alle weiteren Aufrufe werden aus dem Cache befriedigt.

primaryKey() - Liefere Primärschlüssel-Kolumne

Synopsis

  $title = $db->primaryKey($table);

Description

Liefere die Primärschlüsselkolumne der Tabelle $table.

Die Primärschlüsselkolumne ist per Definition die erste Kolumne der Tabelle. Datenmodelle mit zusammengesetzten Primärschlüsseln werden nicht unterstützt.

Select Operations

select() - Liefere Liste von Datensätzen

Synopsis

  $tab|@rows|$cur|$stmt = $db->select(@select,@opt);

Options

-cache => $n

Siehe Quiq::Database::Connection/sql().

-chunkSize => $n

Siehe Quiq::Database::Connection/sql().

-cursor => $bool (Default: 0)

Siehe Quiq::Database::Connection/sql().

-fetchMode => 0|1|2

Siehe Quiq::Database::Connection/sql().

-raw => $bool (Default: 0)

Siehe Quiq::Database::Connection/sql().

-rowClass => $rowClass

Siehe Quiq::Database::Connection/sql().

-sql => $bool (Default: 0)

Führe das Statement nicht aus, sondern liefere das SQL-Statemement zurück.

-tableClass => $tableClass

Siehe Quiq::Database::Connection/sql().

selectWith() - Liefere Liste von Datensätzen

Synopsis

  $tab|@rows|$cur = $db->selectWith($stmt,@select,@opt);

Arguments

$stmt

SELECT-Statement, das in eine WITH Klausel eingebettet wird.

@select

Siehe select()

@opt

Siehe select()

Options

Siehe select()

Returns

Siehe select()

Description

Bette SELECT-Statement $stmt in eine WITH-Klausel ein und führe die Selektion über dieser WITH-Klausel aus. Die WITH-Klausel hat den Vorteil, dass die Bedingungen der WHERE-Klausel über den Kolumnennamen der SELECT-Liste formuliert werden können.

Rationale

Eine Selektion über dem Statement

  SELECT
      fun.oid AS fun_oid
      , usr.usename AS fun_owner
      , nsp.nspname AS fun_schema
      , fun.proname AS fun_name
      , pg_get_function_identity_arguments(fun.oid) AS fun_arguments
      , fun.proname || '(' ||
          COALESCE(pg_get_function_identity_arguments(fun.oid), '')
          || ')' AS fun_signature
      , pg_get_functiondef(fun.oid) AS fun_source
  FROM
      pg_proc AS fun
      JOIN pg_namespace AS nsp
          ON fun.pronamespace = nsp.oid
      JOIN pg_user usr
          ON fun.proowner = usr.usesysid

liefert zwar Datensätze mit den eigens vergebenen Kolumnennamen fun_oid, fun_owner usw. Diese Namen können jedoch nicht bei der Formulierung der WHERE-Klausel verwendet werden. Stattdessen müssen die Namen der zugrundeliegenden Tabellen verwendet werden. Diese Assymetrie, die eine wirkliche Kapselung verhindert, lässt sich vermeiden, wenn das Statement in eine WITH-Klausel eingebettet und über dieser die Selektion formuliert wird. In dem Fall können (und müssen) die Namen des eingebetteten SELECT verwendet werden. Hier eine Suche via fun_name ($stmt ist obiges Statement):

  $stmt = $sql->selectWith($stmt,
      -select => 'fun_schema','fun_signature',
      -where => fun_name => 'check_bigint',
          fun_arguments => 'text, boolean, text, text',
      -orderBy => 'fun_schema',
  );

liefert

  WITH qry AS (
      SELECT
          fun.oid AS fun_oid
          , usr.usename AS fun_owner
          , nsp.nspname AS fun_schema
          , fun.proname AS fun_name
          , pg_get_function_identity_arguments(fun.oid) AS fun_arguments
          , fun.proname || '(' ||
              COALESCE(pg_get_function_identity_arguments(fun.oid), '')
              || ')' AS fun_signature
          , pg_get_functiondef(fun.oid) AS fun_source
      FROM
          pg_proc AS fun
          JOIN pg_namespace AS nsp
              ON fun.pronamespace = nsp.oid
          JOIN pg_user usr
              ON fun.proowner = usr.usesysid
  )
  SELECT
      fun_schema
      , fun_signature
  FROM
      qry
  WHERE
      fun_name = 'check_bigint'
      AND fun_arguments = 'text, boolean, text, text'
  ORDER BY
      fun_schema

selectFrom() - Liefere Liste von Datensätzen

Synopsis

  $tab|@rows|$cur = $db->selectFrom($stmt,@select,@opt);

Arguments

$stmt

SELECT-Statement, das in eine WITH Klausel eingebettet wird.

@select

Siehe select()

@opt

Siehe select()

Options

Siehe select()

Returns

Siehe select()

Description

Bette SELECT-Statement $stmt inline in eine FROM-Klausel ein und führe die Selektion aus. Die Inline-Einbettung hat den Vorteil, dass die Bedingungen der WHERE-Klausel über den Kolumnennamen der SELECT-Liste formuliert werden können:

  ...
  FROM (
      STMT
     ) AS query

Rationale

Analog zu selectWith().

lookup() - Liefere Datensatz

Synopsis

  $row|@vals = $db->lookup(@select,@opt);

Options

-new => $bool (Default: 0)

Liefere einen leeren Neu-Datensatz, wenn der Datensatz nicht gefunden wird.

-raw => $bool (Default: 0)

Liefere Datensatz in Array-Repräsentation

-rowClass => $class (Default: 'Quiq::Database::Row::Object')

Default Datensatz-Klasse. Im Falle von -raw=>1 ist 'Quiq::Database::Row::Array' der Default.

-sloppy => 0|1|2|3 (default: 0)
0

Es muss genau ein Datensatz getroffen werden.

1

Es darf 0 oder 1 Datensatz getroffen werden.

2

Es muss mindestens ein Datensatz getroffen werden.

3

Es dürfen beliebig viele Datensätze getroffen werden.

Wird kein Datensatz getroffen und ist dies erlaubt, wird undef geliefert. Wird mehr als ein Datensatz getroffen und ist dies erlaubt, wird der erste geliefert.

loadRow() - Lade Datensatz

Synopsis

  $row = $db->loadRow($table,@keyVal);

Description

Lade Datensatz mit WHERE-Bedingung @keyVal. Ist @keyVal leer oder einer der Werte leer, liefere einen Null-Datensatz.

Diese Methode ist nützlich, um ein Formular mit einem neuen oder existierenden Datensatz zu versorgen.

nullRow() - Liefere Null-Datensatz

Synopsis

  $row = $db->nullRow(@select,@opt);

Options

-raw => $bool (Default: 0)

Liefere Datensatz in Array-Repräsentation

-rowClass => $class (Default: 'Quiq::Database::Row::Object')

Default Datensatz-Klasse. Im Falle von -raw=>1 ist 'Quiq::Database::Row::Array' der Default.

Description

Liefere Null-Datensatz zu Select-Statement @select und der spezifizierten Klasse.

Anmerkung: Die Row-Instantiierung wird gecacht. Je Statement und Klasse wird beim ersten Aufruf eine Row instantiiert. Bei allen weiteren Aufrufen wird diese Row kopiert.

Example

  • Null-Datensatz einer Tabelle instantiieren

      $per = Quiq::Database::Connection->nullRow('person');

values() - Liefere Kolumnenwerte als Liste oder Hash

Synopsis

  @keyVal|%hash|$arr = $db->values(@select);
  $hash = $db->values(@select,-hash=>1);

Options

-hash => $bool (Default: 0)

Liefere Hashreferenz.

Description

Selektiere Kolumnenwerte und liefere sie als Liste oder Hash zurück. Im Skalarkontext liefere eine Referenz auf die Liste bzw. den Hash.

  • Die Select-Liste kann aus ein oder mehreren Kolumnen bestehen. Bei einer Kolumne wird die Liste der Werte der Kolumne geliefert. bei mehreren Kolumnen werden die Werte zu einer flachen Liste vereinigt. Bei zwei, vier, ... Kolumnen, kann das Resultat an einen Hash zugewiesen werden.

  • Soll die Liste nicht alle, sondern nur verschiedene Werte enthalten, wird DISTINCT selektiert.

  • Sollen NULL-Werte nicht berücksichtigt werden, wird der WHERE-Klausel eine entsprechende IS NOT NULL-Bedingung hinzugefügt.

  • Sollen die Werte sortiert geliefert werden, wird dem Statement eine ORDER BY Klausel hinzugefügt.

  • Im Skalarkontext wird ein Objekt der Klasse Quiq::Array oder der Klasse Quiq::Hash geliefert. Letzteres, wenn Option -hash=>1 angegeben ist.

Examples

Alle Werte einer Kolumne (sortiert):

  @arr = $db->values(
      -select => 'per_nachname',
      -from => 'person',
      -orderBy => 1,
  );

Nur verschiedene Werte (sortiert):

  @arr = $db->values(
      -select => 'per_nachname',
      -distinct => 1,
      -from => 'person',
      -orderBy => 1,
  );

Abbildung von Id auf Nachname:

  %hash = $db->values(
      -select => 'per_id','per_nachname',
      -from => 'person',
  );

Dasselbe, nur dass eine Referenz (Hash-Objekt) geliefert wird:

  $hash = $db->values(
      -select => 'per_id','per_nachname',
      -from => 'person',
      -hash => 1,
  );

Lookup-Hash für Nachname:

  $hash = $db->values(
      -select => 'per_nachname',1,
      -from => 'person',
      -hash => 1,
  );

Array mit Paaren:

  @arr = $db->values(
      -select => 'per_id','per_nachname',
      -from => 'person',
  );

Dasselbe, nur dass eine Referenz (Array-Objekt) geliefert wird:

  $arr = $db->values(
      -select => 'per_id','per_nachname',
      -from => 'person',
  );

Array mit Abfolge von Tripeln:

  @arr = $db->values(
      -select => 'per_id','per_nachname','per_vorname',
      -from => 'person',
  );

value() - Liefere Wert einer Kolumne eines Datensatzes

Synopsis

  $val = $db->value(@select,@opt);

Options

-sloppy => $bool (Default: 0)

Wirf keine Exception, wenn die Ergebnismenge leer ist, sondern undef.

-default => $val (Default: undef)

Wenn auf einen Wert ungleich undef gesetzt, wirf keine Exception, wenn die Ergebnismenge leer ist, sondern $val.

Description

Lies den ersten Datensatz der Ergebnismenge und liefere den Wert der ersten Kolumne zurück.

Anmerkungen

  • Die Select-Liste des Statements sollte sinnvollerweise aus einer Kolumne bestehen. Mehr als eine Kolumne ist zulässig, allerdings ist dies eine Verschwendung von Platz und Zeit, denn auch wenn mehrere Kolumnen angegeben sind, wird nur der Wert der ersten geliefert.

  • Ist die Ergebnismenge leer, wird eine Exception ausgelöst.

  • Es ist kein Fehler, wenn mehr als ein Datensatz getroffen wird. Es wird allerdings nur der erste Datensatz geliefert.

Insert Operations

insert() - Füge Datensatz zu Tabelle hinzu

Synopsis

  $cur = $db->insert($table,@opt,$row);
  $cur = $db->insert($table,@opt,@keyVal);
  $cur = $db->insert($table,@opt,\@keys,\@values);

Options

-sloppy => $bool (Default: 0)

Ignoriere Doubletten-Fehler.

Description

Füge Datensatz zu Tabelle $table hinzu und liefere das Resultat der Ausführung zurück.

insertRows() - Füge mehrere Datensätze zu Tabelle hinzu

Synopsis

  $cur = $db->insertRows($table,\@keys,
      [@vals1],
      [@vals2],
      ...
  );
  
  $cur = $db->insertRows($table,\@keys,
      @vals1,
      @vals2,
      ...
  );

Description

Füge mehrere Datensätze zu Tabelle $table hinzu. Die Datensätze haben die Kolumnen @keys und die Werte @vals. Die Methode liefert das Resultat der Ausführung (Cursor) zurück

Example

  • Datensätze als Arrays

      $db->insertRows('person',
          [qw/per_id per_vorname per_nachname per_geburtstag/],
          [qw/1 Frank Seitz 31.1.1961/],
          [qw/2 Hanno Seitz 7.4.2000/],
          [qw/3 Linus Seitz 11.11.2002/],
      );
  • Datensätze als Abfolge von Werten

      $db->insertRows('person',
          [qw/per_id per_vorname per_nachname per_geburtstag/],
          qw/1 Frank Seitz 31.1.1961/,
          qw/2 Hanno Seitz 7.4.2000/,
          qw/3 Linus Seitz 11.11.2002/,
      );

insertMulti() - Füge mehrere Datensätze zu Tabelle hinzu

Synopsis

  $cur = $db->insertMulti($table,\@keys,[
          [@vals1],
          [@vals2],
          ...
      ]
  );

Description

Füge mehrere Datensätze zu Tabelle $table hinzu. Die Datensätze haben die Kolumnen @keys und die Werte @valsI. Die Methode liefert das Resultat der Ausführung (Cursor) zurück. Im Unterschied zur Methode $db->insertRows() führt diese Methode ein einziges INSERT-Statement mit allen Daten aus, à la

  INSERT INTO person
      (per_id, per_vorname, per_nachname, per_geburtstag)
  VALUES
      ('1', 'Linus', 'Seitz', '2002-11-11'),
      ('2', 'Hanno', 'Seitz', '2000-04-07')
      ('3', 'Emily', 'Philippi', '1997-05-05')
      ...

Example

  $db->insertMulti('person',
      [qw/per_id per_vorname per_nachname per_geburtstag/],[
          [qw/1 Linus Seitz 2002-11-11/],
          [qw/2 Hanno Seitz 2000-04-07/],
          [qw/3 Emily Philippi 1997-05-05/],
      ]
  );

insertResultSet() - Füge Datensätze eines Resultset zu Tabelle hinzu

Synopsis

  $cur = $db->insertResultSet($table,$tab);

Update Operation

update() - Aktualisiere Datensätze

Synopsis

  $cur = $db->update($table,$row); [1]
  $cur = $db->update($table,$row,@where); [2]
  $cur = $db->update($table,@keyVal,-where,@where); # [3]

Description

[1] Aktualisiere Datensatz $row und liefere das Resultat der Ausführung zurück. Als Where-Bedingung wird der Name/Wert der ersten Kolumne von Tabelle $table genommen.

[2] Wie [1], nur dass die Where-Bedingung explizit angegeben ist.

[2] Aktualisiere 0, einen oder mehrere Datensatze in Tabelle $table und liefere das Resultat der Ausführung zurück.

Delete Operation

delete() - Lösche Datensatz bzw. Datensätze aus Tabelle

Synopsis

  $cur = $db->delete($table,$row,@where);
  $cur = $db->delete($table,@where);

Description

Lösche Datensatz bzw. Datensätze aus Tabelle $table und liefere das Resultat der Ausführung zurück.

Schemas

schemaExists() - Prüfe, ob Schema existiert

Synopsis

  $bool = $db->schemaExists($schema);

Description

Liefere wahr, wenn Schema $schema existiert, sonst falsch.

schemas() - Liste der Schemata

Synopsis

  @schemas | $schemaA = $db->schemas(@opt);
  %schemas | $schemaH = $db->schemas(-hash=>1,@opt);

Options

-cache => $bool (Default: 1)

Cache die Liste.

-hash => $bool (Default: 0)

Liefere einen Hash mit den Schemanamen als Schlüssel und 1 als Wert.

Returns

@schemas, $schemaA

Liste der Schemanamen (Liste von Strings) oder eine Referenz auf die Liste.

%schemas, $schemaH

Hash der Schemanamen oder eine Referenz auf den Hash. Der Hashwert ist 1.

Description

Ermittele die Schemata der Datenbank und liefere die Liste oder den Hash der Namen zurück.

Tables

createTable() - Erzeuge Tabelle

Synopsis

  $cur = $db->createTable($table,
      [$colName,@colOpts],
      ...
      @opt,
  );

Options

-replace => $bool (Default: 0)

Erzeuge Tabelle neu, falls sie bereits existiert.

-sloppy => $bool (Default: 0)

Erzeuge Tabelle nicht, falls sie bereits existiert.

Description

Erzeuge Tabelle $table auf der Datenbank.

recreateTable() - Erzeuge existierende Tabelle neu

Synopsis

  $cur = $db->recreateTable($table,
      [$colName,@colOpts],
      ...
      @opt,
  );

Arguments

$name

(String) Name der Tabelle, die neu erzeugt wird.

Options

-mapColumns => \%hash

Abbildung zwischen den Kolumnennamen der alten und der neuen Tabelle. Der Schlüssel des Hash ist der alte Name, der Wert des Hash der neue Name. Es müssen nur die Kolumennamen angegeben werden, die nicht übereinstimmen.

Returns

(Object) Cursor des INSERT-Statements, das die Daten von der alten in die neue Tabelle kopiert hat.

Description

Erzeuge die auf der Datenbank bereits existierende Tabelle $table neu.

Ablauf:

  1. Erzeuge die Tabelle $table unter dem Namen <TABLE>_new

  2. Kopiere die Daten aus der originalen in die neue Tabelle (unter Berücksichtigung geänderter Kolumnennamen, siehe Option -mapColumns. Kolumen, nicht mehr existieren, entfallen.)

  3. Lösche die Orignaltabelle

  4. Benenne die neue Tabelle in die Originaltabelle $table um

copyData() - Kopiere Tabellendaten von Quelldatenbank in Zieldatenbank

Synopsis

  $n = $destDb->copyData($srcDb,$table,%options);

Arguments

$srcDb

Verbindung zur Quelldatenbank

$name

(String) Name der Zieltabelle

Options

-chunkSize => $n (Default: 100)

Kopiere die Datensätze in Chunks der Größe $n.

-srcTable => $srcTable (Default: $table)

Name der Tabelle in der Quelldatenbank, wenn er vom Namen der Zieltabelle abweicht.

-mapColumns => \%hash

Abbildung zwischen den Kolumnennamen der Quell- und der Zieltabelle. Der Schlüssel des Hash ist der Name in der Quelltabelle, der Wert des Hash der Name in der Zieltabelle. Es müssen nur die Kolumennamen angegeben werden, die nicht übereinstimmen.

Returns

(Integer) Anzahl der kopierten Datensätze.

Description

Kopiere die Daten der Tabelle $table aus der Quelldatenbank $srcDb in die Zieldatenbank $destDb. Weicht der Tabellenname ab, kann diese Abweichung mit der Option -srcTable behandelt werden. Weichen Kolumnennamen ab, kann dies mit der Option -mapColumns behandelt werden.

dropTable() - Lösche Tabelle

Synopsis

  $cur = $db->dropTable($table);

Description

Lösche die Tabelle $table (name mit oder ohne Schemaanteil) von der Datenbank $db und liefere das Resultat-Objekt der Statementausführung zurück.

Es wird vorab geprüft, ob die Tabelle existiert. Ist dies nicht der Fall, wird keine Löschung versucht und ein Null-Cursor zurückgeliefert.

Wird die Tabelle erfolgreich gedroppt, führt die Methode ein COMMIT durch. Schlägt dies fehl, führt sie ein ROLLBACK durch. Dies ist für PostgreSQL und SQLite notwendig.

tableExists() - Prüfe, ob Tabelle existiert

Synopsis

  $bool = $db->tableExists($table);

Description

Prüfe, ob Tabelle $table existiert. Wenn ja, liefere "wahr", sonst "falsch".

renameTable() - Benenne Tabelle um

Synopsis

  $cur = $sql->renameTable($oldName,$newName);

analyzeTable() - Analysiere Tabelle

Synopsis

  $db->analyzeTable($table);

Description

Analysiere Tabelle $table und liefere einen Cursor zurück.

addCheckConstraint() - Füge CHECK Constraint zu Tabelle hinzu

Synopsis

  $cur = $db->addCheckConstraint($tableName,$expr,@opt);

Description

Siehe Quiq::Sql::addCheckConstraint()

addForeignKeyConstraint() - Füge FOREIGN KEY Constraint zu Tabelle hinzu

Synopsis

  $cur = $db->addForeignKeyConstraint($tableName,\@tableCols,
      $refTableName,@opt);

Description

Siehe Quiq::Sql::addForeignKeyConstraint()

countRows() - Zähle die Anzahl der Datensätze in der Tabelle

Synopsis

  $n = $db->countRows($tableName);

tableDiff() - Daten-Differenzen zwischen zwei Tabellen

Synopsis

  $tab = $db->tableDiff($table1,$table2,@opt);

Arguments

$table1

Tabellenname, mit oder ohne Schema-Präfix.

$table2

Tabellenname, mit oder ohne Schema-Präfix.

Options

Im folgenden ist @titles ein Array von Kolumnennamen und $titles eine kommaseparierte Liste von Kolumnennamen.

-columns => \@titles | $titles (Default: Kolumnen Tabelle 1)

Kolumnen, die verglichen werden.

-ignoreColumns => \@titles | $titles

Kolumnen, die ignoriert werden. Diese Option ist nützlich, wenn alle Kolumnen verglichen werden sollen, bis auf die mit dieser Option genannten.

-limit => $n (Default: 10)

Begrenze die Größe der beiden Differenzmengen (s.u.) auf jeweils N Zeilen. D.h. es werden maximal 2 * N Zeilen geliefert. Darüber hinausgehende Differenzen werden nicht berücksichtigt. Limit 0 bedeutet, es gibt keine Begrenzung.

-sortColumns => \@titles | $titles (Default: Kolumnen)

Kolumnen, nach denen die Gesamt-Differenzliste sortiert wird.

Description

Die Methode untersucht zwei strukturell identische Tabellen hinsichtlich etwaig vorhandener Daten-Differenzen. Sie tut dies mittels SQL und kann dadurch auch große Datenmengen bewältigen. Der Vergleich geschieht durch Bildung zweier Differenzmengen:

  -- Alle Zeilen in Tabelle 1, die nicht in Tabelle 2 vorkommen
  
  SELECT
      <COLUMNS1>
  FROM
      <TABLE1>
  EXCEPT
  SELECT
      <COLUMNS2>
  FROM
      <TABLE2>
  ORDER BY
      <COLUMNS1>

und

  -- Alle Zeilen in Tabelle 2, die nicht in Tabelle 1 vorkommen
  
  SELECT
      <COLUMNS2>
  FROM
      <TABLE2>
  EXCEPT
  SELECT
      <COLUMNS1>
  FROM
      <TABLE1>
  ORDER BY
      <COLUMNS2>

Sind beide Differenzmengen leer, sind die Tabellen identisch.

Die beiden Differenzmengen werden in einer Ergebnismenge zusammengefasst und als ResultSet-Objekt zurückgeliefert. Die Herkunft einer Row wird durch das Zeilenattribut sourceTable angezeigt. Tabelle 1 wird mit 'A' bezeichnet, Tabelle 2 mit 'B'.

Example

Vergleich der Tabelle q68t999 in den Schemata xv882js und xv882js_test_01 über das Programm quiq-db-table-diff, das ein Frontend zur Methode tableDiff() darstellt:

  $ quiq-db-table-diff dbi#postgresql:dsstest%xv882js:*@tdca.ruv.de:5432 xv882js.q68t999 xv882js_test_01.q68t999
   1 sourceTable
   2 pgmname
   3 tabname
   4 jobname
   5 anz_ins
   6 anz_upd
   7 anz_del
   8 upd_dat
   9 status
  10 runtime
  
  1   2                 3         4   5          6   7    8                            9   10
  | A | xv882js_160538  | q68t340 |   | 37806420 | 0 | -1 | 2019-04-25 09:30:12.034297 |   | 2019-04-25 09:29:51 |
  | B | xv882js_2285224 | q68t340 |   | 37806420 | 0 | -1 | 2019-04-25 09:33:33.987502 |   | 2019-04-25 09:33:11 |
  
  2 rows

doublets() - Dubletten in einer Tabelle

Synopsis

  $tab = $db->doublets($table,@opt);

Arguments

$table

Tabellenname, mit oder ohne Schema-Präfix.

Options

Im folgenden ist @titles ein Array von Kolumnennamen und $titles eine kommaseparierte Liste von Kolumnennamen.

-columns => \@titles | $titles (Default: Alle Kolumnen der Tabelle)

Kolumnen, die auf Dubletten hin untersucht werden.

-ignoreColumns => \@titles | $titles

Kolumnen, die ignoriert werden. Diese Option ist nützlich, wenn alle Kolumnen betrachtet werden sollen, bis auf die mit dieser Option genannten.

-limit => $n (Default: 10)

Begrenze die Anzahl der gemeldeten Dubletten.

-sortColumns => \@titles | $titles (Default: Kolumnen)

Kolumnen, nach denen die Gesamt-Differenzliste sortiert wird.

Returns

Ergebnismengen-Objekt (Quiq::ResultSet::Object)

Description

Suche Dubletten in der Tabelle $table und liefere ein Ergebnisobjekt mit den Treffern zurück.

Example

  $  perl -MQuiq::Database::Connection -E 'print Quiq::Database::Connection\
       ->new("dbi#postgresql:dsstest%xv882js:*\@tdca.ruv.de:5432")\
       ->doublets("dss_meta.cpm_load_objects",-columns=>"load_object,\
       target_object",-limit=>10)->asTable'

Columns

columnExists() - Prüfe, ob Kolumne existiert

Synopsis

  $cur = $db->columnExists($table,$column);

Description

Prüfe, ob Kolumne existiert. Wenn ja, liefere "wahr", sonst "falsch".

addColumn() - Füge Kolumne zu Tabelle hinzu

Synopsis

  $cur = $db->addColumn($table,$column,@colDef,@opt);

Options

-sloppy => $bool (Default: 0)

Wirf keine Exception, wenn die Kolumne bereits existiert, sondern liefere undef.

Example

  $cur = $db->addColumn('person','mag_eis',
      type => 'STRING(1)',
      notNull => 1,
      default => 1,
  );

dropColumn() - Entferne Kolumne aus Tabelle

Synopsis

  $cur = $db->dropColumn($table,$column);

Description

Entferne Kolumne $column aus Tabelle $table und liefere das Resultat der Statement-Ausführung zurück.

Es ist kein Fehler, wenn die Kolumne nicht existiert. In dem Fall wird undef geliefert.

modifyColumn() - Modifiziere Kolumne

Synopsis

  $cur = $db->modifyColumn($table,$column,$property=>$value);

Description

Modifiziere Kolumne $column in Tabelle $table und liefere das Resultat der Statement-Ausführung zurück.

renameColumn() - Benenne Kolumne um

Synopsis

  $cur = $db->renameColumn($table,$oldName,$newName;

Description

Benenne Tabelle $table die Kolumne $oldName in $newName um und liefere das Resultat der Statement-Ausführung zurück.

distinctValues() - Liefere die Anzahl der unterschiedlichen Werte

Synopsis

  $n = $db->distinctValues($table,$column);

minValue() - Liefere den kleinsten Kolumnenwert

Synopsis

  $val = $db->minValue($table,$column);

maxValue() - Liefere den größten Kolumnenwert

Synopsis

  $val = $db->maxValue($table,$column);

countDistinctMinMax() - Liefere Count/Count Distinct/Min/Max

Synopsis

  ($count,$distinctCount,$min,$max) = $db->countDistinctMinMax($table,$column);

Description

Die Methode liefert Information über den Inhalt einer Tabellenkolumne. Sie ist für das Reverse Engineering einer unbekannte Datenbanktabelle nützlich.

Indexes

indexExists() - Prüfe, ob Index existiert

Synopsis

  $bool = $db->indexExists($table,\@colNames);

Description

Prüfe, ob Index existiert. Wenn ja, liefere "wahr", sonst "falsch".

createIndex() - Erzeuge Index

Synopsis

  $cur = $db->createIndex($table,\@colNames,@opt);

Options

-indexName => $str (Default: <TABLE>_ix_<COLUMNS>)

Name des Index.

-reCreate => $bool (Default: 0)

Erzeuge Index neu, falls er bereits existiert.

-tableSpace => $tableSpaceName (Default: keiner)

Name des Tablespace, in dem der Index erzeugt wird (Oracle und PostgreSQL).

-unique => $bool (Default: 0)

Statement für Unique Index.

Description

Erzeuge Index für Tabelle $table und Kolumnen @colNames auf der Datenbank.

createUniqueIndex() - Erzeuge Unique Index

Synopsis

  $cur = $db->createUniqueIndex($table,\@colNames,@opt);

Options

Siehe $db->createIndex()

Description

Erzeuge Unique Index für Tabelle $table und Kolumnen @colNames auf der Datenbank.

dropIndex() - Droppe Index

Synopsis

  $cur = $db->dropIndex($table,\@colNames);

Sequences

createSequence() - Erzeuge Sequenz

Synopsis

  $db->createSequence($name,@opt);

Options

-reCreate => $bool (Default: 0)

Droppe Sequenz, falls sie bereits existiert.

-startWith => $n (Default: 1)

Die Sequenz beginnt mit Startwert $n.

Description

Erzeuge Sequenz $name auf Datenbank $db. Die Methode liefert keinen Wert zurück.

Unter Oracle und PostgreSQL, die das Konzept der Sequenz haben, wird eine normale Sequenz auf der Datenbank erzeugt.

Unter MySQL und SQLite, die das Konzept der Sequenz nicht haben, wird eine Tabelle mit Autoinkrement-Kolumne zur Simulation einer Sequenz erzeugt.

dropSequence() - Droppe Sequenz

Synopsis

  $cur = $db->dropSequence($name);

Description

Droppe Sequenz $name und liefere das Resultat der Statementausführung zurück.

setSequence() - Setze Sequenz auf neuen Startwert

Synopsis

  $db->setSequence($sequence,$n);

Description

Setze Sequenz $sequence auf Wert $n. Die Methode liefert keinen Wert zurück.

nextValue() - Liefere nächsten Sequenzwert

Synopsis

  $n = $db->nextValue($sequence);

Description

Ermittele den nächsten Sequenzwert der Sequenz $sequence und liefere diesen zurück.

Unter Oracle und PostgreSQL wird die betreffende Sequenz befragt.

Unter MySQL und SQLite wird ein leerer Datensatz in die Sequenz-Tabelle eingefügt und dessen automatisch generierter Primärschlüsselwert ermittelt. Um die Sequenz-Tabelle nicht beliebig anwachsen zu lassen, wird die Tabelle alle 100 Werte (d.h. wenn $n % 100 == 0) bereinigt: alle Datensätze mit einem kleineren Wert als $n werden gelöscht.

Views

createView() - Erzeuge View

Synopsis

  $cur = $db->createView($viewName,$selectStmt,@opt);

Options

-reCreate => $bool (Default: 0)

Erzeuge View neu, falls sie bereits existiert.

dropView() - Lösche View

Synopsis

  $cur = $db->dropView($viewName);

Description

Lösche die View $viewName von der Datenbank $db und liefere das Resultat-Objekt der Statementausführung zurück.

Es wird vorab geprüft, ob die View existiert. Ist dies nicht der Fall, wird nicht zu löschen versucht und ein Null-Cursor zurückgeliefert.

Wird die View erfolgreich gedroppt, führt die Methode ein COMMIT durch. Schlägt dies fehl, führt sie ein ROLLBACK durch. Dies ist für PostgreSQL und SQLite notwendig.

viewExists() - Prüfe, ob View existiert

Synopsis

  $bool = $db->viewExists($viewName);

Description

Prüfe, ob View existiert. Wenn ja, liefere "wahr", sonst "falsch".

Trigger

createTrigger() - Erzeuge Trigger

Synopsis

  $cur = $db->createTrigger($table,$name,$when,$event,$level,$body,@opt);
  $cur = $db->createTrigger($table,$name,$when,$event,$level,
      $dbms => $body,
      ...,
      @opt
  );

Options

-replace => $bool (Default: 0)

Ersetze den Trigger, falls ein solcher existiert.

Returns

Cursor

Description

Erzeuge einen Trigger mit Name $name für Tabelle $table und Zeitpunkt $when (BEFORE oder AFTER), der bei Ereignis $event (INSERT, UPDATE oder DELETE) auf Ebene $level (ROW oder STATEMENT) feuert und die Rumpf/Anweisungsfolge $body ausführt.

Es kann ein einzelner Rumpf angegeben werden, wenn die Applikation auf einem bestimmten RDBMS läuft. Oder es können, um portabel programmieren zu können, unterschiedliche Prozedur-Rümpfe für verschiedene RDBMSe definiert werden:

  ...
  Oracle => "
  <oracle_body>
  ",
  PostgreSQL => "
  <postgresql_body>
  ",
  ...

Die Methode wählt dann die zur Datenbank $db passende Rumpf-Definition aus.

Example

Erzeuge unterschiedlichen Triggercode für Oracle und PostgreSQL:

  $db->createTrigger('mytab','mytrig','before','insert|update','row',
      Oracle => "
      BEGIN
          :new.c := 'a';
      END
      ",
      PostgreSQL => "
      BEGIN
          NEW.c = 'a';
          RETURN NEW;
      END;
      ",
  );

Für Oracle wird ein Trigger mit Rumpf erzeugt:

  CREATE TRIGGER mytrig
  BEFORE INSERT OR UPDATE ON mytab
  FOR EACH ROW
  BEGIN
      :new.c := 'a';
  END;

Für PostgreSQL wird zunächst eine Funktion set_c_proc (Triggername plus "_proc") erzeugt, welche die Triggerfunktionalität implementiert:

  CREATE FUNCTION mytrig_proc()
  RETURNS trigger
  AS $SQL$
  BEGIN
      NEW.c = 'a';
      RETURN NEW;
  END;
  $SQL$ LANGUAGE plpgsql

Dann wird der Trigger definiert, der diese Funktion aufruft:

  CREATE TRIGGER set_c
  BEFORE INSERT OR UPDATE ON mytab
  FOR EACH ROW
  EXECUTE PROCEDURE mytrig_proc()

dropTrigger() - Entferne Trigger

Synopsis

  $cur = $db->dropTrigger($name);

triggerExists() - Prüfe, ob Trigger existiert

Synopsis

  $bool = $db->triggerExists($name);

Spezielle Operationen

diff() - Ermittele Datendifferenzen

Synopsis

  $tab|@rows|$cur = $db->diff(@args);

Options

Wie $db->select()

updateNToM() - Verwalte N-zu-M Relation

Synopsis

  $db->updateNToM($masterId,\@values1,\@values2,
      a => $a,
      b => $b,
      b_pk => $b_pk,
      b_col => $b_col,
      a_b => $a_b,
      a_b_fk_a => $a_b_fk_a,
      a_b_fk_b => $a_b_fk_b,
  );

Arguments

$masterId

Primärschlüssel-Wert des Master-Datensatzes.

@values1

Liste der dem Master-Datensatz zugeordneten B-Werte vor der Änderung.

@values2

Dito. nach der Änderung.

a => $a,

Name der Master-Tabelle.

b => $b,

Name der Slave-Tabelle.

b_pk => $b_pk,

Name der Primärschlüsselkolumne der Slave-Tabelle.

b_col => $b_col,

Name der Wert-Kolumne der Slave-Tabelle.

a_b => $a_b,

Name der Relations-Tabelle.

a_b_fk_a => $a_b_fk_a,

Name der Fremdschlüsselkolumne in der Relationstabelle auf die Master-Tabelle.

a_b_fk_b => $a_b_fk_b,

Name der Fremdschlüsselkolumne in der Relationstabelle auf die Slave-Tabelle.

Description

Folgendes Datenmodell:

  A <-- A_B --> B

Beispiel: A = Tabelle mit Texten, B = Tabelle mit Schlagworten, A_B = Relationstabelle für die Zuordnung von Schlagworten zu Texten.

Die Methode sorgt dafür, daß für einen Datensatz in A mit der Id $masterId eine Änderung der Schlagwortliste von @values1 nach @values2 die Relationsdatensätze in A_B gemäß dieser Änderung aktualisiert werden. Neue Schlagworte in @values2 werden zu B hinzugefügt, Schlagworte, die wegfallen und nicht von anderen Texten referenziert werden, werden entfernt.

Example

Siehe KnowledgeBase::System->edit()

DETAILS

Zeitmessung

Im Zuge der Ausführung eines SQL-Statement werden drei Zeiten ermittelt:

  1. Der Startzeitpunkt der Ausführung (Aufruf von sql)

  2. Die Dauer der Statementausführung

  3. Die Zeit, die seit Start des Statements vergangen ist

Diese Zeiten können vom Cursor abgefragt werden mittels:

  $cur->startTime;
  $cur->execTime;
  $cur->time;

Parallele Datenbankverbindung

Eine parallele Verbindung zur gleichen Datenbank unter dem gleichen User kann mittels

  $db2 = $db->new;

aufgebaut werden. Dies kann nützlich sein, um einen nebenläufigen Transkationsrahmen zu eröffnen.

Null-Cursor

Wird ein Cursor benötigt, ohne dass ein Statement ausgeführt werden soll, kann ein Null-Cursor erzeugt werden:

  $cur = $db->sql;

Statement-Generierung

Die Methode sql() liefert das SQL-Objekt der Datenbankverbindung. Dies ist ein Objekt der Klasse Quiq::Sql, das beim Verbindungsaufbau passend zum DBMS instantiiert wurde.

Alle SQL-Generierungsmethoden der Klasse Quiq::Sql können über diese Methode aufgerufen werden, zum Beispiel:

  $stmt = $db->stmt->createTable('person',
      ['per_id',type=>'INTEGER',primaryKey=>1],
      ['per_vorname',type=>'STRING(20)'],
      ['per_nachname',type=>'STRING(20)'],
  );

Statement-Generierung plus -Ausführung

Die meisten Statements der Klasse Quiq::Sql können auch direkt ausgeführt werden, ohne dass das Statement zuvor generiert werden muss, zum Beispiel:

  $db->createTable('person',
      ['per_id',type=>'INTEGER',primaryKey=>1],
      ['per_vorname',type=>'STRING(20)'],
      ['per_nachname',type=>'STRING(20)'],
  );

Die direkte Ausführung ist einer getrennten Generierung und Ausführung vorzuziehen, da die Quiq::Database::Connection-Methoden bei der Ausführung teilweise DBMS-abhängige Sonderbehandlungen vornehmen.

Erweiterte Statement-Generierung

Anstelle der Default Sql-Klasse Quiq::Sql kann beim Verbindungsaufbau eine anwendungspezifische Klasse vereinbart werden:

  package MyApp::Sql;
  use base qw/Quiq::Sql/;
  
  ...
  
  package main;
  
  $db = Quiq::Database::Connection->new(...,-sqlClass=>'MyApp::Sql');

Prepare/Bind

DML-Statements (SELECT, INSERT, UPDATE, DELETE) können mit Platzhaltern versehen werden. Das Statement wird dann nicht ausgeführt, sondern ein Bind-Cursor geliefert.

Beispiel mit INSERT

  my $bindCur = $db->insert('person',
      per_id => \'?',
      per_vorname => \'?',
      per_nachname => \'?',
  );
  
  $bindCur->bind(
      1,'Rudi','Ratlos',
      2,'Elli','Pirelli',
      3,'Erika','Mustermann',
  );

Beispiel mit SELECT

  my $bindCur = $db->select(
      -from => 'person',
      -where => 'per_nachname = ?',
  );
  
  my $cur = $bindCur->bind('Mustermann');
  while (my $row = $cur->fetch) {
      print $row->asString,"\n";
  }
  $cur->close;

Lookup von Datensätzen

Selektion eines eindeutigen Objekts

  $row = $db->lookup('person',-where,per_id=>4711);

Es ist ein Fehler, wenn

  • kein Datensatz existiert

  • mehr als ein Datensatz existiert

Soll die Methode undef liefern, wenn kein Datensatz existiert, wird -sloppy=>1 angegeben:

  $row = $db->lookup('person',-sloppy=>1,-where,per_id=>4711);

Soll ein leerer Datensatz geliefert werden, der gesuchte Datensatz nicht gefunden wird, wird -new=>1 angegeben:

  $row = $db->lookup('person',-new=>1,-where,per_id=>4711);

Der Aufruf liefert also immer einen Datensatz. Mit der Methode rowStatus() kann geprüft werden, ob der Datensatz selektiert oder neu erzeugt wurde:

  if ($row->rowStatus eq 'I') {
      # initialisieren
  
      $row->set(
          per_id => $db->nextValue('id');
          per_vorname => 'Erika',
          per_namchname => 'Mustermann',
      );
  
      # speichern
      $db->insert('person',$row);
  }

Einfügen von Datensätzen

Ad hoc

  my $per_id = $db->nextValue('id');
  $db->insert('person',
      per_id => $per_id,
      per_vorname => 'Rudi',
      per_nachname => 'Ratlos',
  );
  my $per = $db->lookup('person',-where,per_id=>$per_id);

Der Datensatz wird durch Aufzählung der Kolumnen/Wert-Paare zur Tabelle hinzugefügt. Um das Objekt im Programm zu haben, muss der Datensatz selektiert werden.

Mittels anonymem Row-Objekt

  my $per = $db->nullRow('person');
  $per->set(
      per_id => $db->nextValue('id'),
      per_vorname => 'Rudi',
      per_nachname => 'Ratlos',
  );
  $db->insert('person',$row);

Mittels Objekt (noch nicht implementiert)

  my $per = Person->new($db,
      per_id => $db->nextValue('id'),
      per_vorname => 'Rudi',
      per_nachname => 'Ratlos',
  );
  $per->insert($db);

Default-Schema

Per UDL kann ein Default-Schema definiert werden:

  dbi#DBMS:DB%USER:PASSW;schema=SCHEMA

Namen von Datenbank-Objekten, die ohne Schema-Präfix angegeben werden, werden auf dieses Schema bezogen. Auf diese Weise ist es leicht möglich, eine Anwendung auf verschiedenen Schemata der gleichen Datenbank laufen zu lassen. Dies ist vor allem bei Oracle nützlich, dessen Instanzen einen großen Overhead haben.

Bei SQLite ist die Semantik eine leicht andere: Hier ist es nicht das Default-Schema, sondern es darf der Schema-Präfix SCHEMA verwendet werden.

BLOB Datentyp

  • Die maximale Größe eines BLOB/TEXT-Werts muss im Falle von Oracle eingestellt werden. Dies geschieht durch Aufruf von maxBlobSize():

      $db->maxBlobSize(500*1024); # 0,5 MB

    Der Defaultwert ist 1024*1024 Bytes (1MB).

Tabelle erzeugen

  $db->createTable('person',
      ['per_id',type=>'INTEGER',primaryKey=>1],
      ['per_vorname',type=>'STRING(20)'],
      ['per_nachname',type=>'STRING(20)'],
      ['per_foto',type=>'BLOB'],
  );

Daten speichern

  $cur = $db->insert('person',
      per_id => \'?',
      per_vorname => \'?',
      per_nachname => \'?',
      per_foto => \'?',
  );
  
  # BLOB-Kolumne bekannt machen, damit die Schnittstelle
  # die notwendigen Sonderbehandlungen für diesen Datentyp
  # durchführen kann. Dies ist im Falle von Oracle und PostgreSQL
  # nötig, da diese die Daten speziell kodieren. Bei SQLite und MySQL
  # ist das nicht erforderlich. Der Aufruf von bindTypes() sollte aus
  # Portabilitätsgründen aber immer gemacht werden.
  
  $cur->bindTypes(undef,undef,undef,'BLOB');
  
  my $foto = Quiq::Path->read('/home/pirelli/Picture/elli.jpg');
  $cur->bind(1,'Elli','Pirelli',$foto);

Daten selektieren

  $per = $db->lookup('person',-where,per_id=>1);

TEXT-Datentyp

Wie BLOB-Datentyp, aber als Bind-Typ TXET angeben:

  $cur->bindTypes(undef,undef,undef,'TEXT');

Auch hier ist dies wegen Oracle erforderlich.

UTF-8

Beim Verbindungsaufbau kann angegeben werden, ob das Perl-Programm UTF-8 Encoding verwendet:

  $db = Quiq::Database::Connection->new($udl,-utf8=>1);

Die Option sorgt dafür, dass Zeichenketten-Daten (STRING, TEXT) als UTF-8 Zeichenketten auf der Datenbank gespeichert werden und umgekehrt als UTF-8 Zeichenketten geliefert werden.

Existierende Handle nutzen

Existiert eine Lowlevel-Handle bereits, kann sie mit der Option -handle in das Datenbankobjekt eingesetzt werden.

Beispiel: Eine DBI MySQL-Handle $dbh wird als Lowlevel-Handle verwendet,

  UDL braucht nur die
  
     $db = Quiq::Database::Connection->new('dbi#mysql',-handle=>$dbh);

Zugriff auf MS Access Datenbank

Unter Unix/Linux ist ein lesender Zugriff auf MS Access Datenbanken mittels des freien Open Source Package mtools möglich. Es enthält neben verschiedenen Programme auch einen ODBC-Treiber, der genutzt werden kann, um von Perl aus auf eine Access-Datenbank zuzugreifen.

Installation (Redhat)

ODBC-Treiber für MS-Access

mtools: http://mdbtools.sourceforge.net/

  # yum install mdbtools

ODBC Driver Manager

unixODBC: http://http://www.unixodbc.org/

  # yum install unixODBC

Perl DBI-Treiber für ODBC

DBD::ODBC: https://metacpan.org/pod/DBD::ODBC

  # cpanm DBD::ODBC

Konfiguration

ODBC-Treiber (aus den mtools) definieren:

  # vi /etc/odbcinst.ini
  [MDBTools]
  Description = MDB Tools ODBC
  Driver      = libmdbodbc.so
  FileUsage   = 1

Datenquelle definieren:

  # vi /etc/odbc.ini
  [test]
  Description = Access Test-Datenbank
  Driver      = MDB Tools ODBC
  Database    = /path/to/file.mdb

Perl-Programm

Von Perl aus auf die Access-Datenbank zugreifen:

  my $udl = 'dbi#access:test';
  my $db = Quiq::Database::Connection->new($udl,-utf8=>1);
  
  my $stmt = 'select * from tdruckdaten';
  my $tab = $db->select($stmt);
  print $tab->asTable;

VERSION

1.208

AUTHOR

Frank Seitz, http://fseitz.de/

COPYRIGHT

Copyright (C) 2023 Frank Seitz

LICENSE

This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself.