Отчет об ошибке ORACLE ORA-01422: точная выборка возвращает больше запрошенного количества строк?

#sql #oracle

#sql #Oracle

Вопрос:

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

 DECLARE
      V_lname  VARCHAR2(15);
BEGIN
      SELECT last_name INTO v_lname
       FROM employees
       WHERE first_name='John';
       DBMS_OUTPUT.PUT_LINE  ('John' 's last name is : ' 
|| v_lname);

END;    
  

и у меня эта ошибка;

Отчет об ошибке ORA-01422: точная выборка возвращает больше запрошенного количества строк ORA-06512: в строке 4

Ответ №1:

Сообщение об ошибке понятно, вы можете получить только одно значение в свою v_lname переменную, поэтому PL / SQL выдает ошибку, сообщающую, что ваш запрос пытается вернуть несколько строк.

Либо:

  • Измените запрос, чтобы он возвращал только одну строку
  • Измените PL / SQL так, чтобы он мог обрабатывать несколько строк.

Я продемонстрирую второй вариант, поскольку я понятия не имею, какой сотрудник с именем «Джон» вам может понадобиться.

 begin
  for rJohn in 
    (select last_name
     from   employees
     where  first_name='John'
    ) loop
      dbms_output.put_line  ('John''s last name could be : '|| rJohn.last_name);
   end loop;
end;
/    
  

Здесь я использую неявный курсор для цикла (https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/cursor-FOR-LOOP-statement.html#GUID-62C9A3C8-82F9-468F-8D84-81672E67736D ) для выполнения dbms_output.put_line вызова по каждой строке, которую он находит для вашего запроса.

Ответ №2:

Два бесполезных варианта. Почему бесполезно? Потому что вам, вероятно, следует переписать запрос так, чтобы он возвращал только желаемое «John».

Кроме того, предложение: пусть переменная ссылается на тип данных столбца, не исправляйте его, например varchar2(15) . Что, если вам — когда-нибудь в будущем — придется изменить таблицу и увеличить столбец до varchar2(25) ? Ваш код с треском провалится.


Первый вариант: использовать агрегатную функцию, такую как MIN или MAX :

 DECLARE
  V_lname  employees.last_name%type;            --> this
BEGIN
  SELECT MAX(last_name)                         --> this
    INTO v_lname
    FROM employees
    WHERE first_name = 'John';

  DBMS_OUTPUT.PUT_LINE  ('John' 's last name is : ' || v_lname);
END;    
  

Другой вариант — использовать ROWNUM :

 DECLARE
  V_lname  employees.last_name%type;            --> this
BEGIN
  SELECT last_name
    INTO v_lname
    FROM employees
    WHERE first_name = 'John'
      AND rownum = 1;                           --> this

  DBMS_OUTPUT.PUT_LINE  ('John' 's last name is : ' || v_lname);
END;