2009-07-28 17 views
3

ich meine vorbereitete Erklärung erstellen, wie:PHP/PostgreSQL: überprüfen, ob eine vorbereitete Anweisung existiert bereits

pg_prepare('stm_name', 'SELECT ...'); 

Heute habe ich ein Problem hatte (zweimal eine Funktion für Fehler Aufruf), wenn eine vorbereitete Anweisung mit derselben erklärt Name zweimal:

Warning: pg_prepare() [function.pg-prepare]: Query failed: ERROR: prepared statement "insert_av" already exists in xxx on line 221 

so, wie die Frage, Titel, es ist ein Weg zu überprüfen, ob eine Anweisung mit dem gleichen Etikett bereiten bereits vorhanden ist, und in dem Fall, überschreibt?

Ich weiß, dass dieser Fehler von meinem Fehler herrührt und gelöst wird, indem ich einfach die vorbereiteten Anweisungen am Anfang meines Codes deklariere, aber ich frage mich, ob es eine Lösung gibt, mehr Kontrolle über sie zu haben.

EDIT:

Nach der Milen Antwort ist ganz einfach, wenn die vorbereitete Anweisung zu überprüfen Verwendung ist bereits in einfach die DB für die pg_prepared_statements Tabelle abfragt:

try{ 
    $qrParamExist = pg_query_params("SELECT name FROM pg_prepared_statements WHERE name = $1", array($prepared_statement_name)); 
    if($qrParamExist){ 
     if(pg_num_rows($qrParamExist) != 0){ 
      echo 'parametized statement already created'; 
     }else{ 
      echo 'parametized statement not present'; 
     } 
    }else{ 
     throw new Exception('Unable to query the database.'); 
    } 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

Aber ich glaube nicht, dass dies eine gute Lösung ist, weil ich jedes Mal die Datenbank abfragen muss.

Ok, normalerweise werden die vorbereiteten Anweisungen am Anfang des Skripts deklariert und dann einfach wiederverwendet, aber ich habe eine Klasse schön verkabelt und ich mag es nicht, 10 vorbereitete Anweisungen zu deklarieren, wenn ich nur 3 davon verwenden werde Sie.

Also, ich glaube ich einen einfachen PHP-Array verwenden werde, halte die Aussagen verfolgen ich erstellen und dann mit isset() Funktion zu überprüfen, ob es existiert oder erstellt werden muss:

try{ 
    $prepare = pg_prepare('my_stmt_name', "SELECT ..."); 
    if($prepare){ 
     $this->rayPrepared['my_stmt_name'] = true; 
    }else{ 
     throw new Exception('Prepared statement failed.'); 
    } 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 
+0

Können Sie mir bitte sagen, wie Sie die Warnmeldung erhalten? Wenn ich diese Warnmeldung nicht habe, verbrachte ich fast eine Stunde, um zu verstehen, warum mein Code fehlschlägt. Danke –

+1

@EnsomHodder versuchen Sie mit 'error_reporting (E_ALL);' und mit 'pg_last_error' wenn Ihr Ergebnis von' pg_prepare' oder 'pg_query' fehlschlägt (zB false) – Strae

Antwort

4

Einen Weg (I hofft, dass jemand einen einfacheren) hinweisen wird:

<? 
$prepared_statement_name = 'activity1'; 
$mydbname = '...'; 

$conn = pg_connect("host=... port=... dbname=... user=... password=..."); 

$result = pg_query_params($conn, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array($prepared_statement_name)); 

if (pg_num_rows($result) == 0) { 
    $result = pg_prepare($conn, $prepared_statement_name, 'SELECT * FROM pg_stat_activity WHERE datname = $1'); 
} 

$result = pg_execute($conn, $prepared_statement_name, array($mydbname)); 
while($row = pg_fetch_row($result)) { 
    var_dump($row); 
} 
+0

Ja, es funktioniert, ich werde meine Frage mit dem Code aktualisieren Ich habe versucht – Strae

0

Lassen Sie sich diese in pHP nicht versucht, aber wenn dies in Ihrer Anwendung möglich (wenn Sie die Erklärung nur an einem Ort und nicht müssen „holen müssen "Es wieder mit Namen" könnte man versuchen, eine unbenannte Aussage zu erstellen. http://www.postgresql.org/docs/8.4/interactive/libpq-exec.html sagt:

PQprepare ...
stmtName möglicherweise "", um eine unbenannte Anweisung zu erstellen, in diesem Fall wird jede bereits vorhandene unbenannte Anweisung automatisch ersetzt; Andernfalls ist es ein Fehler, wenn der Anweisungsname bereits in der aktuellen Sitzung definiert ist.
php_pg verwendet PQprepare, also könnte dies für Sie funktionieren.

+0

Sorry, ich habe viele verschiedene vorbereitete Statements .. kann die unbenannten verwendet werden. – Strae

+0

Ja, die "aktuelle Sitzung".Ich fand heraus, dass "aktuelle Sitzung" nicht "Verbindung" bedeutet. Es ist eine Schande, dass es keine robuste Möglichkeit gibt, die API einfach dazu zu bringen, uns zu sagen, was wir wissen müssen, ohne etwas zu unternehmen und eine Anfrage zu stellen. – Opux

-3

Warum verwenden Sie überhaupt vorbereitete Anweisungen? Sie bieten nur dann einen Leistungsvorteil, wenn Sie dieselbe Aussage mehrfach verwenden.

+2

Erstens bieten sie mehr Sicherheit gegen die Injektion .... dann, wo habe ich gesagt, dass ich sie nur einmal benutze? ;) – Strae

+0

Ich neige dazu, diesem Downvote zuzustimmen, ich frage mich nur, warum er jedes Mal, wenn du es tust, meinen Repräsentanten herabstimmt, da ich tatsächlich der erste war, der den Downvote gemacht hat? Verwirrt. – Rob

+1

Leistungsvorteile sind nett, aber Hilfe gegen SQL-Injektion ist schöner. – xentek

1

Manchmal verwenden Sie EXECUTE, um den Fehler "relation with OID ###### existiert nicht" zu beheben.

Verwandte Themen