Ошибка Apex 5 и PL/SQL в операторах select

У меня есть этот код PL/SQL, который делает выбор из таблицы и вставляет во временную таблицу, когда найдено точное совпадение, но в отдельном представлении должны отображаться все совпадения, если они найдены. Итак, скажем, у меня есть номер детали, называемый SKU001, и я набираю его в поле, он должен отображать в одном поле и вставлять в другую таблицу. Когда я только набираю SKU, он не должен вставляться в другую таблицу, а только отображать все совпадения, такие как SKU001, SKU002, SKU003 и т. Д. Код работает, но я продолжаю получать ошибки, которые не имеют смысла, поскольку я обслуживаю ошибки .

Итак, позвольте мне попытаться немного разбить его. скажем, у меня есть таблица с именем TABLENAME со следующим:

NAME  | STOCKCODE | PRICE | other columns ...
Item1 | SKU001    | 12.99
Item2 | SKU002    | 13.99
Item3 | SKU003    | 14.99

Во временной таблице есть только столбцы NAME, STOCKCODE и PRICE.

Чтобы получить данные, у меня есть 2 табличные формы, которые выполняют следующее.

select * from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');

а для TEMPTABLE есть Apex page SQL.

select STOCKCODE, NAME, PRICE TEMPTABLE where SESSION_USER=:P4_USER


DECLARE
l_stock VARCHAR2(200);
l_name VARCHAR2(200);
l_price VARCHAR2(200);
BEGIN
select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where (NAME=:P4_SEARCH) or (BARCODE=:P4_SEARCH) or (STOCKCODE=:P4_SEARCH);
insert into TEMPTABLE (STOCKCODE, NAME, PRICE) 
 values (l_stock, l_name, l_price);
     exception
when too_many_rows then
select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');
when no_data_found then
select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');
END;

Когда я только это:

BEGIN
select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');
END;

это работает отлично каждый раз.

Если я выполню только это:

BEGIN
select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where (NAME=:P4_SEARCH) or (BARCODE=:P4_SEARCH) or (STOCKCODE=:P4_SEARCH);
insert into TEMPTABLE (STOCKCODE, NAME, PRICE)
END;

но при запуске всего сценария PL/SQL, как указано выше, я получаю ошибки как таковые: когда я ищу SKU001, он отображает элемент поиска и добавляет его в TEMPTABLE, но когда я ищу SKU, он выдает мне ошибку:

ORA-01422: exact fetch returns more than requested number of rows 
ORA-06512: at line 23 
ORA-01403: no data found

ПРИМЕЧАНИЕ!! Отображаемая здесь строка 23 не является строкой 23 в приведенном выше коде из-за форматирования моего браузера, строка 23 выглядит следующим образом:

22 ->     when no_data_found then
23 -> select STOCKCODE, NAME, PRICE into stock, name, price from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');

В то же время, если я очищаю или сбрасываю сеанс, он отображает:

ORA-01403: no data found
ORA-06512: at line 23
ORA-01403: no data found

Что мне кажется странным, потому что я добавляю exception для no_data_found, а также для too_many_lines

Что я здесь делаю неправильно? Я надеюсь, что я предоставил достаточно информации здесь для того, чтобы это имело смысл.

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


person Community    schedule 26.10.2016    source источник


Ответы (4)


Первый запрос не вызовет исключение too_many_rows, если у вас нет дубликатов barcode stockcode или name

просто поднимите исключение для no_data_found, потому что первый запрос требует точного совпадения, не поднимет данные, а затем запустит второй запрос.

DECLARE
L_STOCK VARCHAR2(200);
L_BARCODE VARCHAR2(200);
L_NAME VARCHAR2(200);
L_PRICE VARCHAR2(200);
BEGIN
select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME 
where (:P4_SEARCH=NAME) or (:P4_SEARCH=BARCODE) or (:P4_SEARCH=STOCKCODE);
insert 
into TEMPTABLE (STOCKCODE, NAME, PRICE)
values (l_stock, l_name, l_price);
exception
when no_data_found 
then
select STOCKCODE, NAME, PRICE
into stock, name, price
from TABLENAME 
where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');
end;

Затем это должно дать вам эфирное совпадение SKU001 в первом запросе и вставить в TEMPTABLE или, если частичное совпадение, отображать только результаты последнего запроса.

person Community    schedule 26.10.2016
comment
имеет смысл, но думаю, что я пробовал это, позвольте мне проверить. - person ; 26.10.2016
comment
Что за черт. Это работает, без ошибок и работает в обе стороны!! Спасибо!! - person ; 26.10.2016
comment
;) в любое время, рад, что смог помочь - person ; 26.10.2016

Попробуйте INSERT..SELECT

insert into TEMPTABLE (STOCKCODE, NAME, PRICE)
select STOCKCODE, NAME, PRICE
from TABLENAME
where (NAME=:P4_SEARCH) or (BARCODE=:P4_SEARCH) or (STOCKCODE=:P4_SEARCH);
person sagi    schedule 26.10.2016
comment
Привет, спасибо за ответ. Это также все еще работает с некоторыми вставками, но по-прежнему дает те же самые ошибки и, кажется, недовольно строкой 23, как упоминалось в моем вопросе. Поэтому, если я запускаю ваш запрос один, он работает так же, как и мой, но не в полном сценарии PL/SQL. - person ; 26.10.2016

Ошибка «no_data_found» может быть вызвана самим Oracle. Он не может найти подходящее сообщение, чтобы показать вам.

Но поместили ли вы исключение «no_data_found» в обработчик исключений?

declare
  ...
begin
  ...
exception
  when no_data_found
  then
    select STOCKCODE, NAME, PRICE 
    into stock, name, price 
    from TABLENAME 
    where regexp_like(NAME, :P4_SEARCH, 'i') 
    or regexp_like(BARCODE, :P4_SEARCH, 'i') 
    or regexp_like(STOCKCODE, :P4_SEARCH, 'i');

  when others
  then
     ...
end;
person wieseman    schedule 26.10.2016
comment
Я думал, что, когда данные не найдены, я просто задаю ему альтернативный запрос вместо отображения сообщения. Я ошибаюсь? - person ; 26.10.2016
comment
С обработчиком исключений вы можете делать почти все, что захотите. Например выполнить запрос, запустить другую процедуру, показать сообщение. Я отредактировал свой ответ. - person wieseman; 26.10.2016
comment
У меня есть оба этих исключения в моем коде no_data_found и too_many_lines - person ; 26.10.2016
comment
Если вы выполните следующий запрос, сколько строк получится в результате? выберите STOCKCODE, NAME, PRICE из TABLENAME, где (NAME=:P4_SEARCH) или (BARCODE=:P4_SEARCH) или (STOCKCODE=:P4_SEARCH); Вы знаете значение :p4_search? - person wieseman; 26.10.2016
comment
Идея состоит в том, что я могу выполнить либо запрос регулярного выражения, либо использовать части столбца для отображения результатов (все результаты совпадают), но когда будет найдено точное совпадение, вставить в TEMPTABLE. P4_SEARCH — это поле поиска в Apex, в котором я могу искать либо ШТРИХ-КОД, НАЗВАНИЕ, АКЦИОНЕРНЫЙ КОД. поэтому P4_SEARCH является текстовым полем. Я могу выполнить поиск sku и получить результаты для SKU001, SKU002, SKU003, но если искать SKU001 как полное слово, он должен найти уникальное совпадение и вставить его в TEMPTABLE. - person ; 26.10.2016
comment
хорошо, теперь приливы повернулись. Сделал мелкие изменения и теперь ошибок больше не выдает, но теперь вставка не работает без ошибок, поиск работает. :( - person ; 26.10.2016

На мой взгляд, вы ловите два исключения.

При поиске SKU вы поймаете исключение no_data_found при выполнении запроса:

select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where (NAME=:P4_SEARCH) or (BARCODE=:P4_SEARCH) or (STOCKCODE=:P4_SEARCH)

Затем вы выполняете новый запрос из раздела when no_data_found:

select STOCKCODE, NAME, PRICE
into l_stock, l_name, l_price
from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');

но этот запрос вызывает новое исключение too_many_rows. Да, этот запрос может повторно настроить несколько строк с условием regexp_like(STOCKCODE, 'SKU', 'i'). Но когда вы используете предложение into, вы должны быть уверены, что ваш запрос вернет только одну запись. Чтобы избежать исключения too_many_rows, вы можете попробовать изменить свой запрос в разделе исключений, как советовал @sagi:

when no_data_found then
    insert into TEMPTABLE (STOCKCODE, NAME, PRICE)
    select STOCKCODE, NAME, PRICE
    from TABLENAME where regexp_like(NAME, :P4_SEARCH, 'i') or regexp_like(BARCODE, :P4_SEARCH, 'i') or regexp_like(STOCKCODE, :P4_SEARCH, 'i');
person AlexSmet    schedule 26.10.2016
comment
Привет, спасибо за ответ. Вы правы, говоря, что новый запрос выполняется, когда no_data_found, но когда мы доходим до выполнения, он не вызывает новое исключение из-за запроса регулярного выражения для соответствия частям значений столбца, также нет оператора вставки, как в первый запрос. Последний запрос невозможен, я не могу ничего вставить в TEMPTABLE, если no_data_found он может вставить только тогда, когда точное совпадение найдено в соответствии с первым выбором. - person ; 26.10.2016