Error ora 01427 single row subquery returns more than one row

If SQL engine expects your subquery to return a singular value, it may throw ORA-01427 when the result of the subquery contains multiple values.

There’re two error patterns related to ORA-01427 described in this post:

  1. SELECT with Equal Operator
  2. Job Failed by Trigger.

I will talk about them respectively in the following sections. In which, the first error pattern is very common and easy to solve. But the second one is not so obvious, you need more patience to solve it.

A. ORA-01427 in SELECT with Equal Operator

If SQL engine expects your subquery to return a single row, it may throw ORA-01427 when the subquery returns more than one row unexpectedly. For example:

SQL> select * from employees where department_id = (select department_id from departments where location_id = 1700);
select * from employees where department_id = (select department_id from departments where location_id = 1700)
                                               *
ERROR at line 1:
ORA-01427: single-row subquery returns more than one row

This is because the subquery in the SELECT statement returned more than one row for the predicate department_id, which does not comply with a singular value limited operator, the equal =. Consequently, the statement fails to continue and then throw ORA-01427 to notify developers.

Solutions

It’s just like that we wanted strictly only one item, but eventually it returned more than we expected.

Equal Sign Wants Only One. But Get More Eventually!

Equal Sign Wants Only One. But Get More Eventually!

1. Using IN Operator

Then what operator is used to prevent ORA-01427 in SELECT statement? In practice, SELECT should use IN operator instead of = (equal operator) in order to accommodate more than one row returned by the subquery.

SQL> select * from employees where department_id in (select department_id from departments where location_id = 1700);

A similar exception that relates to returned number mismatch is ORA-00913: too many values. But they have different error patterns.

More comparison conditions like ANY, SOME or ALL should also be helpful to accept more than one row in your statements so as to avoid ORA-01427 in subquery statement.

2. Using = (Equal) Operator

If you really want to use an equal operator to confine the scope of returned rows as one, you have to limit the number of rows returned of queries to only one row. That’s how we workaround it.

SQL> select * from employees where department_id = (select * from (select department_id from departments where location_id = 1700) where rownum = 1);

An order by clause is more appropriate in the above subquery so as to be close to your expectation.

select * from employees where department_id = (select * from (select department_id from departments where location_id = 1700 order by manager_id) where rownum = 1);

3. Do Not Use DISTINCT with Equal Operator

Adding one distinct keyword before column list cannot prevent ORA-01427, because the number of rows returned by the subquery is still unpredictable.

SQL> select * from employees where department_id = (select distinct department_id from departments where location_id = 1700);
select * from employees where department_id = (select distinct department_id from departments where location_id = 1700)
                                               *
ERROR at line 1:
ORA-01427: single-row subquery returns more than one row

No surprises, we saw ORA-01427 in SELECT statement once again.

B. ORA-01427 in Job Failed by Trigger

ORA-12012 and ORA-01427

ORA-12012 and ORA-01427

Same error ORA-01427 could accompany ORA-12012 in the alert log when one scheduled job failed to complete successfully.

ORA-12012: error on auto execute of job 10
ORA-01427: single-row subquery returns more than one row
ORA-06512: at line 21

Trigger Caused ORA-01427

According to this error pattern in the above, we saw ORA-01427 in a failed job with ORA-12012. We’d better check some triggers, especially logon and logoff ones to see if there’s any chances to block the job process accidentally. Noticeably, which is Job No. 10 in this case.

You should check the content of the job in the first place to see if there’re any chances to throw ORA-01427. Perhaps you should disable each trigger at a time in order to isolate and identify the cause. Or just turn them off temporarily.

Further reading: How to Kill Session in Logon Trigger

C. MySQL Subquery Returns More Than 1 Row

The same error pattern occurs in MySQL, incorrect number of rows from subquery will result ERROR 1241, let’s see its content:

ERROR 1242 (ER_SUBSELECT_NO_1_ROW)
SQLSTATE = 21000
Message = «Subquery returns more than 1 row»

This error is caused by the subquery that must return at most one row but returns multiple rows eventually.

mysql> select * from items where id = (select item_id from orders);

If the subquery returns just one row, the above query will work without errors. If it returns more than one row, we will see error 1242.

The solution is the same as we mentioned in the above sections. Beside IN operator, we can also use ANY, one of comparison conditions to fix the query, for example:

mysql> select * from items where id = any (select item_id from orders);

This is how comparison conditions work for MySQL.

The error ORA-01427 is raised, when a sub-query returns more than one row to an Equality or in-Equality operator.

ORA-01427

The reason being there are restrictions on the legal comparison operators.The single row subquery operator are

Symbol Meaning
= equal
> greater than
>= greater than or equal
< less than
<= less than or equal
<> not equal
!= not equal

So whenever you are using these single row subquery operator, if you return more than one row,it will start throwing the error

How to resolve the error ORA-01427

(1) either we change the query to use Multiple -row Subquery Operators 

Multiple-row Sub-query Operators
Symbol Meaning
IN equal to any member in a list
NOT IN not equal to any member in a list
ANY returns rows that match any value on a list
ALL returns rows that match all the values in a list

(2) We look at the query and find out what is happening, why it is returning more rows than expected. Like the way we resolved this error for Concurrent Manager issue. It is generally advisable  use the sub-query based on primary key in order to get consistent result,

Lets us take a look at few example

Few Examples

(1) While starting the concurrent Manager in the EBS environment, we were getting below error

Cause: cleanup_node failed due to ORA-01427: single-row subquery returns more than one row
ORA-06512: at "APPS.FND_CP_FNDSM", line 29
ORA-06512: at line 1.

This error happens when we have more than two FNDSM of FNDIM defined for the node.So we selected the node name of all the concurrent Manager in the system

Solution
We can resolve the solution manually through below update

SQL> select CONCURRENT_QUEUE_NAME,NODE_NAME from fnd_concurrent_queues group by CONCURRENT_QUEUE_NAME,NODE_NAME;
CONCURRENT_QUEUE_NAME NODE_NAME
FNDSCH SUNTEST
PODAMGR SUNTEST
FTE_TXN_MANAGER SUNTEST
FNDSM_20151_SUNTEST SUNTEST
FNDICM SUNTEST
FNDTMTST SUNTEST
STANDARD SUNTEST
FNDIM_SUNTEST SUNTEST
FNDIM_20153_SUNTEST SUNTEST
WFMLRSVC SUNTEST
XDP_Q_FE_READY_SVC SUNTEST
WMSTAMGR SUNTEST
INVMGR SUNTEST
AMSDMIN SUNTEST
FNDSM_SUNTEST SUNTEST

We can see there are two FNDSM and FNDIM for the node SUNTEST.


FNDSM_20151_SUNTEST SUNTEST
FNDIM_SUNTEST SUNTEST
FNDIM_20153_SUNTEST SUNTEST
FNDSM_SUNTEST SUNTEST

Lets do the update now

SQL> update fnd_concurrent_queues set NODE_NAME=null where CONCURRENT_QUEUE_NAME='FNDSM_20151_SUNTEST';
1 row updated.
SQL> update fnd_concurrent_queues set NODE_NAME=null where CONCURRENT_QUEUE_NAME='FNDIM_20153_SUNTEST';
1 row updated.
SQL> commit;
Commit complete.
SQL> select CONCURRENT_QUEUE_NAME,NODE_NAME from fnd_concurrent_queues group by CONCURRENT_QUEUE_NAME,NODE_NAME;
CONCURRENT_QUEUE_NAME NODE_NAME
FNDSCH SUNTEST
PODAMGR SUNTEST
FTE_TXN_MANAGER SUNTEST
FNDSM_20151_SUNTEST  
FNDICM SUNTEST
FNDTMTST SUNTEST
STANDARD SUNTEST
FNDIM_SUNTEST SUNTEST
FNDIM_20153_SUNTEST  
WFMLRSVC SUNTEST
XDP_Q_FE_READY_SVC SUNTEST
WMSTAMGR SUNTEST
INVMGR SUNTEST
AMSDMIN SUNTEST
FNDSM_SUNTEST SUNTEST

Or we can run conc clean and run autoconfig again to resolve the issue

SQL> EXEC FND_CONC_CLONE.SETUP_CLEAN;
COMMIT;
EXIT;

(2) Another example would be

SELECT * FROM employers
WHERE dept_id = (SELECT dept_id
FROM dept);

This will fail as we are selecting all dept_id in subquery while expecting one. This will succeed if dept is having one rows only. To resolve we need to add some where clause in subquery so that it returns one value

SELECT * FROM employers
WHERE dept_id = (SELECT dept_id
FROM dept where location='NEWYORK');

or

We can put in operator in place of equality operator

SELECT * FROM employers
WHERE dept_id in (SELECT dept_id
FROM dept);

I hope you this content on ORA-01427: single-row subquery returns more than one row. Please do provide feedback

Also Reads
ORA-00900 : Invalid Sql statement : check out this post for the various solutions for ORA-00900 invalid sql statement.Reasons for the error.How to debug and resolve it quickly,
ORA-03113 : Check out method to resolve ORA-03113: end-of-file on communication channel. This error could happen in database startup, running program
ora-29283: invalid file operation : check out this post on how to resolve ORA-29283 : invalid file operation
ORA-29285: file write error : ORA-29285: file write error is the common error while doing file handling operation.Check out this post on various reason and solution on how to solve it
ORA-00054 : ORA-00054: resource busy and acquire with NOWAIT specified with DDL statement,select for update,forms nowait locks,DDL_LOCK_TIMEOUT

Ezoic

November 10, 2020

When you run a SQL Statement with Subquery, you can get ” ORA-01427: Subquery returns more than one row ” error.

ORA-01427 single-row subquery returns more than one row

Error details are as follows.

SELECT *

FROM employee

WHERE emp_id = (SELECT emp_id

FROM person

WHERE person_name = 'Mehmet') ;
ORA-01427 single-row subquery returns more than one row

Cause: The outer query must use one of the keywords ANY, ALL, IN, or NOT IN to specify values to compare because the subquery returned more than one row.

Action: Use ANY, ALL, IN, or NOT IN to specify which values to compare or reword the query so only one row is retrieved.

ORA-01427

This error ORA-01427: Subquery returns more than one row is related with the keywords ANY, ALL, IN, or NOT IN to specify values to compare because the subquery returned more than one row.

single-row subquery returns more than one row

If your SQL Statement ( single row subquery ) returns only one row, then you need to use the equal comparison operators (=,<,>,<> ).

But If your SQL Statement ( multiple row subquery ) returns more than one row ( multiple rows ), then you need to use the Multiple-row Sub-query Operators like ( IN, ANY, ALL and etc.. )

To solve the above SQL Statement, you can use the IN operator instead of = operator as follows.

SELECT *
FROM employee
WHERE emp_id IN (SELECT emp_id
FROM person
WHERE person_name = 'Mehmet') ;



This solution is valid for both Select and Update, Insert and Delete operations.

If you got this error during the Update, Insert and Delete operations, then Check your Statement if Subquery returns more than one row, then use the Multiple-row Sub-query Operators like ( IN, ANY, ALL and etc.. )

Do you want to learn more details about Oracle SQL, then read the following articles.

Oracle SQL Tutorials For Beginners – Learn Oracle SQL from scratch with Oracle SQL Online Course

 3,519 views last month,  3 views today

About Mehmet Salih Deveci

I am Founder of SysDBASoft IT and IT Tutorial and Certified Expert about Oracle & SQL Server database, Goldengate, Exadata Machine, Oracle Database Appliance administrator with 10+years experience.I have OCA, OCP, OCE RAC Expert Certificates I have worked 100+ Banking, Insurance, Finance, Telco and etc. clients as a Consultant, Insource or Outsource.I have done 200+ Operations in this clients such as Exadata Installation & PoC & Migration & Upgrade, Oracle & SQL Server Database Upgrade, Oracle RAC Installation, SQL Server AlwaysOn Installation, Database Migration, Disaster Recovery, Backup Restore, Performance Tuning, Periodic Healthchecks.I have done 2000+ Table replication with Goldengate or SQL Server Replication tool for DWH Databases in many clients.If you need Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS Consultancy and Training you can send my email adress [email protected].-                                                                                                                                                                                                                                                 -Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS ve linux Danışmanlık ve Eğitim için  [email protected] a mail atabilirsiniz.

oracle tutorial webinars

ORA-01427

Operating within database software can sometimes feel like navigating a minefield. The vast expanse of data sets, tables and functions can leave a user tip-toeing throughout, careful not to enter a mistaken query or improper syntax that could halt the data in an instant. A software as user-friendly and accessible as Oracle can even occasionally feel problematic, perhaps seeming most daunting when writing statements for it to process. The ORA-01427 error can be the manifestation of these fears. Fortunately, the error has a couple of basic approaches that will remedy the situation and have your code back up and running in no time.

The Problem

The ORA-01427 is a straightforward query error in Oracle. The cause of the error is a subquery returning more than one row of information. This error in multi-row returns on the subquery originates from an outer query failing to use appropriate, designated keywords to specify values for comparison in the subquery.

Before we continue with solving this error, let us briefly discuss subqueries in Oracle. The definition of an Oracle subquery is fairly tautological: a subquery is a query within a query. To review, a query is simply a function used to retrieve specific data from the tables within a database. The query allows a user to view data spread across a database on one single datasheet. A subquery furthers this process, allowing the user to issue a query within the SQL statement to refine a request.

A subquery can be placed in a WHERE clause, a FROM clause, or a SELECT clause depending on its purpose. Most often the subquery will be proposed in the WHERE clause (also known as a “nested subquery”). Oracle will allow a user to issue subqueries in the WHERE clause up to 255 levels. A subquery can also be in the FROM clause (a “inline subquery”) or a SELECT clause, however a subquery placed in the SELECT clause must return a single value.

The Solution

One necessity of the subquery is that it returns just one row or otherwise includes certain keywords in the outer query. The keywords are ANY, ALL, IN or NOT IN. These will aid Oracle in specifying values to compare, creating a concise return.

This brings us to our solution for the ORA-01427 error. There are essentially two options to take. The first is to rewrite the query so that the subquery will only return a single row, thus eliminating the source of the error. This will require a user to rethink how they wish to acquire the data that they were initially searching for. The alternative option that will allow the user to more quickly assume where they left off is to change the query by inserting one of the previously mentioned keywords (ANY, ALL, IN or NOT IN). Let us look at how this would play out in a brief example.

Perhaps the user attempted to issue the following SQL statement:

SELECT *

FROM employers

WHERE client_id = (SELECT client_id

FROM clients

WHERE clients_name = ‘Walmart’) ;

If more than one instance in the client’s table of the clients_name ‘Walmart’ existed, the following would be prompted:

ORA-01427: single-row subquery returns more than one row

The user can then correct the statement by utilizing an IN condition, which is used to reduce the need for multiple OR conditions in SELECT statements:

SELECT *

FROM employers

WHERE client_id IN (SELECT client_id

FROM clients

WHERE clients_name = ‘Walmart’) ;

This will eliminate the ORA-01427 error message from occurring.

Looking forward

Perhaps what takes database managers the longest to master is coding SQL statements. It can be incredibly easy to make what seem like the simplest of mistakes after they are corrected. Oracle has taken a lot of steps in mitigating user frustration when coding, but errors can always arise. If you are finding that you are having a difficult time with coding SQL statements, or maybe want a little more advice on creating cleaner statements, feel free to contact a licensed Oracle consultant for more information.

Приходилось сталкиваться с такой ошибкой?
Читаем дальше.

Зачем же использовать такие подзапросы, коль возможны ошибки?
Но ведь удобно же!

Пример.
Ест у нас запрос, который скажем выводит некий список расходных транзакций модуля Inventory


SELECT ...
FROM mtl_material_transactions mmt
WHERE ...

Нам здесь не важно, что выводит этот список и по какому критерию, но нужно отметить, что за многоточиями может скрываться не один десяток, а то и не одна сотня, строк кода.

Но вот возникла необходимость добавить в запрос еще одну колонку — счет ГК с которого списали ТМЦ. Мы знаем, что в таблице mtl_transaction_accounts по коду складской транзакции можно найти две полупроводки, одна с положительной суммой (дебет), другая с отрицательной (кредит). Ну вот значит счет кредитовой полупроводки нас и интересует. Самым простым способом «вклиниться» в существующий запрос будет что-то такое:


SELECT ...
,(SELECT mta.reference_account
FROM mtl_transaction_accounts mta
WHERE mta.transaction_id = mmt.transaction_id
AND mta.base_transaction_value < 0
) AS "Счет учета ТМЦ"
FROM mtl_material_transactions mmt
WHERE ...

Запускаем — беда!
ORA-01427: подзапрос одиночной строки возвращает более одной строки

Почему возникла ошибка?
Для некоторых складских транзакций наши предположения оказались неверны.
И это плохо.
А плохо потому, что проблемными могут оказаться всего лишь пара записей из нескольких тысяч, а мы не увидим ничего, т.к. весь запрос возвращает ошибку.

Прежде чем начинать исправить ситуацию, нужно понять а какой собственно результат запроса был бы приемлемым, учитывая наличие складских транзакций с неожиданными распределениями(проводками)?

А хотелось бы, чтобы запрос таки отработал, и все сотни, а то и тысячи (а то и больше) «правильных» записей мы увидели, а для тех нескольких ошибочных пусть вернется хоть что-нибудь — мы с ними отдельно разберемся, главное чтобы их отличить от правильных можно было.

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

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


SELECT ...
,(SELECT MAX(mta.reference_account)
FROM mtl_transaction_accounts mta
WHERE mta.transaction_id = mmt.transaction_id
AND mta.base_transaction_value < 0
) AS "Счет учета ТМЦ"
FROM mtl_material_transactions mmt
WHERE ...

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

Тем не менее, главный шаг к правильному решению уже сделан, осталось чуть-чуть. Ведь во всех случаях, где подзапрос возвращает одну запись, использование MAX не является ошибкой — максисум от одного значения равен самому значению. Значит нам нужно в тех случаях, где подзапрос возвращает одну запись — использовать
MAX (ну хотите MIN). А там где больше чем одну — возвращать значение, указывающее на ошибку.

Так ведь это же совсем не сложно сделать!
Количество записей подзапроса — это COUNT(*), условную логику можно реализовать через CASE или, по старинке, через DECODE. Не забудем и про то, что подзапрос может совсем не вернуть записей:

  
SELECT ...
,(SELECT DECODE(COUNT(*), 1,MAX(mta.reference_account), 0,NULL, -999)
FROM mtl_transaction_accounts mta
WHERE mta.transaction_id = mmt.transaction_id
AND mta.base_transaction_value < 0
) AS "Счет учета ТМЦ"
FROM mtl_material_transactions mmt
WHERE ...

Всё.
Теперь не только ошибка ORA-01427 больше не появится, но и можно легко найти те записи, где наша логика определения счета учета ТМЦ дала сбой.

Дополнительно отметим, что так как mta.reference_account имеет числовой тип данных, то и ошибочное значение должно быть числовым (-999). Для строковых типов данных можно было бы использовать — ‘Ошибка’ или ‘ORA-01427’. Для дат — что-то из далекого прошлого или будущего. Важно лишь, чтобы такого значения гарантированно не было в реальных данных.

Подводим итоги.
При использовании подзапросов вместо


SELECT
(SELECT t2.column
FROM table2
WHERE ...)
FROM table1 t1
WHERE ...

лучше использовать


SELECT
(SELECT DECODE(COUNT(*), 0,NULL, 1,MAX(t2.column), 'ORA-01427')
FROM table2
WHERE ...)
FROM table1 t1
WHERE ...

И не забыть разобраться почему появились записи с ‘ORA-01427’

Понравилась статья? Поделить с друзьями:
  • Error ora 01422 exact fetch returns more than requested number of rows
  • Error ora 00913 too many values
  • Error ora 00900 invalid sql statement
  • Error ora 00257 archiver error connect internal only until freed
  • Error ora 00001 unique constraint violated