Справочник системных ошибок и решений

Windows Server, Active Directory, 1С:Предприятие, СУБД, Linux, Cisco, MikroTik, Asterisk.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты на сайте предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, программного обеспечения, баз данных, сетевого оборудования и других компонентов инфраструктуры. Перед выполнением действий создайте резервную копию и по возможности протестируйте изменения в безопасной среде. Пользователь самостоятельно оценивает риски и несет ответственность за результат. При отсутствии необходимых знаний обратитесь к квалифицированному ИТ-специалисту.

ORA-01427 1С:Предприятие и СУБД

Ошибка ORA-01427: single-row subquery returns more than one row

Обновлено: 26.08.2026 · Официальная документация ↗
  • Ошибка ORA-01427: single-row subquery returns more than one row при выполнении SQL-запросов (SELECT, UPDATE, DELETE).
  • Скалярный подзапрос (в секции WHERE col = (...) или SELECT (...) FROM ...) возвращает множественные строки вместо одной.
  • Сбои тяжелых аналитических отчетов и интеграционных выгрузок.

1. Определение некорректного подзапроса

Ошибка возникает, когда оператор скалярного сравнения (=, !=, >, <) ожидает ровно одно значение:

-- Ошибочный запрос (если у одного клиента несколько заказов):
SELECT client_name, 
       (SELECT order_id FROM orders o WHERE o.client_id = c.id) AS order_id
FROM clients c;

2. Способ исправления А: Замена оператора на IN или ANY

-- Вместо WHERE col = (SELECT ...)
SELECT * FROM clients 
WHERE id IN (SELECT client_id FROM orders WHERE total > 1000);

3. Способ исправления Б: Использование агрегации или ограничения выборки

-- Получение последнего заказа через агрегацию:
SELECT client_name, 
       (SELECT MAX(order_id) FROM orders o WHERE o.client_id = c.id) AS last_order_id
FROM clients c;

4. Способ исправления В: Использование аналитических функций (ROW_NUMBER)

WITH ranked_orders AS (
    SELECT client_id, order_id,
           ROW_NUMBER() OVER (PARTITION BY client_id ORDER BY order_date DESC) as rn
    FROM orders
)
SELECT c.client_name, ro.order_id
FROM clients c
LEFT JOIN ranked_orders ro ON c.id = ro.client_id AND ro.rn = 1;
💡 Практика специалистов: Избегайте использования скалярных подзапросов в списке `SELECT` для больших выборок. Они работают по принципу nested loop для каждой строки и приводят к колоссальным задержкам I/O и CPU, помимо риска падения по ORA-01427.

Частые вопросы (FAQ)

Чем ORA-01427 отличается от ORA-01422?

ORA-01422 генерируется в PL/SQL при выполнении команды SELECT INTO. ORA-01427 генерируется SQL-движком при выполнении обычного SQL-запроса, содержащего скалярный подзапрос.

Почему ORA-01427 может не возникать на тестовой базе, но падать в Production?

На тестовой базе в таблицах мало данных (или нет дубликатов по ключам). На проде при росте объема данных подзапрос начинает возвращать 2+ строки, что приводит к внезапному сбою.

Как переписать UPDATE с подзапросом, чтобы избежать ORA-01427?

Используйте конструкцию MERGE INTO. Она позволяет прозрачно управлять связыванием наборов данных без риска падения от некорректных подзапросов в блоке SET.

Помогает ли ключевое слово ROWNUM = 1 внутри подзапроса?

Да, добавление WHERE ROWNUM = 1 гарантирует возврат не более одной строки, однако без правильного ORDER BY возвращенное значение может оказаться непредсказуемым.

Полезные материалы
Рекомендуем