2017-10-25 1 views
1

Ich habe empirisch entdeckt, dass PostgreSQL können Sie ‚Tupel‘ erstellen (Terminologie mir, ich weiß nicht, was sie es nennen) eine mehrspaltige Zustand in WHERE zu definieren:Wie übergeben Tupel (nicht Array) als Einschränkung Parameter in SQL-Abfrage über Client-Bibliothek (Postgres)?

update T set x=true where (a_id, b_id) IN ((3428, 3544), (3450, 3542)); 

Dies scheint genau das zu tun, was ich hoffe, es würde tun: x wird aktualisiert, wo a_id = erstes Element in Tupel und B_id = zweites Element in Tupel. Das ist nahe daran, nützlich zu sein, aber damit es wirklich wichtig ist, muss ich in der Lage sein, diese 'Tupel' als Parameter aus einer Client-Bibliothek zu setzen; insbesondere node-pg in diesem Fall.

Ist es möglich, $ 1 an etwas in der folgenden Abfrage zu binden, so dass $ 1 eine Liste von 0 oder mehr Paaren von a_id und b_id ist?

client.query("UPDATE t SET x=true WHERE (a_id, b_id) IN $1"), [...?]) 

Wenn nicht, kann ich zumindest tun

client.query("UPDATE t SET x=true WHERE (a_id, b_id) IN ($1, $2, ...$N)", [ a1b1, a1b2, ...aNbN ]) 

?

+0

Sie können das tun zweite, aber nicht die erste. –

+0

Beste Ratschläge: Vermeide Tupel wie eine Seuche, sie sind ein Vermächtnis, das durch JSON/JSONB abgelöst wurde - was du stattdessen verwenden solltest. –

+0

@ vitaly-t JSON/JSONB in ​​Bezug auf SQL-Abfrage? Können Sie auf eine Dokumentation zu diesem Thema verweisen? – user3175580

Antwort

0

unten ist eine Möglichkeit, Array von Ganzzahlen mit einem Argument zu ungenannten Prepared-Anweisung zu übergeben, aber ich bin sicher, wie viel das ist benutzbar, aber sicherlich machbar mit Node-Postgres.

sql:

f=# create table nu(i int, t text); 
CREATE TABLE 
f=# insert into nu values (1,'a'),(2,'a'),(4,'a'); 
INSERT 0 3 
f=# select * from nu; 
i | t 
---+--- 
1 | a 
2 | a 
4 | a 
(3 rows) 

js:

client.query("update nu set t = 'b' where i = any ($1::int[]) returning *", [[1,2,3]], (err, res) => { 
    console.log(err, res.rows) 
    client.end() 
}) 

Ausgang:

null [ anonymous { i: 1, t: 'b' }, anonymous { i: 2, t: 'b' } ] 

zusätzliche Kontrolle:

f=# select * from nu; 
i | t 
---+--- 
4 | a 
1 | b 
2 | b 
(3 rows) 

Im Hinblick auf die zweite Art und Weise - es ist genau das getan, wie Sie in Ihrem Beispiel zeigen

UPDATE

Aufgrund meines inacurate Lesen wir wieder andere Frage beantwortet. doch entschied ich mich oben zu verlassen, so dass das nächste Stück Code wäre comprehendable:

client.query("update nu set t = 'foo' where (i,t)::text = any ($1::text[]) returning *", ['{"(1,b)","(2,b)"}'], (err, res) => { 
    console.log(err, res.row) 
    client.end() 
}) 

und somit Anweisung erzeugt:

t 2017-10-26 07:53:25 UTC :: LOG: execute <unnamed>: update nu set t = 'foo' where (i,t)::text = any ($1::text[]) returning * 
t 2017-10-26 07:53:25 UTC :: DETAIL: parameters: $1 = '{"(1,b)","(2,b)"}' 

und Ergebnis:

f=# select * from nu; 
i | t 
---+----- 
4 | a 
1 | foo 
2 | foo 
(3 rows) 
+0

Sicher; eigentlich erinnerte ich mich auch an "ANY". Aber es ist nur nützlich, wenn ich Parameter übergeben kann, sodass ich die Abfrage tatsächlich mit 'WHERE (a_id, b_id) = ANY ($ 1)' schreiben kann. Die Frage ist, wenn $ 1 ein Array ist, welche Elemente werden von Pg als (a_id, b_id) Paare geparst? Scheint wie 2-Element-Subarrays nicht funktionieren, daher ist diese besondere Art, die Abfrage mit Parametern im Hinterkopf zu schreiben, nutzlos. Im Grunde müssen Sie 'WHERE (a_id = $ 1 UND b_id = $ 2) ODER (a_id = $ 3 AND b_id = $ 4) ODER ....' – user3175580

+0

@ user3175580 Ich aktualisierte die Antwort - hoffentlich verstehe ich jetzt das OP und die richtige Frage zu beantworten :) –

Verwandte Themen