Mam dość szczegółowe zapytanie w skrypcie, który używa ?
symboli zastępczych. Chciałem przetestować to samo zapytanie bezpośrednio z wiersza poleceń psql (poza skryptem). Chcę uniknąć wchodzenia i zastępowania wszystkich ?
rzeczywistymi wartościami, zamiast tego chciałbym przekazać argumenty po zapytaniu.
Przykład:
SELECT *
FROM foobar
WHERE foo = ?
AND bar = ?
OR baz = ? ;
Szukam czegoś takiego:
%> {select * from foobar where foo=? and bar=? or baz=? , 'foo','bar','baz' };
postgresql
parameters
vol7ron
źródło
źródło
Odpowiedzi:
Możesz użyć konstrukcji -v np
a następnie odwołaj się do zmiennych w sql jako: v1,: v2 itd
select * from table_1 where id = :v1;
Zwróć uwagę na sposób przekazywania wartości ciągu / daty w dwóch cudzysłowach
" '...' "
źródło
\set v3 'another value'
. Pamiętaj tylko, że kiedy musisz zacytować wartość w instrukcji SQL, użyj apostrofów wokół nazwy zmiennej, na przykład:SELECT * FROM foo WHERE bar = :'v3';
awk
psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" -c 'select * from table_1 where id = :v1;'
wygeneruje błąd składniowy. Jeśli jednak bash jest twoją powłoką, możesz spróbować:psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" <<< 'select * from table_1 where id = :v1;'
z dobrym skutkiem.Dowiedział się w PostgreSQL, możesz wyciągać
PREPARE
oświadczenia tak samo, jak w języku skryptowym. Niestety nadal nie możesz użyć?
, ale możesz użyć$n
notacji.Korzystając z powyższego przykładu:
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;
źródło
foo
jest zajęty, a innyPREPARE
powinien mieć inną nazwę, podczas gdy bieżąca sesja nie jest zamknięta. Jeśli graszPREPARE
wpsql
to, trudno jest wymyślić za każdym razem nową nazwę iDEALLOCATE
możesz w tym pomóc =)W psql istnieje mechanizm poprzez
\set name val
polecenie, które ma być powiązane z
-v name=val
opcją wiersza poleceń. Cytowanie jest bolesne, w większości przypadków łatwiej jest umieścić całe zapytanie wewnątrz skorupy dokumentu.Edytować
Ups, powinienem był powiedzieć
-v
zamiast-P
(co jest dla opcji formatowania) poprzednia odpowiedź dobrze.źródło
Parametry można również przekazać w wierszu poleceń psql lub z pliku wsadowego. Pierwsze instrukcje zawierają informacje niezbędne do połączenia się z bazą danych.
Ostatnia zachęta wymaga podania wartości ograniczenia, które zostaną użyte w klauzuli WHERE column IN (). Pamiętaj o umieszczaniu pojedynczych cudzysłowów w ciągach znaków i oddzielaniu ich przecinkami:
@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
Teraz w pliku kodu SQL dodaj token v1 w klauzuli WHERE lub w dowolnym innym miejscu w SQL. Zwróć uwagę, że tokenów można również używać w otwartej instrukcji SQL, a nie tylko w pliku. Zapisz to jako test.sql:
SELECT * FROM myTable WHERE NOT someColumn IN (:v1);
W systemie Windows zapisz cały plik jako plik DOS BATch (.bat), zapisz test.sql w tym samym katalogu i uruchom plik wsadowy.
Dziękujemy za Dave Page z EnterpriseDB za oryginalny skrypt podpowiedzi.
źródło
Wydawałoby się, że to, o co prosisz, nie może być wykonane bezpośrednio z wiersza poleceń . Będziesz musiał albo użyć funkcji zdefiniowanej przez użytkownika w plpgsql, albo wywołać zapytanie z języka skryptowego (a to drugie podejście ułatwia uniknięcie wstrzykiwania SQL).
źródło
Chciałbym udzielić innej odpowiedzi zainspirowanej komentarzem @ malcook (używając basha).
Ta opcja może zadziałać, jeśli musisz użyć zmiennych powłoki w zapytaniu, gdy używasz
-c
flagi . W szczególności chciałem uzyskać liczbę tabeli, której nazwa była zmienną powłoki (której nie można przekazać bezpośrednio podczas używania-c
).Załóżmy, że masz zmienną powłoki
Następnie możesz uzyskać wyniki za pomocą
psql -q -A -t -d databasename -c <<< echo "select count(*) from $TABLE_NAME;"
(
-q -A -t
służy tylko do wydrukowania wynikowej liczby bez dodatkowego formatowania)Zwrócę uwagę, że
echo
w tu-string (<<<
operator) może nie być konieczne, początkowo myślałem, że cudzysłowy same w sobie będą w porządku, może ktoś może wyjaśnić przyczynę.źródło
Skończyło się na korzystaniu z lepszej wersji @ vol7ron answer:
DO $$ BEGIN IF NOT EXISTS(SELECT 1 FROM pg_prepared_statements WHERE name = 'foo') THEN PREPARE foo(text,text,text) AS SELECT * FROM foobar WHERE foo = $1 AND bar = $2 OR baz = $3; END IF; END$$; EXECUTE foo('foo','bar','baz');
W ten sposób zawsze możesz wykonać to w takiej kolejności (zapytanie przygotowane tylko jeśli nie zostało jeszcze przygotowane), powtórzyć wykonanie i uzyskać wynik z ostatniego zapytania.
źródło