имя столбца psql не существует при запуске через скрипт bash - PullRequest
0 голосов
/ 09 ноября 2019

Я пытаюсь запустить несколько команд SQL в скрипте bash. Я попытался выполнить следующее заявление на PSQL, он работает нормально. Тем не менее, когда я запускаю точное выражение в сценарии, оно говорит, что столбец не существует.

Заявление

\copy (SELECT * FROM table_a h JOIN table_b b ON h."IDX" = b."IDX" WHERE b."XXX" BETWEEN 0 AND 100) to 'D:\$path\onetry1.csv' with csv HEADER;

Я знаю, что в Postgres требуется использовать двойные кавычки вимена столбцов в верхнем регистре. Я сделал это.

Это мой bash-скрипт:

#! /bin/sh

db="usm"

PGPASSWORD=XXX123 psql -h localhost -U postgres -d $db -c "\copy (SELECT * FROM table_a h JOIN table_b b ON h."IDX" = b."IDX" WHERE b."XXX" BETWEEN 0 AND 500) to '$path\onetry2.csv' with csv HEADER;"

Я получаю ошибку:

ОШИБКА: столбец h.idx не существуетЛИНИЯ 1: ... M table_a h ПРИСОЕДИНЯЙТЕСЬ к table_b b ON h.IDX = b ....

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

Ваш скрипт не отправляет двойные кавычки. У вас есть это:

"\copy (SELECT * FROM table_a h JOIN table_b b ON h."IDX" = b."IDX" WHERE b."XXX" BETWEEN 0 AND 500) to '$path\onetry2.csv' with csv HEADER;"

по сути это работает как объединение следующих строк

"\copy (SELECT * FROM table_a h JOIN table_b b ON h."
IDX
" = b."
IDX
" WHERE b."
XXX
" BETWEEN 0 AND 500) to '$path\onetry2.csv' with csv HEADER;"

, но PostgreSQL никогда не увидит двойные кавычки. Используйте обратную косую черту, избегая вложенных двойных кавычек:

"\copy (SELECT * FROM table_a h JOIN table_b b ON h.\"IDX\" = b.\"IDX\" WHERE b.\"XXX\" BETWEEN 0 AND 500) to '$path\onetry2.csv' with csv HEADER;"

также, предпочитайте избегать форсирования всего верхнего регистра или любого конкретного случая по этому вопросу. Вы все еще можете набрать верхний регистр, если хотите. Я использую имена столбцов в кавычках только для того, чтобы форматировать итоговые запросы красивее.

0 голосов
/ 09 ноября 2019

Для случаев, когда программы принимают входные данные, которые могут конфликтовать с процессом оболочки (например, кавычки, двойные кавычки и различные замены), обычно лучше использовать один из других параметров цитирования:

  • Если программы могут обрабатывать STDIN, здесь могут использоваться документы (<<word).
  • Если программы работают только с параметрами командной строки, здесь документ может быть встроен
  • Рассмотрите возможность использования переменных дляупростите цитирование.

Я полагаю, что psql также принимает ввод stdin, поэтому здесь документы могут работать (удаляя -c). Упрощение форматирования SQL для удобства чтения.

PGPASSWORD=XXX123 psql -h localhost -U postgres -d $db <<SQL
\copy (
   SELECT *
   FROM table_a h
   JOIN table_b b ON h."IDX" = b."IDX"
   WHERE b."XXX" BETWEEN 0 AND 500)
   to '$path\onetry2.csv' with csv HEADER;
SQL

Если программы принимают только аргументы командной строки, можно использовать here strings (обратите внимание, что это только функция bash, а не POSIX).

PGPASSWORD=XXX123 psql -h localhost -U postgres -d $db -c "$(cat <<SQL
\copy (
   SELECT *
   FROM table_a h
   JOIN table_b b ON h."IDX" = b."IDX"
   WHERE b."XXX" BETWEEN 0 AND 500)
   to '$path\onetry2.csv' with csv HEADER;
SQL
)

Если команда составлена ​​из переменных (или может храниться в переменных), она может исключить сложное цитирование.

V=$(cat <<SQL
\copy (
   SELECT *
   ...
   to '$path\onetry2.csv' with csv HEADER;
SQL
)
PGPASSWORD=XXX123 psql -h localhost -U postgres -d $db -c "$v"
...