Автор статьи: Артем Михайлов

PostgreSQL — это одна из самых популярных систем управления базами данных в мире. 

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

Синтаксические ошибки

SQL-запросы должны быть написаны с соблюдением определенного синтаксиса. Неверные конструкции и отсутствие необходимых ключевых слов могут привести к неожиданным ошибкам. Проверять синтаксис можно с помощью онлайн-парсеров, например, на сайте sqlfiddle.com. 

Некоторые примеры синтаксических ошибок в SQL-запросах в PostgreSQL и методы их решения:

Ошибка в использовании оператора

SELECT * FROM table WHERE field = 'value' AND OR field2 = 'value2'

Здесь используется оператор AND перед оператором OR, что недопустимо. Также неправильно использована конструкция "поле = значение OR поле = значение", необходимо использовать "поле = значение1 OR поле = значение2".

Правильный вариант выглядит так:

SELECT * FROM table WHERE field = 'value1' OR field2 = 'value2'

Использование специальных символов

SELECT * FROM table WHERE field LIKE '%value%'

Здесь используется подстановочный символ % внутри строки поиска. Однако, PostgreSQL использует другой символ для обозначения подстановочных знаков, это символ ''. Для использования подстановочного знака % необходимо использовать оператор LIKE с ESCAPE:

SELECT * FROM table WHERE field LIKE '%value%'

Ошибка выбора неправильного индекса

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

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

Пример кода:

CREATE TABLE test (
  id SERIAL PRIMARY KEY,
  name VARCHAR (50) NOT NULL,
  age INTEGER,
  email VARCHAR (100)
)

CREATE INDEX test_name_idx ON test (name)
-- Запрос имеет слишком низкую селективность
EXPLAIN ANALYZE SELECT * FROM test

Этот запрос не использует индекс, потому что таблица очень маленькая и использование индекса не приведет к улучшению производительности.

Ошибки работы с NULL-значениями

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

Например, если попытаться складывать NULL-значения в запросе, то результатом будет NULL. В следующем примере мы попытаемся сложить два поля, одно из которых имеет NULL-значение:

SELECT field1 + field2 FROM table1

Если одно из полей содержит NULL, то результатом запроса будет NULL. Чтобы избежать этой ошибки, можно использовать функцию COALESCE(), которая заменяет NULL на определенное значение:

SELECT COALESCE(field1, 0) + COALESCE(field2, 0) FROM table1

Это означает, что если поле содержит NULL, то он будет заменен на 0, и операция сложения будет выполнена с этим измененным значением, а не с NULL.

Другой пример ошибки связан с использованием операторов сравнения. Если попытаться сравнить значение поля с NULL с помощью оператора = или <>, то результатом будет неопределенное значение. Вместо этого для проверки на наличие NULL-значений используется оператор IS NULL или IS NOT NULL:

SELECT * FROM table1 WHERE field1 IS NULL;

Ошибки вложенности запросов

Вложенность — это как раз то, что позволяет SQL запросам возвращать более сложные результаты, например, соединять несколько таблиц в одном запросе или использовать подзапросы.

Одной из наиболее распространенных ошибок является некорректное использование оператора JOIN. В следующем примере мы попытаемся соединить две таблицы с помощью оператора JOIN:

SELECT * FROM table1 JOIN table2 ON table1.id = table2.id

Если обе таблицы содержат множество записей, то запрос может занять длительное время на выполнение из-за большого количества строк. Вместо этого рекомендуется использовать оператор WHERE для фильтрации записей:

SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);

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

Ошибки, которые могут привести к нарушению сохранности транзакций

Ошибки, которые могут привести к нарушению сохранности транзакций, могут возникнуть из-за ошибок в программном коде или из-за неправильных конфигурационных настроек. Некоторые из них включают:

  • Неверное использование оператора COMMIT: неправильное использование оператора COMMIT может привести к нарушению транзакционной сохранности. Например, если в результате работы нескольких операторов данные не были записаны в базу данных, а оператор COMMIT уже был выполнен.

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

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

Методы обеспечения сохранности транзакций

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

  • Использование оператора ROLLBACK: если транзакция была испорчена, то можно использовать оператор ROLLBACK, чтобы отменить изменения.

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

  • Оптимизация индексов: оптимизация индексов, используемых в запросах, может повысить быстродействие базы данных, что также поможет предотвратить нарушения сохранности.

Пример использования оператора ROLLBACK для восстановления целостности данных в базе данных:

BEGIN
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT

Если при выполнении оператора UPDATE возникнет ошибка, то можно использовать оператор ROLLBACK, чтобы отменить изменения в базе данных:

BEGIN
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
ROLLBACK

Подводя итоги

PostgreSQL является мощным инструментом для управления базами данных, однако, при использовании этой системы управления неизбежно могут возникать ошибки. Если вы не учитываете некоторые особенности, то ваш код может стать источником проблем с данными и производительностью. Тем не менее, следует помнить, что список ошибок не является исчерпывающим, и каждый проект имеет свои уникальные требования. Поэтому, чтобы минимизировать риски возникновения ошибок, рекомендуется тщательно проектировать свои программы и тестировать их перед выкладыванием в продакшен.


Приглашаем всех желающих на открытое занятие «МК по проектированию БД для несложного Enterprise-приложения». Что вас ждет на этом уроке:

  • Посмотрим, для чего на самом деле нужны нормальные формы.

  • Обсудим полезные подходы при создании связей.

  • Совместно спроектируем небольшую базу данных.

Записаться на открытый урок можно на странице онлайн-курса «PostgreSQL для администраторов баз данных и разработчиков».

Комментарии (4)


  1. motoroller95
    20.04.2023 16:33
    +1

    это шутка какая-то?


    1. varanio
      20.04.2023 16:33

      тоже не понял


  1. varanio
    20.04.2023 16:33
    -1

    И это в официальном блоге OTUS? Вы этому учите людей? Жесть какая-то


  1. Akina
    20.04.2023 16:33
    +1

    С точки зрения того, кто в теме, всё вышенаписанное - это тихий ужас и кошмар. Даже просто набор описанных ситуаций - и тот выглядит так, словно его составлял ГСЧ. Сами ситуации рассмотрены ну крайне поверхностно. Советы (там где они есть), по большей части либо никакие, либо вредные.

    Если сравнивать уровень вебинаров, которые проводят сотрудники OTUS по около-SQL темам, и уровень статей на Хабре, которые публикуются от имени того же OTUS, то создаётся впечатление, что это две разные фирмы. Небо и земля, как с разных планет...

    Грустно, товарищи.