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.