#Что происходит и когда возникает
При выполнении INSERT ... RETURNING, UPDATE ... RETURNING или DELETE ... RETURNING приложение сообщает «SQL logic error», «near RETURNING: syntax error» либо «SQLITE_ERROR». В SQLite эта конструкция доступна с 3.35.0 (12 марта 2021 года). Версия команды sqlite3, Python или PHP на другом сервере ничего не доказывает: проверять нужно библиотеку в том процессе, где происходит сбой.
#Возможные причины: как различить
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Старая SQLite в приложенииRETURNING отсутствует в SQLite до 3.35.0. | SELECT sqlite_version() внутри соединения возвращает 3.34.x или ниже. | Обновить связанную библиотеку приложения либо использовать совместимый SQL. |
| Приложение использует другую библиотекуСистемный sqlite3 и библиотека PHP/Python могут быть разных версий. | sqlite3 --version и SELECT sqlite_version() из приложения показывают разные значения. | Проверять в работающем процессе, не подменять библиотеку вслепую. |
| Неверное расположение RETURNINGRETURNING разрешён только в верхнеуровневых INSERT, UPDATE, DELETE, не в произвольном SELECT или вложенном запросе. | Версия не ниже 3.35, но тестовый корректный INSERT работает, а исходный SQL не выполняется. | Исправить синтаксис и учитывать ограничения RETURNING. |
#Пошаговая диагностика и исправление
- Зафиксируйте исходный запрос и сообщениеПрименять, если ошибка появилась после обновления кода или переезда. Найдите в журнале только SQL-оператор (без паролей и личных данных), номер версии приложения и точный текст ошибки. Отдельно отметьте, это INSERT, UPDATE или DELETE. Ничего в базе пока не меняйте; если нет доступа к журналу, попросите разработчика показать диагностический вывод.
- Проверьте версию внутри приложенияЕсли проблема в Python, откройте терминал в той же виртуальной среде и запустите пример ниже: команда выведет версию библиотеки SQLite, встроенной в модуль sqlite3. Если ошибка из PHP, выполните в локальном служебном скрипте (не публикуйте его на сайте) запрос SELECT sqlite_version() через то же PDO-соединение и удалите файл после проверки. В sqlite3-консоли выполните SELECT sqlite_version();. Если версия меньше 3.35.0, переходите к выбору совместимости.
- Повторите безопасный пример без рабочей таблицыОткройте терминал: Linux — меню приложений → «Терминал», Windows — «Пуск» → «Терминал», macOS — «Терминал». Выполните пример Python с подключением :memory: из блока ниже; права администратора не нужны. В версии 3.35+ выводится число 1. Если появляется ошибка синтаксиса, подтвердите версию и не тестируйте вставки в рабочей базе.
- Проверьте синтаксис исходного SQLЕсли тест в памяти прошёл, убедитесь, что RETURNING находится в конце верхнеуровневого INSERT/UPDATE/DELETE и возвращаемые им строки действительно считываются приложением. SQLite не разрешает поместить UPDATE ... RETURNING внутрь CTE как самостоятельную таблицу. Вынесите операцию из вложенного запроса; сначала испытайте на копии, затем повторите только штатную операцию.
- Выберите обновление без подмены системных библиотекЕсли версия устарела, подготовьте тестовую среду с поддерживаемым выпуском языка/драйвера и SQLite 3.35+; проверьте версии из самого приложения и тесты транзакций. На работающем сервере не заменяйте системный libsqlite3 вручную: это может нарушить зависимости. Вариант с обновлением согласуйте с владельцем приложения и сделайте резервную копию.
- Используйте совместимую схему без RETURNING, если обновление невозможноДля одиночного INSERT в пределах одного соединения иногда можно выполнить обычный INSERT и прочитать идентификатор через last_insert_rowid() либо API lastrowid — только если таблица использует подходящий ROWID и этот идентификатор вам нужен. Выполните чтение в том же соединении непосредственно после вставки; это не заменяет RETURNING для UPDATE/DELETE и таблиц WITHOUT ROWID. Испытайте в отдельной базе, не копируйте пример на боевую таблицу.
- Повторите исходную операцию в тестовой копииПосле обновления драйвера или исправления SQL запустите ранее падавшую операцию на копии базы, сравните возвращённые строки и количество изменений, затем выполните ROLLBACK, если она была диагностической. Если ошибка сохранилась при 3.35+, сохраните полный SQL без конфиденциальных значений и перейдите к документации ограничений RETURNING.
#Команды и проверочные примеры
python3 -c "import sqlite3; print(sqlite3.sqlite_version)"import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE demo(id INTEGER PRIMARY KEY, name TEXT)")
print(con.execute("INSERT INTO demo(name) VALUES (?) RETURNING id", ("Проба",)).fetchone())
con.close()#Как проверить результат
Версия SQLite не ниже 3.35.0, тест в :memory: выводит (1,), а операция приложения в тестовой копии возвращает ожидаемые данные. Важно проверить именно используемый драйвер, а не только внешнюю команду sqlite3.
#Если не помогло
При «near RETURNING» на новой версии проверьте границы SQL-оператора, запрет на RETURNING в триггерах и вложенных запросах и поддержку драйвером набора строк. При системной ошибке загрузки библиотеки верните прежний пакет или окружение и обратитесь к ответственному за сервер.