2012-09-08 4 views
5

Ich möchte eine "vorbereitete Aussage" in Postgres mit dem Knoten-Postgres-Modul erstellen. Ich möchte es erstellen, ohne es an Parameter zu binden, da die Bindung in einer Schleife stattfinden wird.node-postgres: Wie erstellt man eine Anweisung, ohne die Abfrage auszuführen?

Im documentation i lesen:

query(object config, optional function callback) : Query 
If _text_ and _name_ are provided within the config, the query will result in the creation of a prepared statement. 

Ich versuchte

client.query({"name":"mystatement", "text":"select id from mytable where id=$1"}); 

aber wenn ich nur die Text & Namenstasten in der Config-Objekt versuchen vorbei, erhalte ich eine Ausnahme:

(übersetzte) Nachricht ist bindende 0 Parameter, aber die vorbereitete Anweisung erwartet 1

Gibt es etwas, das mir fehlt? Wie erstellen/bereiten Sie eine Anweisung auf, ohne sie an einen bestimmten Wert zu binden, um zu vermeiden, dass die Anweisung in jedem Schritt einer Schleife neu erstellt wird?

Antwort

9

Ich habe gerade eine vom Autor von Node-Postgres gefunden.

Mit Knoten Postgres das erste Mal, wenn Sie eine benannte Abfrage aus, es analysiert, gebunden ist, und auf einmal ausgeführt. Jede nachfolgende Abfrage auf der gleichen Verbindung mit dem gleichen Namen wird automatisch überspringen "Parsen" Schritt und nur neu binden und führen Sie die bereits geplante Abfrage.

Momentan unterstützt node-postgres keine Möglichkeit, eine vorbereitete Abfrage mit dem Namen zu erstellen und die Abfrage nicht auszuführen. Diese Funktion wird in libpq und dem Client/Server-Protokoll unterstützt (verwendet von der reinen Javascript-Bindungen), aber ich habe es nicht direkt in der API ausgesetzt. I dachte, es würde Komplexität der API ohne wirklichen Nutzen hinzufügen. Da benannte Anweisungen an den Client gebunden sind, in dem sie erstellt werden, wenn der Client getrennt und wieder verbunden ist oder ein anderer Client aus dem Clientpool zurückgegeben wird, wird die benannte Anweisung nicht mehr arbeiten (erfordert eine erneute Analyse)).

2

Update: Lesen Sie Ihre Frage noch einmal, hier ist, was ich glaube, dass Sie tun müssen. Sie müssen auch ein "Wert" -Array übergeben.

Nur um zu klären; Dort, wo Sie normalerweise Ihre Anfrage vorbereiten würden, bereiten Sie einfach das Objekt vor, das Sie übergeben, ohne das Array Wert. Dann, wo Sie normalerweise Ihre Abfrage ausführen würden, legen Sie das Wert-Array im Objekt fest und übergeben Sie es an die Abfrage. Wenn es das erste Mal ist, wird der Fahrer die eigentliche Vorbereitung für Sie beim ersten Mal tun, und einfach tun verbindlich und Ausführung für den Rest der Iteration.

+0

Das Problem bei dieser Lösung ist, dass die vorbereitete Anweisung wird zum Zeitpunkt der Erstellung verwendet mit den ‚was auch immer‘ Werte ausgeführt werden. Es fühlt sich auch akkiv an, die erste Iteration der Schleife für die Erstellung zu verwenden. –

+0

Das ist, wie die API entworfen wird, nehme ich an, zumindest habe ich das von den Dokumenten bekommen und es in einem meiner eigenen Projekte benutzt.Die API erwartet von Ihnen, dass Sie Ihr Abfrageobjekt erstellen, wenn Sie es verwenden müssen, und dann wird es herausfinden, ob es eine Anweisung vorbereiten muss oder nicht, je nachdem, ob es weiß, was Sie bereits in "Text" eingegeben haben. –

0

können Sie verwenden pg-prepared dafür:

var prep = require('pg-prepared') 

// First prepare statement without binding parameters 
var item = prep('select id from mytable where id=${id}') 

// Then execute the query and bind parameters in loop 
for (i in [1,2,3]) { 
    client.query(item({id: i}), function(err, result) {...}) 
} 
+0

'pg-prepared' macht etwas anderes, als was OP verlangt. Es bietet die Möglichkeit, benannte Platzhalter in Abfragen zu verwenden. –

+0

OP möchte vorbereitete Anweisungen erstellen, ohne Parameterwerte bei der Erstellung zu binden. Dies geschieht im Beispiel mit pg-prepared. Zuerst erstellen Sie die Anweisung, ohne die Parameterwerte zu binden, und speichern sie in var item. Dann rufst du es mit den Parametern an. Daher kann OP dies verwenden, indem er die Anweisung ohne Variablenbindung erstellt und sie dann mit den Parameterwerten in der Schleife aufruft. – pihvi

+1

In Ihrem Fall muss die * Datenbank * die Abfrage immer wieder vorbereiten. was OP will, ist die DB durch die Vorbereitung der STMT nur einmal zu entlasten. Gemäß der akzeptierten Antwort könnte pg-prepared dies erreichen, wenn es der Abfrage ein eindeutiges "name" -Attribut gibt - siehe https://github.com/brianc/node-postgres/wiki/Prepared-Statements –