Prty::Database::Connection - Verbindung zu einer Relationalen Datenbank
Prty::Hash
Ein Objekt der Klasse repräsentiert eine Verbindung zu einer Relationalen Datenbank.
$db = $class->new(@opt); $db = $class->new($udl,@opt); $db = $class->new($udlObj,@opt); $db2 = $db->new(@opt);
connect()
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.
Bereits aufgebaute Low-Level Datenbankverbindung zuweisen.
Logging von SQL-Statements.
Logdatei. Wenn nicht angegeben oder '-' wird auf STDOUT gelogged.
Name der Sql-Klasse zur Statementgenerierung.
Definiere das clientseitige Character Encoding als UTF-8.
$db = $class->newFromSbit($db);
$db->disconnect; $db->disconnect($commit);
destroy()
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.
$bool = $class->dbExists($udl);
Prüfe, ob Verbindung zur Datenbank $udl möglich ist. Liefere "wahr", wenn dies der Fall ist, andernfalls "falsch".
$n = $db->maxBlobSize; $n = $db->maxBlobSize($n);
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.
$bool = $db->strict; $bool = $db->strict($bool);
Bei eingeschaltetem Strict-Modus wird eine Exception
my $db = Prty::Database::Connection->new('dbi#mysql', -handle=>$main::dbh, ); ... $db->strict(1); # bei Datenbank-Fehler wird Exception geworfen $db->strict(0)
$sqlObj = $db->stmt;
sqlEngine()
Liefere das Sql-Objekt der Datenbankverbindung. Mit dem Sql-Objekt lassen sich SQL-Statements generieren, z.B.
$stmt = $db->stmt->dropTable($table);
$udlObj = $db->udl;
Liefere das Udl-Objekt der Datenbankverbindung. Das Udl-Objekt hält Information über die Datenbankverbindung, z.B.
$user = $db->udl->user;
$time = $cur->startTime;
$time = $cur->time;
Die folgenden Methoden testen auf das DBMS. Sie werden angewendet, wenn DBMS-spezifische Unterscheidungen vorgenommen werden müssen.
$dbms = $db->dbms;
($oracle,$postgresql,$sqlite,$mysql) = $db->dbmsTestVector;
$bool = $db->isOracle;
Liefere "wahr", wenn die Datenbank eine Oracle-Datenbank ist, sonst "falsch".
$bool = $db->isPostgreSQL;
Liefere "wahr", wenn die Datenbank eine PostgreSQL-Datenbank ist, sonst "falsch".
$bool = $db->isSQLite;
Liefere "wahr", wenn die Datenbank eine SQLite-Datenbank ist, sonst "falsch".
$bool = $db->isMySQL;
Liefere "wahr", wenn die Datenbank eine MySQL-Datenbank ist, sonst "falsch".
$rowClass = $this->defaultRowClass($raw);
Liefere den Namen der Default-Rowklasse:
Prty::Database::Row::Object ($raw ist "falsch") Prty::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.
Alle Statements einer Session oder ein gewisser Abschnitt kann gelogged werden.
Für die gesamte Session:
$db = Prty::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;
$bool = $db->isLog;
$db->openLog;
$db->writeLog(@str);
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.
$db->msgToLog($msg);
printLog()
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.
$db->stmtToLog($stmt);
Schreibe SQL Statement $stmt ins SQL-Log. Die Methode liefert keinen Wert zurück.
<LogMsgSeparator> <stmt>
=== <stmt>
$db->timeToLog($time);
Schreibe Ausführungszeit $time ins SQL-Log. Die Methode liefert keinen Wert zurück.
Der Logfileeintrag hat per Default folgenden Aufbau:
/* <time> */
$db->closeLog;
$db->startProgressLog($n);
$db->printProgressLog($msg);
Schreibe Fortschrittsmeldung $msg ins SQL-Log. Die Methode liefert keinen Wert zurück.
<LogMsgPrefix> <msg>
# <msg>
Ist die Meldung mehrzeilig, wird sie einzeilig gemacht, indem NEWLINE durch SPACE ersetzt wird.
$db->endProgressLog($msg);
$db->exportTable($table,$file);
Exportiere die Daten der Tabelle $table in Datei $file.
$db->importTable($table,$file);
Importiere die Daten aus Datei $file in Tabelle $table.
$db->lockTable($table);
$cur = $db->sql($stmt,@opt);
Führe SQL-Statement $stmt über Datenbankverbindung $db aus, instantiiere ein Resultat-Objekt (Cursor), und liefere eine Referenz auf dieses Objekt zurück.
Fetche Datensätze in Chunks von $n Sätzen. Diese Option hat aktuell nur bei PostgreSQL und -fetchMode 1 oder 2 eine Bedeutung.
Der Parameter hat nur im Falle PostgreSQL eine Auswirkung. Siehe auch Abschnitt "SELECT mit PostgreSQL".
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.
Die Datensätze werden in Chunks von -chunkSize Sätzen gefetcht. Dies ist der Default-Modus.
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.
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.
Schreibe SQL-Statement und Ausführungszeit nach STDOUT.
Fetche die Datensätze als einfache Arrays statt als komplexe Row-Objekte. Als Default-Rowklasse verwende Prty::Database::Row::Array statt Prty::Database::Row::Object (der Parameter -rowClass überschreibt diesen Default).
Name der Datensatzklasse, auf die die Datensätze der Ergebnismenge geblesst werden.
Name der Tabellenklasse, die die Ergebnismenge speichert. Bei Raw-Datensätzen ist Prty::Database::ResultSet::Array der Default, ansonsten Prty::Database::ResultSet::Object.
Referenz auf Cursor-Objekt (Prty::Database::Cursor)
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 -pgFetchMode gesetzt ist.
-fetchMode=>0|1|2 (Default: 0) 0=Defaultverhalten, 1=dekl. Cursor, 2=dekl. Cursor und extra Session -chunkSize=>$n (Default: 500) Fetche Datensätze in Chunks von $n Stück
$cur = $db->sqlAtomic($stmt,@opt);
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, der Zugriff auf die erzeugten Objekt wird blockiert. Oder das Setzen von Session-Einstellungen verfällt mit einem ROLLBACK. usw.
$cur = $db->setSchema($schema);
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.
$cur = $db->setEncoding($charset);
$cur = $db->setDateFormat;
$cur = $db->setNumberFormat;
$cur = $db->begin;
Beginne Transaktion und liefere das Resultat der Ausführung zurück.
$cur = $db->commit; $cur = $db->commit($commit);
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.
$cur = $db->rollback;
Verwirf alle auf der Datenbank durchgeführten Datenänderungen.
$cur = $db->save($table,$row,@where);
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
Es wird keine Datenbankoperation ausgeführt.
Es wird eine Update-Operation auf der Datenbank ausgeführt, d.h. es wird die Methode $row->update() gerufen.
Es wird eine Insert-Operation auf der Datenbank ausgeführt, d.h. es wird die Methode $row->insert() gerufen.
Es wird eine Delete-Operation auf der Datenbank ausgeführt, d.h. es wird die Methode $row->delete() gerufen.
$titleA|@titles = $db->titles(@select);
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.
$title = $db->primaryKey($table);
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.
$tab|@rows|$cur = $db->select(@select,@opt);
Siehe Prty::Database::Connection/sql().
$row|@vals = $db->lookup(@select,@opt);
Liefere einen leeren Neu-Datensatz, wenn der Datensatz nicht gefunden wird.
Liefere Datensatz in Array-Repräsentation
Default Datensatz-Klasse. Im Falle von -raw=>1 ist 'Prty::Database::Row::Array' der Default.
Es muss genau ein Datensatz getroffen werden.
Es darf 0 oder 1 Datensatz getroffen werden.
Es muss mindestens ein Datensatz getroffen werden.
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.
$row = $db->loadRow($table,@keyVal);
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.
$row = $db->nullRow(@select,@opt);
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.
Null-Datensatz einer Tabelle instantiieren
$per = Prty::Database::Connection->nullRow('person');
@keyVal|%hash|$arr = $db->values(@select); $hash = $db->values(@select,-hash=>1);
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.
DISTINCT
Sollen NULL-Werte nicht berücksichtigt werden, wird der WHERE-Klausel eine entsprechende IS NOT NULL-Bedingung hinzugefügt.
NULL
IS NOT NULL
Sollen die Werte sortiert geliefert werden, wird dem Statement eine ORDER BY Klausel hinzugefügt.
ORDER BY
Im Skalarkontext wird ein Objekt der Klasse Prty::Array oder der Klasse Prty::Hash geliefert. Letzteres, wenn Option -hash=>1 angegeben ist.
Prty::Array
-hash=>1
Liefere Hashreferenz.
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', );
$val = $db->value(@select,@opt);
Lies den ersten Datensatz der Ergebnismenge und liefere den Wert der ersten Kolumne zurück.
Anmerkungen
Die Select-Liste des Statement 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.
Wirf keine Exception, wenn die Ergebnismenge leer ist, sondern undef.
undef
Wenn auf einen Wert ungleich undef gesetzt, wirf keine Exception, wenn die Ergebnismenge leer ist, sondern $val.
$cur = $db->insert($table,@opt,$row); $cur = $db->insert($table,@opt,@keyVal); $cur = $db->insert($table,@opt,\@keys,\@values);
Füge Datensatz zu Tabelle $table hinzu und liefere das Resultat der Ausführung zurück.
Ignoriere Doubletten-Fehler.
$cur = $db->insertRows($table,\@keys, [@vals1], [@vals2], ... ); $cur = $db->insertRows($table,\@keys, @vals1, @vals2, ... );
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
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/, );
$cur = $db->update($table,$row); [1] $cur = $db->update($table,$row,@where); [2] $cur = $db->update($table,@keyVal,-where,@where); # [3]
[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.
$cur = $db->delete($table,$row,@where); $cur = $db->delete($table,@where);
Lösche Datensatz bzw. Datensätze aus Tabelle $table und liefere das Resultat der Ausführung zurück.
$cur = $db->createTable($table, [$colName,@colOpts], ... @opt, );
Erzeuge Tabelle $table auf der Datenbank.
Erzeuge Tabelle neu, falls sie bereits existiert.
Erzeuge Tabelle nicht, falls sie bereits existiert.
$cur = $db->dropTable($table);
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.
$bool = $db->tableExists($table);
Prüfe, ob Tabelle $table existiert. Wenn ja, liefere "wahr", sonst "falsch".
$db->analyzeTable($table);
Analysiere Tabelle $table und liefere einen Cursor zurück.
$cur = $db->addForeignKeyConstraint($tableName,\@tableCols, $refTableName,@opt);
Siehe Prty::Sql::addForeignKeyConstraint()
$n = $db->countRows($tableName);
$cur = $db->columnExists($table,$column);
Prüfe, ob Kolumne existiert. Wenn ja, liefere "wahr", sonst "falsch".
$cur = $db->addColumn($table,$column,@colDef,@opt);
Wirf keine Exception, wenn die Kolumne bereits existiert, sondern liefere undef.
$cur = $db->addColumn('person','mag_eis', type=>'STRING(1)', notNull=>1, default=>1, );
$cur = $db->dropColumn($table,$column);
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.
$cur = $db->modifyColumn($table,$column,$property=>$value);
Modifiziere Kolumne $column in Tabelle $table und liefere das Resultat der Statement-Ausführung zurück.
$cur = $db->renameColumn($table,$oldName,$newName;
Benenne Tabelle $table die Kolumne $oldName in $newName um und liefere das Resultat der Statement-Ausführung zurück.
$n = $db->distinctValues($table,$column);
$val = $db->minValue($table,$column);
$val = $db->maxValue($table,$column);
($count,$distinctCount,$min,$max) = $db->countDistinctMinMax($table,$column);
Die Methode liefert Information über den Inhalt einer Tabellenkolumne. Sie ist für das Reverse Engineering einer unbekannte Datenbanktabelle nützlich.
$bool = $db->indexExists($table,\@colNames);
Prüfe, ob Index existiert. Wenn ja, liefere "wahr", sonst "falsch".
$cur = $db->createIndex($table,\@colNames,@opt);
Erzeuge Index für Tabelle $table und Kolumnen @colNames auf der Datenbank.
Name des Index.
Erzeuge Index neu, falls er bereits existiert.
Name des Tablespace, in dem der Index erzeugt wird (Oracle und PostgreSQL).
Statement für Unique Index.
$cur = $db->createUniqueIndex($table,\@colNames,@opt);
Erzeuge Unique Index für Tabelle $table und Kolumnen @colNames auf der Datenbank.
Siehe $db->createIndex()
$cur = $db->dropIndex($table,\@colNames);
$db->createSequence($name,@opt);
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.
Droppe Sequenz, falls sie bereits existiert.
Die Sequenz beginnt mit Startwert $n.
$cur = $db->dropSequence($name);
Droppe Sequenz $name und liefere das Resultat der Statementausführung zurück.
$db->setSequence($sequence,$n);
Setze Sequenz $sequence auf Wert $n. Die Methode liefert keinen Wert zurück.
$n = $db->nextValue($sequence);
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.
$cur = $db->createView($viewName,$selectStmt,@opt);
Erzeuge View neu, falls sie bereits existiert.
$cur = $db->dropView($viewName);
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.
$bool = $db->viewExists($viewName);
Prüfe, ob View existiert. Wenn ja, liefere "wahr", sonst "falsch".
$cur = $db->createTrigger($table,$name,$when,$event,$level,$body,@opt); $cur = $db->createTrigger($table,$name,$when,$event,$level, $dbms=>$body, ..., @opt );
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.
Ersetze den Trigger, falls ein solcher existiert.
Cursor
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:
set_c_proc
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()
$cur = $db->dropTrigger($name);
$bool = $db->triggerExists($name);
$tab|@rows|$cur = $db->diff(@args);
Wie $db->select()
Im Zuge der Ausführung eines SQL-Statement werden drei Zeiten ermittelt:
Der Startzeitpunkt der Ausführung (Aufruf von sql)
Die Dauer der Statementausführung
Die Zeit, die seit Start des Statement vergangen ist
Diese Zeiten können vom Cursor abgefragt werden mittels:
$cur->startTime; $cur->execTime; $cur->time;
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.
Wird ein Cursor benötigt, ohne dass ein Statement ausgeführt werden soll, kann ein Null-Cursor erzeugt werden:
$cur = $db->sql;
Die Methode sql() liefert das SQL-Objekt der Datenbankverbindung. Dies ist ein Objekt der Klasse Prty::Sql, das beim Verbindungsaufbau passend zum DBMS instantiiert wurde.
Alle SQL-Generierungsmethoden der Klasse Prty::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)'], );
Die meisten Statements der Klasse Prty::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 Prty::Database::Connection-Methoden bei der Ausführung teilweise DBMS-abhängige Sonderbehandlungen vornehmen.
Anstelle der Default Sql-Klasse Prty::Sql kann beim Verbindungsaufbau eine anwendungspezifische Klasse vereinbart werden:
package MyApp::Sql; use base qw/Prty::Sql/; ... package main; $db = Prty::Database::Connection->new(...,-sqlClass=>'MyApp::Sql');
DML-Statements (SELECT, INSERT, UPDATE, DELETE) können mit Platzhaltern versehen werden. Das Statement wird dann nicht ausgeführt, sondern ein Bind-Cursor geliefert.
my $bindCur = $db->insert('person', per_id=>\'?', per_vorname=>\'?', per_nachname=>\'?', ); $bindCur->bind( 1,'Rudi','Ratlos', 2,'Elli','Pirelli', 3,'Erika','Mustermann', );
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;
$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); }
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.
my $per = $db->nullRow('person'); $per->set( per_id=>$db->nextValue('id'), per_vorname=>'Rudi', per_nachname=>'Ratlos', ); $db->insert('person',$row);
my $per = Person->new($db, per_id=>$db->nextValue('id'), per_vorname=>'Rudi', per_nachname=>'Ratlos', ); $per->insert($db);
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.
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).
$db->createTable('person', ['per_id',type=>'INTEGER',primaryKey=>1], ['per_vorname',type=>'STRING(20)'], ['per_nachname',type=>'STRING(20)'], ['per_foto',type=>'BLOB'], );
$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 = Prty::Path->read('/home/pirelli/Picture/elli.jpg'); $cur->bind(1,'Elli','Pirelli',$foto);
$per = $db->lookup('person',-where,per_id=>1);
Wie BLOB-Datentyp, aber als Bind-Typ TXET angeben:
$cur->bindTypes(undef,undef,undef,'TEXT');
Auch hier ist dies wegen Oracle erforderlich.
Beim Verbindungsaufbau kann angegeben werden, ob das Perl-Programm UTF-8 Encoding verwendet:
$db = Prty::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.
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 = Prty::Database::Connection->new('dbi#mysql',-handle=>$dbh);
1.107
Frank Seitz, http://fseitz.de/
Copyright (C) 2017 Frank Seitz
This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
5 POD Errors
The following errors were encountered while parsing the POD:
Expected text after =item, not a number
To install Prty, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Prty
CPAN shell
perl -MCPAN -e shell install Prty
For more information on module installation, please visit the detailed CPAN module installation guide.