Утилита psql для работы с PostgreSQL

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

Подключение к серверу баз данных

Если у вас ещё не установлен сервер PostgreSQL, то вы можете установить его по одной из двух инструкций: [Установка PostgreSQL из исходников] и [Установка PostgreSQL 16 на Debian 12 из репозитория].

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

$ psql -d <база> -U <роль> -h <узел> -p <порт>

По умолчанию при подключении вы используете:

  • в качестве имени базы и роли — имя пользователя ОС;
  • в качестве адреса сервера — локальный сокет, который находится в каталоге /var/run/postgresql/ и порт 5432.

Таким образом если вы в системе находитесь под пользователем postgres, то следующие команды будут равнозначными:

postgres@srv-deb:~$ psql
postgres@srv-deb:~$ psql -d postgres -U postgres -h /var/run/postgresql/ -p 5432

Но обычно мы не работаем под пользователем postgres, поэтому можем использовать одну из этих команд для подключения к серверу под пользователем postgres:

alex@srv-deb:~$ sudo -u postgres psql
alex@srv-deb:~$ sudo su - postgres -c psql

Лично мне больше нравится первый вариант, но многие предпочитают второй. Кстати про sudo я писал в этой статье: Использование sudo в Linux.

Примеры работы в консоли psql

Подключившись к СУБД вы можете выполнять SQL запросы, они должны заканчиваться точкой запятой. Или вы можете использовать встроенные команды psql, они начинаются на обратный слеш.

Для примера запроса SQL можем создать новую базу данных:

postgres=# CREATE DATABASE test_db;
CREATE DATABASE

Про другие, самые простые запросы SQL я писал в статье Основы SQL.

Для получения информации об узле к которому вы подключились используйте команду \conninfo:

postgres=# \conninfo
Вы подключены к базе данных "postgres" как пользователь "postgres" через сокет в "/var/run/postgresql", порт "5432".

Не выходя из терминала psql вы можете подключится к другому узлу или базе с помощью команды \c <база> <роль> <узел> <порт>.

postgres=# \c test_db
Вы подключены к базе данных "test_db" как пользователь "postgres".

postgres=# \conninfo
Вы подключены к базе данных "test_db" как пользователь "postgres" через сокет в "/var/run/postgresql", порт "5432".

Чтобы выйти из терминала psql можно использовать 2 равносильные команды \q и exit.

Получение справочной информации

Получить справку о psql можно следующими способами:

  • psql --help
  • man psql

Вы также можете получить справку находясь в терминале psql:

  • \? — список команд psql (это встроенные команды, которые начинаются на обратный слеш);
  • \? variables — список специальных переменные psql (с их помощью можно настраивать работу psql, это будет показано ниже);
  • \h — список команд SQL (таких как SELECT, CREATE DATABASE и так далее);
  • \h <команда> — синтаксис определённой команды SQL.

Настройка psql

При входе в psql будут выполнятся команды записанные в ~/.psqlrc. Этого файла может и не быть, но если он будет создан в домашнем каталоге пользователя, то psql будет его читать при каждом подключении к серверу.

Вот некоторые примеры настроек, которые можно ввести в ~/.psqlrc:

  • \setenv PAGER 'less -XS' — результат запроса, будет попадать в утилиту less;
  • \timing on — после запроса показывать время его выполнения;
  • \set PROMPT1 '%n@%/%R%# ' — приглашение вода команды, когда psql ждет новую команду;
  • \set PROMPT2 '%n@%/%R%#... ' — приглашение вода команды, когда psql ждет дополнительный ввод;
  • \set HISTSIZE 2000 — история команд будет хранить 2000 строк.

Настраивая приглашение PROMPT1 (основное приглашение) и PROMPT2 (приглашение для многострочного ввода) используются следующие служебные символы:

  • %n — имя пользователя;
  • %/ — имя базы;
  • %R — индикатор состояния ввода:
    • = — внутри транзакции;
    • ! — транзакция сломана;
  • %# — индикатор прав:
    • # — суперпользователь (postgres),
    • > — обычный пользователь.

В качестве практики давайте настроим .psqlrc для пользователя postgres:

alex@srv-deb:~$ sudo -u postgres -i

postgres@srv-deb:~$ nano .psqlrc
\setenv PAGER 'less -XS'
\timing on
\set HISTSIZE 2000
\set PROMPT1 '%n@%/%R%# '
\set PROMPT2 '%n@%/%R%#... '
\set HISTSIZE 2000

postgres@srv-deb:~$ psql
Секундомер включён.
psql (16.8 (Debian 16.8-1.pgdg120+1))
Введите "help", чтобы получить справку.

postgres@postgres=# \c test_db
Вы подключены к базе данных "test_db" как пользователь "postgres".

postgres@test_db=# CREATE TABLE users
postgres@test_db-#... (fio text,
postgres@test_db(#... company text,
postgres@test_db(#... phone varchar(11),
postgres@test_db(#... email text
postgres@test_db(#... );
CREATE TABLE
Время: 3,086 мс

postgres@test_db=# exit

Как вы могли увидеть, после запроса выводится время его выполнения. Также в приглашении ввода команды к имени пользователя добавилось имя базы. А ещё мы изменили многострочный ввод, когда мы нажимаем Enter не закончив команду, то появляется многоточие.

История команд введённых в psql сохраняется в файл .psql_history, и мы задали что хранится там будут 2000 строк. Перемещаться по истории команд в терминале psql можно клавишами вверх и вниз, точно также как мы привыкли делать это в bash.

Формат выводимой информации

Когда вы выполняете какой-нибудь запрос в терминале psql, то в выводе видите результат этого запроса. По умолчанию такой вывод показывается в форме таблички. Но вы можете настроить формат выводимой информации сами:

  • \a — с выравниванием / без выравнивания;
  • \pset fieldsep ' ' — с помощью переменной fieldsep можно задать разделитель (по умолчанию используется вертикальная черта '|');
postgres@postgres=# SELECT * FROM pg_tables LIMIT 5;
 schemaname |       tablename       | tableowner | tablespace | hasindexes | hasrules | hastriggers | >
------------+-----------------------+------------+------------+------------+----------+-------------+->
 pg_catalog | pg_statistic          | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_type               | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_foreign_table      | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_authid             | postgres   | pg_global  | t          | f        | f           | f
 pg_catalog | pg_statistic_ext_data | postgres   |            | t          | f        | f           | f
(5 строк)
Время: 0,459 мс

postgres@postgres=# \a
Формат вывода: unaligned.

postgres@postgres=# SELECT * FROM pg_tables LIMIT 5;
schemaname|tablename|tableowner|tablespace|hasindexes|hasrules|hastriggers|rowsecurity
pg_catalog|pg_statistic|postgres||t|f|f|f
pg_catalog|pg_type|postgres||t|f|f|f
pg_catalog|pg_foreign_table|postgres||t|f|f|f
pg_catalog|pg_authid|postgres|pg_global|t|f|f|f
pg_catalog|pg_statistic_ext_data|postgres||t|f|f|f
(5 строк)
Время: 0,432 мс

postgres@postgres=# \pset fieldsep ' '
Разделитель полей: " ".

postgres@postgres=# SELECT * FROM pg_tables LIMIT 5;
schemaname tablename tableowner tablespace hasindexes hasrules hastriggers rowsecurity
pg_catalog pg_statistic postgres  t f f f
pg_catalog pg_type postgres  t f f f
pg_catalog pg_foreign_table postgres  t f f f
pg_catalog pg_authid postgres pg_global t f f f
pg_catalog pg_statistic_ext_data postgres  t f f f
(5 строк)
Время: 0,467 мс
  • \t — отображение строки заголовка и итоговой строки / без такого отображения;
postgres@postgres=# SELECT * FROM pg_tables LIMIT 5;
 schemaname |       tablename       | tableowner | tablespace | hasindexes | hasrules | hastriggers | >
------------+-----------------------+------------+------------+------------+----------+-------------+->
 pg_catalog | pg_statistic          | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_type               | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_foreign_table      | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_authid             | postgres   | pg_global  | t          | f        | f           | f
 pg_catalog | pg_statistic_ext_data | postgres   |            | t          | f        | f           | f
(5 строк)
Время: 0,393 мс

postgres@postgres=# \t
Режим вывода только кортежей включён.

postgres@postgres=# SELECT * FROM pg_tables LIMIT 5;
 pg_catalog | pg_statistic          | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_type               | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_foreign_table      | postgres   |            | t          | f        | f           | f
 pg_catalog | pg_authid             | postgres   | pg_global  | t          | f        | f           | f
 pg_catalog | pg_statistic_ext_data | postgres   |            | t          | f        | f           | f
Время: 0,472 мс
  • \x — расширенный режим, когда нужно вывести много столбцов одной таблицы, они будут выведены в один столбец.
postgres@postgres=# \x
Расширенный вывод включён.

postgres@postgres=# SELECT * FROM pg_tables LIMIT 3;
-[ RECORD 1 ]-----------------
schemaname  | pg_catalog
tablename   | pg_statistic
tableowner  | postgres
tablespace  |
hasindexes  | t
hasrules    | f
hastriggers | f
rowsecurity | f
-[ RECORD 2 ]-----------------
schemaname  | pg_catalog
tablename   | pg_type
tableowner  | postgres
tablespace  |
hasindexes  | t
hasrules    | f
hastriggers | f
rowsecurity | f
-[ RECORD 3 ]-----------------
schemaname  | pg_catalog
tablename   | pg_foreign_table
tableowner  | postgres
tablespace  |
hasindexes  | t
hasrules    | f
hastriggers | f
rowsecurity | f

Время: 0,454 мс

Взаимодействие psql с операционной системой

Терминал psql умеет выполнять команды операционной системы. Для этого нужно использовать команду \!. Например так:

postgres@postgres=# \! hostname
srv-deb

Можно установить переменную окружения в систему с помощью команды \setenv:

postgres@postgres=# \setenv TEST Hello
postgres@postgres=# \! echo $TEST
Hello

А для того чтобы перевести вывод команд в файл нужно использовать \o имя_файла. И чтобы вернуть всё обратно используем \o без имени файла:

postgres@postgres=# \o dba.log

postgres@postgres=# SELECT schemaname, tablename, tableowner FROM pg_tables LIMIT 3;
Время: 0,388 мс

postgres@postgres=# \! cat dba.log
 schemaname |    tablename     | tableowner
------------+------------------+------------
 pg_catalog | pg_statistic     | postgres
 pg_catalog | pg_type          | postgres
 pg_catalog | pg_foreign_table | postgres
(3 строки)

Помимо вывода в файл psql умеет выполнять команды из файла. Это делается с помощью команды \i имя файла. Вот пример:

postgres@srv-deb:~$ nano dba.sql
SELECT schemaname, tablename, tableowner FROM pg_tables LIMIT 3;

postgres@srv-deb:~$ psql
Секундомер включён.
psql (16.8 (Debian 16.8-1.pgdg120+1))
Введите "help", чтобы получить справку.

postgres@postgres=# \i dba.sql
 schemaname |    tablename     | tableowner
------------+------------------+------------
 pg_catalog | pg_statistic     | postgres
 pg_catalog | pg_type          | postgres
 pg_catalog | pg_foreign_table | postgres
(3 строки)
Время: 1,141 мс

Переменные окружения

Утилита psql может использовать переменные окружения. Для установки переменной используется команда \set, которой нужно передать имя и значение переменной. Если команде \set не передать никаких параметров, то она выведет все переменные окружения. Вывести значение переменной можно с помощью команды \echo, которой нужно передать имя переменной, но перед именем нужно обязательно поставить двоеточие:

postgres@postgres=# \set TEST Hi!

postgres@postgres=# \echo :TEST
Hi!

postgres@postgres=# \set
AUTOCOMMIT = 'on'
COMP_KEYWORD_CASE = 'preserve-upper'
DBNAME = 'postgres'
ECHO = 'none'
ECHO_HIDDEN = 'off'
ENCODING = 'UTF8'
ERROR = 'false'
FETCH_COUNT = '0'
HIDE_TABLEAM = 'off'
HIDE_TOAST_COMPRESSION = 'off'
HISTCONTROL = 'none'
HISTSIZE = '2000'
HOST = '/var/run/postgresql'
IGNOREEOF = '0'
LAST_ERROR_MESSAGE = ''
LAST_ERROR_SQLSTATE = '00000'
ON_ERROR_ROLLBACK = 'off'
ON_ERROR_STOP = 'off'
PORT = '5432'
PROMPT1 = '%n@%/%R%# '
PROMPT2 = '%n@%/%R%#... '
PROMPT3 = '>> '
QUIET = 'off'
ROW_COUNT = '3'
SERVER_VERSION_NAME = '16.8 (Debian 16.8-1.pgdg120+1)'
SERVER_VERSION_NUM = '160008'
SHOW_ALL_RESULTS = 'on'
SHOW_CONTEXT = 'errors'
SINGLELINE = 'off'
SINGLESTEP = 'off'
SQLSTATE = '00000'
TEST = 'Hi!'
USER = 'postgres'
VERBOSITY = 'default'
VERSION = 'PostgreSQL 16.8 (Debian 16.8-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit'
VERSION_NAME = '16.8 (Debian 16.8-1.pgdg120+1)'
VERSION_NUM = '160008'

Кстати, настраивая файл ~/.psqlrc мы как раз изменяли некоторые переменные окружения.

Чтобы удалить переменную окружения используйте команду \unset, например:

postgres@postgres=# \unset TEST

postgres@postgres=# \echo :TEST
:TEST

Как видно выше, если переменной нет, то \echo просто выводит переданный текст.

Но переменную можно создавать не только с помощью \set, также можно в переменную записать результат запроса. Чтобы это сделать, нужно использовать в конце запроса вместо точки с запятой команду \gset:

postgres@postgres=# SELECT now() AS curr_time \gset
Время: 0,300 мс

postgres@postgres=# \echo :curr_time
2025-04-22 10:11:28.403395+03

В примере выше мы результат функции now() записали в переменную curr_time!

Дальше можете почитать статью: [Способы конфигурирования PostgreSQL].


Если понравилась статья, подпишись на мой канал в VK или Telegram.

Оставьте комментарий