Получение ошибки ORA-01422, когда существует только одна запись с условием

Я пытаюсь выбрать данные в процедуре Oracle PL/SQL. Когда я выбираю данные из таблицы напрямую вот так

SELECT * FROM CUSTOMER_USERS
 WHERE customer_id = 'cust1234'
   AND user_id = 'cust1234user'

Я получаю одну строку данных.

ID ПОЛЬЗОВАТЕЛЯ ПОЛЬЗОВАТЕЛЬСКИЙ ИД ОПИСАНИЕ ТОЛЬКО ДЛЯ ЧТЕНИЯ ОБНОВЛЕНО_BY CUST_API_KEY LAST_ACCESS_DATE cust1234user cust1234 1234 Корпорация Н Джейдо [api_key] 19.03.2024 02:31:37

Однако, когда я помещаю те же точные условия в запрос выбора с переменными, это вызывает ошибку с описанием «ORA-01422: точная выборка возвращает больше, чем запрошенное количество строк».

 customerID := 'cust1234';
 userID := 'cust1234user';
 SELECT CUST_API_KEY INTO v_encValue
   FROM CUSTOMER_USERS
  WHERE customer_id = customerID
    AND userid = userID;

Как это могло произойти? Эти два столбца составляют ПК, поэтому в этой таблице даже не может быть дубликатов по этим критериям. Я не могу сказать, что он думает о дополнительных строках.

userid и userID идентичны, и, скорее всего, это умножает возвращаемые строки
Barbaros Özhan 02.04.2024 23:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это объясняется в документации:

Если инструкция SQL ссылается на имя, которое принадлежит как столбцу, так и локальной переменной или формальному параметру, то имя столбца имеет приоритет.

Итак, когда вы это сделаете:

AND userid = userID

обе эти ссылки userid относятся к столбцу таблицы; ни то, ни другое не относится к переменной PL/SQL. Таким образом, это условие считается истинным, по крайней мере, для каждой строки, где userid не равно нулю. Обратите внимание, что по умолчанию немного другой случай не имеет значения; вы только что избежали той же проблемы с customer_id и customerID, добавив к ним подчеркивание.

Сделайте имена переменных PL/SQL отличными от имен столбцов. Обычно к переменным добавляют какой-нибудь префикс (например, l_userid), и если вы это сделаете, то установите соглашение об именах для вашего кода. В сохраненном блоке PL/SQL вы также можете указать переменные с именем блока (например, именем процедуры) и именем/псевдонимом таблицы — некоторые люди предпочитают это.

Ух ты, совершенно тупая ошибка. Вот к чему приводит попытка что-то сделать в конце 12-часового рабочего дня. Спасибо и MT0 за ваши ответы.

SausageBuscuit 03.04.2024 15:05

Когда вы используете идентификатор, Oracle попытается найти значение этого идентификатора из локальной области - в данном случае с помощью SQL-запроса. Если он не найдет его, он проверит значения идентификаторов во внешних областях (например, переменных PL/SQL). Итак, ваш запрос:

SELECT CUST_API_KEY INTO v_encValue
FROM   CUSTOMER_USERS
WHERE  customer_id = customerID
AND    userid = userID;

фактически то же самое, что:

SELECT CUST_API_KEY INTO v_encValue
FROM   CUSTOMER_USERS u
WHERE  u.customer_id = customerID
AND    u.userid = u.userID;

Где userID — это значение столбца, а НЕ переменная PL/SQL.

Всегда называйте переменные иначе, чем идентификаторы столбцов.

DECLARE
  v_customerID CUSTOMER_USERS.CUSTOMER_ID%TYPE  := 'cust1234';
  v_userID     CUSTOMER_USERS.USERID%TYPE       := 'cust1234user';
  v_encValue   CUSTOMER_USERS.CUST_API_KEY%TYPE;
BEGIN
  SELECT CUST_API_KEY
  INTO   v_encValue
  FROM   CUSTOMER_USERS
  WHERE  customer_id = v_customerID
  AND    userid      = v_userID;
END;
/

Другие вопросы по теме