Сохраните многострочный EOSQL и запрос char в переменной и запустите его с помощью psql

#postgresql #bash #shell #psql

Вопрос:

У меня есть следующий код в сценарии оболочки, который инициализирует postgres базу данных в docker контейнере:

 if [ "$ENV" == "development" ];
then
    psql --username "postgres" --dbname "postgres" <<EOSQL

    SELECT 'CREATE DATABASE $DATABASE' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DATABASE');gexec

    connect "$DATABASE";

    DO $
    BEGIN
        -- Some stuff
    END
    $;

    -- Other stuff
EOSQL
else
    psql --host "$HOST" --username "postgres" --dbname "postgres" <<EOSQL

    SELECT 'CREATE DATABASE $DATABASE' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DATABASE');gexec

    connect "$DATABASE";

    DO $
    BEGIN
        -- Some stuff
    END
    $;

    -- Other stuff
EOSQL
fi
 

В операторе if and else SQL-запрос идентичен, и я хотел бы ввести переменную, чтобы мне не пришлось ее повторять.

Я пытался это сделать QUERY="..." , psql ... -c "$QUERY" но потом получаю ошибки в символе.

Есть ли способ сохранить этот многострочный SQL-запрос в переменной и запустить его с помощью psql

Ответ №1:

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

 hostoption=""
if [[ "$ENV" != "development" ]]
then
    hostoption="--host $HOST"
fi

psql $hostoption --username "postgres" --dbname "postgres" <<EOSQL

SELECT 'CREATE DATABASE $DATABASE' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DATABASE');gexec

connect "$DATABASE";

DO $
BEGIN
    -- Some stuff
END
$;

-- Other stuff
EOSQL
 

Этот путь hostoption пуст для развития. И добавление пробела после psql ничего не нарушит.

Для других сред он содержит параметр хост.

Ответ №2:

Чтобы легко протестировать ваш запрос, лучше всего сохранить его в скрипте и использовать -f из psql . Но если вам действительно нужен этот запрос в самом сценарии оболочки, вы можете использовать апострофы, чтобы заключить слово-разделитель ( EOF ) и запретить расширение оболочки, чем вы можете просто скопировать и вставить проверенный sql-скрипт в сценарий оболочки, например:

 psql $hostoption --username "postgres" --dbname "postgres" <<'EOSQL'

SELECT 'CREATE DATABASE $DATABASE'  WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DATABASE');gexec

connect "$DATABASE";

DO $
BEGIN
    -- Some stuff
END
$;

-- Other stuff
EOSQL
 

Лучшая логика программирования для вашего вопроса уже была указана @Nic3500.