Ошибка ORA-01422, возникающая при выполнении хранимой процедуры из задачи сценария SSIS, однако она выполняется успешно при запуске из SQL Developer

Я выполняю хранимую процедуру Oracle из задачи сценария SSIS, и пакет используется для успешного выполнения без каких-либо проблем. Однако внезапно он начал давать сбой из-за ошибки ORA-01422.

Не было никаких изменений пакетов, изменений хранимых процедур или изменений конфигурации, из которой извлекается соединение.

Кроме того, SELECT INTO, который у меня есть на стороне Oracle в хранимой процедуре, просто выполняет SELECT COUNT(1) INTO - поэтому я не совсем уверен, как он может получить более 1 строки, что, насколько я понимаю, предполагает ошибка.

Кроме того, хранимая процедура успешно запускается при выполнении вручную из Oracle SQL Developer, что меня сбивает с толку.

Я работаю в основном с T-SQL и SSIS, поэтому не уверен, что что-то упускаю при попытке прочитать ошибку PL/SQL.

Обновлено:

Это мой код задачи скрипта:

OracleConnection OracleConn = new OracleConnection(Dts.Variables["OracleConnectionString"].Value.ToString());

OracleCommand OracleCmd = new OracleCommand("TEST.TEST_DATA", OracleConn);
OracleCmd.CommandType = CommandType.StoredProcedure;

OracleParameter ins_count = new OracleParameter("ins_count", OracleDbType.Int32);
ins_count.Direction = ParameterDirection.Output;

OracleCmd.Parameters.Add(ins_count);

OracleParameter upd_count = new OracleParameter("upd_count", OracleDbType.Int32);
upd_count.Direction = ParameterDirection.Output;

OracleCmd.Parameters.Add(upd_count);

OracleParameter rev_count = new OracleParameter("rev_count", OracleDbType.Int32);
rev_count.Direction = ParameterDirection.Output;

OracleCmd.Parameters.Add(rev_count);

OracleConn.Open();
OracleCmd.ExecuteNonQuery();

string returnValue = ins_count.Value.ToString();
Dts.Variables["DestInsCount"].Value = Convert.ToInt64(returnValue);

returnValue = upd_count.Value.ToString();
Dts.Variables["DestUpdCount"].Value = Convert.ToInt64(returnValue);

returnValue = rev_count.Value.ToString();
Dts.Variables["DestRevCount"].Value = Convert.ToInt64(returnValue);

Я получаю ошибку в ExecuteNonQuery. ORA-01422: точная выборка возвращает больше строк, чем запрошено\nORA-06512: в "TEST.TEST_DATA"

Вот код хранимой процедуры Oracle:

CREATE PROCEDURE TEST_DATA
    (
      ins_count OUT number,
      upd_count OUT number,
      rev_count OUT number
    )
    AS
    log_id_v number;
    update_cnt number;
    insert_cnt number;
    reverse_cnt number;
    stg_cnt number;
    BEGIN
    
    SELECT COUNT(1) INTO stg_cnt
    FROM TEST.STAGE_DATA;
    IF (stg_cnt > 0) THEN
        --Records exist in the stage table
          
      INSERT INTO TEST.DATA 
        (
          DATE,
          CLIENT_ID,
          PROGRAM_ID,
          STATUS,
          LOG_ID
        )
      SELECT
          TD.DATE,
          TD.CLIENT_ID,
          TD.PROGRAM_ID,
          TD.STATUS,
          STD.LOG_ID
      FROM TEST.DATA TD
      INNER JOIN TEST.STAGE_DATA STD
        ON TD.DATE = STD.DATE
          AND TD.CLIENT_ID = STD.CLIENT_ID
          AND TD.PROGRAM_ID = STD.PROGRAM_ID
          AND TD.STATUS <> 'Reverse'
      WHERE TD.MODIFIED_DTM = (
          SELECT MAX(TD.MODIFIED_DTM)
          FROM TEST.DATA TD
          WHERE TD.CLIENT_ID = STD.CLIENT_ID 
          AND TD.PROGRAM_ID = STD.PROGRAM_ID
          AND TD.DATE = STD.DATE
          AND TD.STATUS <> 'Reverse'
          );
          
        --Get current LOG_ID - stage table should have only one
        SELECT DISTINCT(LOG_ID) INTO log_id_v
        FROM TEST.STAGE_DATA;
    
      
        --Get count of records inserted with reverse status in main table
        SELECT COUNT(1) INTO reverse_cnt
        FROM TEST.DATA
        WHERE STATUS = 'Reverse'
        AND LOG_ID = log_id_v;
      
      INSERT INTO TEST.DATA 
        (
          DATE,
          CLIENT_ID,
          PROGRAM_ID,
          STATUS,
          LOG_ID
        )
     SELECT
          SELECT
          STD.DATE,
          STD.CLIENT_ID,
          STD.PROGRAM_ID,
          'Update',
          STD.LOG_ID
      FROM TEST.STAGE_DATA STD
      WHERE EXISTS
          (
            SELECT 1 
            FROM TEST.DATA TD 
            WHERE TD.CLIENT_ID = STD.CLIENT_ID 
            AND TD.PROGRAM_ID = STD.PROGRAM_ID
            AND TD.DATE = STD.DATE
            AND TD.STATUS <> 'Reverse'
            );
            
      --Get count of records inserted with update status in main table
      SELECT COUNT(1) INTO update_cnt
      FROM TEST.DATA
      WHERE STATUS = 'Update'
      AND LOG_ID = log_id_v;  
      
      --Insert new records  
        MERGE INTO TEST.DATA TD
        USING TEST.STAGE_DATA STD
        ON (
            TD.CLIENT_ID = STD.CLIENT_ID 
            AND TD.PROGRAM_ID = STD.PROGRAM_ID
            AND TD.DATE = STD.DATE
          )
        WHEN NOT MATCHED THEN INSERT
        (
          DATE,
          CLIENT_ID,
          PROGRAM_ID,
          STATUS,
          LOG_ID
        )
        VALUES
        (
          STD.DATE,
          STD.CLIENT_ID,
          STD.PROGRAM_ID,
          'New',
          STD.LOG_ID
        );
        
        --Get count of records inserted with new status in main table
        SELECT COUNT(1) INTO insert_cnt
        FROM TEST.DATA
        WHERE STATUS = 'New'
        AND LOG_ID = log_id_v;
     
      --Set output variables
        rev_count := reverse_cnt;  
        ins_count := insert_cnt;
        upd_count := update_cnt;
        
    ELSE
        --when no records in stage table
        
        --Set output variables to 0
        ins_count := 0;
        upd_count := 0;
        rev_count := 0;
        
    END IF;
    END;

Обратите внимание, что моя таблица этапов пуста, поэтому код переходит прямо к блоку ELSE и возвращает 0 для всех выходных параметров при запуске вручную из Oracle SQL Developer. Я ожидал такого же результата от своей задачи сценария, но он выдает ошибку ORA, упомянутую выше.

Вы не показали ни одного своего кода и не показали, почему, по вашему мнению, именно вызов вашей процедуры вызывает ошибку или почему именно этот запрос внутри этой процедуры. Возможно, стек ошибок, который вы видите, действительно указывает на это, но вы этого тоже не показали. Возможно, это другой вызов или другая линия, или вы не подключены к той БД/схеме, о которой думаете, или... кто знает. Вы действительно не дали нам ничего, с чем можно было бы работать.

Alex Poole 26.08.2024 19:34

Я не понимаю, как вы ожидаете от нас помощи с кодом, который мы не видим?

Gerhard 27.08.2024 07:30

Я добавил код, с которым работаю. Дает ли это какую-либо подсказку?

nyrrovro 27.08.2024 16:31

Настоящая проблема здесь в том, что у вас нет номера строки, который точно указывает, где происходит ошибка. По умолчанию исключения Oracle включают стек ошибок и все соответствующие номера строк. Если у вас нет этой информации, код может включать неправильную обработку исключений, которая делает что-то вроде exception when others then dbms_output.put_line(sqlerrm); Если вы удалите всю пользовательскую обработку исключений, значения по умолчанию, скорее всего, вернут всю необходимую вам отладочную информацию.

Jon Heller 28.08.2024 05:22
Стоит ли изучать 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
4
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

SELECT DISTINCT(LOG_ID) INTO log_id_v
        FROM TEST.STAGE_DATA;

Это вполне может вернуть более одной строки, что приведет к получению ошибки. Вы не можете использовать неявный курсор в такой переменной, если она не является скаляром (одна строка). Я предлагаю использовать агрегат типа MAX:

   SELECT MAX(LOG_ID) INTO log_id_v
            FROM TEST.STAGE_DATA;

Конечно, если это была ошибка, это означает, что на самом деле существует более одного значения, поэтому, вероятно, не имеет смысла в программировании просто выбирать одно случайное значение, подобное этому. Вам придется подумать о том, какой из них вы действительно хотите.

Спасибо за ваше время. Пытаясь устранить эту ошибку, я усек таблицу TEST.STAGE_DATA, но по-прежнему получаю ту же ошибку. Когда я запускаю хранимую процедуру вручную, код переходит к блоку ELSE из-за условия IF (stg_cnt > 0), а затем устанавливает выходные параметры. Однако запуск хранимой процедуры из задачи сценария SSIS приводит к ошибке ORA 01422.

nyrrovro 27.08.2024 19:34
Ответ принят как подходящий

Мне удалось решить эту проблему с помощью администратора базы данных. Похоже, что файл tnsnames.ora был обновлен, и хост был обновлен, чтобы указывать на какой-то другой сервер. Однако имя службы и учетные данные остались такими же, как и раньше, поэтому моя конфигурация SSIS работала должным образом.

По сути, я подключался к другому серверу с такой же структурой. И на этом сервере таблица TEST.STAGE_DATA уже была заполнена некоторыми данными, которые имели дубликаты. Таким образом, ошибка 01422 на самом деле была выдана оператором слияния, поскольку было найдено более 1 записи для условия слияния.

Хотя я в некоторой степени работал с SSIS, я впервые подключаюсь к базе данных Oracle, отсюда и допущенная ошибка. Спасибо всем за ваше время и вклад в это, очень ценю это.

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