PostgreSQL: Як передати параметри з командного рядка?


92

У мене є дещо детальний запит у сценарії, який використовує ?заповнювачі. Я хотів протестувати цей самий запит безпосередньо з командного рядка psql (поза сценарієм). Я хочу уникати входу та заміни всіх ?фактичних значень, натомість я б хотів передати аргументи після запиту.

Приклад:

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

Шукаємо щось на зразок:

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

Більше контексту, будь ласка. Це запит у файлі SQL, у сценарії Perl / Python / Ruby / <вставте сюди улюблену мову сценаріїв> або в іншому місці?

@Jack: Я хочу зробити це безпосередньо з підказки psql (командний рядок). Я беру свій код із сценарію, але не хочу проходити весь процес пошуку / заміни.
vol7ron

@ Vol7ron, будь ласка, див. Мою відповідь нижче для прикладу командного рядка psql.
MAbraham1,

1
@ MAbraham1: приємно. Я мав би дати ще трохи передумов своєму питанню. У мене багато сценаріїв, які мають SQL у відкритому тексті. Іноді корисно взяти їх і вдарити тих безпосередньо по базі даних із спеціальними значеннями для налагодження. Я шукав спосіб легко це зробити всередині Postgres без необхідності зберігати додаткові файли.
vol7ron

@ Vol7ron, дякую. Я думав з точки зору пакетних завдань, однак ви також зможете використовувати маркери у відкритому SQL. Не забудьте проголосувати, якщо вам сподобалась моя відповідь.
MAbraham1,

Відповіді:


178

Ви можете використовувати конструкцію -v, наприклад

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

а потім посилатися на змінні в sql як: v1,: v2 тощо

select * from table_1 where id = :v1;

Будь ласка, зверніть увагу на те, як ми передаємо значення рядка / дати, використовуючи дві лапки " '...' "


2
+1 Цікаво, передача іменованих аргументів. Чи знаєте ви про будь-який спосіб зробити це після входу в систему?
vol7ron

9
Звичайно, просто використовуйте \set v3 'another value'. Тільки пам’ятайте, коли вам потрібно вказати значення в операторі SQL, використовуйте апострофи навколо імені змінної, наприклад:SELECT * FROM foo WHERE bar = :'v3';
Cromax

1
Думаю, вони це отримали відawk
Ніла Макгігана

1
Можна @ використовувати замість: як sqlserver
Awais Mahmood

4
Зверніть увагу, прочитавши це, я сподівався виявити, що змінні, встановлені з -v, будуть доступні для команд, що виконуються з -c, але, на жаль, вони не є. Іншими словами, psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" -c 'select * from table_1 where id = :v1;' генерує синтаксичну помилку. Однак, якщо bash - це ваша оболонка, ви можете спробувати: psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" <<< 'select * from table_1 where id = :v1;' з хорошим ефектом.
malcook

30

Виявлено в PostgreSQL, ви можете писати PREPAREтвердження так само, як і мовою сценаріїв. На жаль, ви все ще не можете використовувати ?, але ви можете використовувати $nпозначення.

Використовуючи наведений вище приклад:

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 чи було щось інше, що ти хотів включити до цього? :) звільнення відбувається автоматично в кінці сеансу
vol7ron

Тільки зауважте, що зараз fooзайнято, а інший PREPAREповинен мати інше ім’я, поки поточний сеанс не закритий. Якщо ви граєте з PREPAREв psqlце важко придумати кожен раз нове ім'я і DEALLOCATEможе допомогти з цим =)
Іван Чорний

Дякуємо, що згадали про це. Я не використовував PREPARE деякий час, але це корисна інформація
vol7ron,

Це рішення є дуже хорошим IMO. Корисний побічний ефект - ви можете легко викликати підготовлену заяву кілька разів.
Юрій

13

У psql є механізм через

\set name val

command, який повинен бути прив'язаний до -v name=valопції командного рядка. Цитування болюче. У більшості випадків простіше помістити все м’ясо запиту всередину оболонки тут-документа.

Редагувати

ой, я повинен був сказати -vзамість -P(що стосується варіантів форматування) попередня відповідь зрозуміла.


7

Ви також можете передавати параметри в командному рядку psql або з командного файлу. Перші оператори збирають необхідні деталі для підключення до вашої бази даних.

Заключний підказка запитує значення обмеження, які будуть використані в реченні WHERE стовпця IN (). Пам’ятайте, що якщо рядки містять одинарні лапки, і розділяйте їх комами:

@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

Тепер у своєму кодовому файлі SQL додайте маркер v1 до вашого речення WHERE або де-небудь ще в SQL. Зверніть увагу, що маркери також можна використовувати у відкритому операторі SQL, а не лише у файлі. Збережіть це як test.sql:

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

У Windows збережіть весь файл як файл DOS BATch (.bat), збережіть test.sql в тому ж каталозі та запустіть пакетний файл.

Дякуємо Дейву Пейджу з EnterpriseDB за оригінальний підказаний сценарій.


+1 для прикладу Windows; хоча більшість баз даних Pg існує у варіанті * nix
vol7ron

2

Здається, те, що ви запитуєте, не можна зробити безпосередньо з командного рядка . Вам доведеться або використовувати користувацьку функцію в plpgsql, або викликати запит із мови сценаріїв (а останній підхід полегшує уникнення введення SQL).


Чи не я - багато разів я бажаю, щоб голоси проти вимагали якихось пояснень (подібно до причин, чому ми голосуємо за закриті питання), навіть якщо вони залишаються анонімними.
vol7ron
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.