PostgreSQL: come passare i parametri dalla riga di comando?


92

Ho una query piuttosto dettagliata in uno script che utilizza i ?segnaposto. Volevo testare la stessa query direttamente dalla riga di comando di psql (fuori dallo script). Voglio evitare di entrare e sostituire tutti i ?con valori effettivi, invece vorrei passare gli argomenti dopo la query.

Esempio:

SELECT  * 
FROM    foobar
WHERE   foo = ?
   AND  bar = ?
    OR  baz = ?  ;

Alla ricerca di qualcosa come:

%> {select * from foobar where foo=? and bar=? or baz=? , 'foo','bar','baz' };

Più contesto, per favore. Questa query è in un file SQL, in uno script Perl / Python / Ruby / <inserisci il linguaggio di scripting preferito qui> o in qualche altro posto?

@ Jack: sto cercando di farlo direttamente dal prompt di psql (riga di comando). Sto prendendo il mio codice da uno script, ma non voglio passare attraverso l'intero processo di ricerca / sostituzione.
vol7ron

@ Vol7ron, vedi la mia risposta di seguito per un esempio di riga di comando psql.
MAbraham1

1
@ MAbraham1: simpatico. Avrei dovuto fornire qualche informazione in più alla mia domanda. Ho molti script che hanno SQL in testo aperto. A volte è utile prenderli e inserirli direttamente nel database, con valori personalizzati per il debug. Stavo cercando un modo per farlo facilmente all'interno di Postgres senza dover salvare file aggiuntivi.
vol7ron

@ Vol7ron, grazie. Stavo pensando in termini di lavori batch, tuttavia dovresti essere in grado di utilizzare i token anche in SQL aperto. Non dimenticare di votare se ti è piaciuta la mia risposta.
MAbraham1

Risposte:


178

Puoi usare il costrutto -v es

psql -v v1=12  -v v2="'Hello World'" -v v3="'2010-11-12'"

e quindi fare riferimento alle variabili in sql come: v1,: v2 ecc

select * from table_1 where id = :v1;

Si prega di prestare attenzione a come passiamo il valore stringa / data utilizzando due virgolette " '...' "


2
+1 Interessante, passando argomenti con nome. Sei a conoscenza di un modo per farlo una volta effettuato l'accesso?
vol7ron

9
Certo, basta usare \set v3 'another value'. Ricorda, quando devi citare il valore SELECT * FROM foo WHERE bar = :'v3';
nell'istruzione

1
Immagino che l'abbiano preso daawk
Neil McGuigan

1
Può essere usato al posto di: come sqlserver
Awais Mahmood,

4
Nota, leggendo questo, speravo di scoprire che le variabili impostate con -v sarebbero state disponibili per i comandi eseguiti con -c, ma purtroppo non lo sono. In altre parole, psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" -c 'select * from table_1 where id = :v1;' genererà un errore di sintassi. Tuttavia, se bash è la tua shell, potresti provare: psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" <<< 'select * from table_1 where id = :v1;' con buoni risultati.
malcook

30

Trovato in PostgreSQL, puoi fare PREPAREdichiarazioni proprio come puoi fare in un linguaggio di scripting. Sfortunatamente, non puoi ancora usare ?, ma puoi usare la $nnotazione.

Utilizzando l'esempio sopra:

PREPARE foo(text,text,text) AS
    SELECT  * 
    FROM    foobar
    WHERE   foo = $1
       AND  bar = $2
        OR  baz = $3  ;
EXECUTE foo('foo','bar','baz');
DEALLOCATE foo;

@ IvanBlack c'era qualcos'altro che volevi includere in questo? :) la deallocazione viene eseguita automaticamente alla fine di una sessione
vol7ron

Tieni presente che ora fooè occupato e un altro PREPAREdovrebbe avere un altro nome mentre la sessione corrente non è chiusa. Se giochi con PREPAREdentro psqlè difficile inventare ogni volta un nuovo nome e DEALLOCATEpuò aiutarti =)
Ivan Black

Grazie per averlo menzionato. Non uso PREPARE da un po 'di tempo, ma questa è un'informazione utile
vol7ron

Questa soluzione è molto buona IMO. Un utile effetto collaterale: puoi facilmente chiamare la dichiarazione preparata più volte.
Yuri

13

In psql esiste un meccanismo tramite il

\set name val

comando, che dovrebbe essere legato -v name=valall'opzione della riga di comando. Le virgolette sono dolorose, nella maggior parte dei casi è più facile mettere l'intera carne della query in un documento qui di shell.

modificare

oops, avrei dovuto dire -vinvece di -P(che è per le opzioni di formattazione) la risposta precedente ha capito bene.


7

È inoltre possibile passare i parametri dalla riga di comando di psql o da un file batch. Le prime istruzioni raccolgono i dettagli necessari per la connessione al database.

Il prompt finale richiede i valori del vincolo, che verranno utilizzati nella clausola IN () della colonna WHERE. Ricorda di virgolette singole se stringhe e separate da virgola:

@echo off
echo "Test for Passing Params to PGSQL"
SET server=localhost
SET /P server="Server [%server%]: "

SET database=amedatamodel
SET /P database="Database [%database%]: "

SET port=5432
SET /P port="Port [%port%]: "

SET username=postgres
SET /P username="Username [%username%]: "

SET /P bunos="Enter multiple constraint values for IN clause [%constraints%]: "
ECHO you typed %constraints%
PAUSE
REM pause
"C:\Program Files\PostgreSQL\9.0\bin\psql.exe" -h %server% -U %username% -d %database% -p %port% -e -v v1=%constraints% -f test.sql

Ora nel file di codice SQL, aggiungi il token v1 all'interno della clausola WHERE o in qualsiasi altro punto dell'SQL. Notare che i token possono essere utilizzati anche in un'istruzione SQL aperta, non solo in un file. Salvalo come test.sql:

SELECT * FROM myTable
WHERE NOT someColumn IN (:v1);

In Windows, salvare l'intero file come file DOS BATch (.bat), salvare test.sql nella stessa directory e avviare il file batch.

Grazie a Dave Page, di EnterpriseDB, per lo script originale richiesto.


+1 per l'esempio di Windows; sebbene la maggior parte dei database Pg esistano in una variante * nix
vol7ron

2

Sembrerebbe che ciò che chiedi non possa essere fatto direttamente dalla riga di comando . Dovrai utilizzare una funzione definita dall'utente in plpgsql o chiamare la query da un linguaggio di scripting (e quest'ultimo approccio rende un po 'più semplice evitare l'iniezione SQL).


Non ero io - molte volte vorrei che i voti negativi richiedessero una sorta di spiegazione (simile ai motivi per cui votiamo per chiudere le domande), anche se lasciati in modo anonimo.
vol7ron
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.