#sql #oracle #plsql
#sql #Oracle #plsql
Вопрос:
N.B, проблема, с которой я сталкиваюсь, связана не с бизнес-логикой, а скорее с самой хранимой процедурой. это очень странная проблема, с которой я сталкиваюсь, и у меня раньше не было такой проблемы.
Я изменяю хранимую процедуру, написанную на PL / SQL, называемую « MY_STORED_PROC
«, и каждый раз, когда я меняю ее содержимое, предыдущие изменения все еще остаются в результате выполнения SP.
Это пример хранимой процедуры:
create or replace PROCEDURE MY_STORED_PROC
(
V_USER IN VARCHAR2 DEFAULT NULL,
V_NUMBER_PARAM IN NUMBER DEFAULT 0,
V_ORIGIN IN NUMBER DEFAULT 0
)
AS
CV_1 SYS_REFCURSOR;
V_SAMPLE NUMBER;
BEGIN
SELECT BAP.APA_CNAME
INTO V_USER_DB
FROM BH_APPLICATION_PARAM BAP
WHERE BAP.APA_NCODE = 84;
INSERT INTO T_DEBUG (ERR_LINE, MESSAGE_INFO)
SELECT ID, 'EXAMPLE_MESSAGE'
FROM <my_table>
WHERE <ID = 1>;
END MY_STORED_PROC;
В предыдущей структуре у меня есть EXAMPLE_MESSAGE
строка, которая вставляется в T_DEBUG
таблицу при выполнении этого SP и выполнении условия.
Теперь, после изменения EXAMPLE_MESSAGE
образца строки другим текстом и компиляции и выполнения SP, сообщение EXAMPLE_MESSAGE
по-прежнему отображается в результатах.
Я не понимаю, почему — если только этот SP имеет заданный образец строки, а таблица
T_DEBUG
усекается перед вызовом SP.
Что я пробовал:
- Выполнить
DELETE FROM T_DEBUG;
иTRUNCATE TABLE T_DEBUG
перед вызовом SP. - Выполнить
DROP PROCEDURE MY_STORED_PROC
, затем выполнитьCREATE OR REPLACE PROCEDURE MY_STORED_PROC
(с объявлением имени схемы и без него) с полностью измененной логикой процедуры. - Скомпилируйте и «Скомпилируйте для отладки» SP — i.e:
MY_STORED_PROC
с именем схемы и без него.
Пример:
CREATE OR REPLACE PROCEDURE <SCHEMA>.MY_STORED_PROC ...
CREATE OR REPLACE PROCEDURE MY_STORED_PROC ...
-
Измените SP для усечения таблицы
T_DEBUG
, «которая содержит образец строки» — это действие (до того, как SP выполнит какое-либо действие «i.e. insert data in T_DEBUG
«). -
Удаление хранимой процедуры:
DROP PROCEDURE MY_STORED_PROC;
и выполнить:CREATE OR REPLACE PROCEDURE <SCHEMA>.MY_STORED_PROC ...
. -
Проверьте
T_DEBUG
таблицу, и она не содержит никакого триггера — это одна таблица без дополнительных функций или характеристик (like indexes, triggers, back-up table(s), etc
). -
Скомпилируйте (SP) со следующим преднамеренным исключением:
-- Generate intentional DivisionByZero unhandled exception: /*SELECT 1/0 INTO V_SAMPLE FROM DUAL;*/
На более позднем этапе ORA-01476
возникает исключение, и, на мой взгляд, SP принимает изменения, но после всех этих изменений я не могу объяснить, почему строка образца остается (даже изменяя содержимое SP).
- В (30/10/2020) Я также добавил:
'SAMPLE - ' || TO_CHAR(SYSDATE)
в качестве примера строки, затем удалил, затем скомпилировал SP — без этого кода — и я все равно получил эту строку образца с датой 30/10/2020 — дата, когда я добавил такой образец, несмотря на то, что я выполнил этот SP в 05/11/2020.
Есть ли какой-либо способ «обновить» хранимую процедуру или какие другие тесты можно выполнить для обновления этой хранимой процедуры?
Я не являюсь администратором базы данных этой базы данных, но я мог бы получить больше информации для обмена с администратором базы данных — я уже объяснил им свою проблему, но помощь не была предоставлена.
Ответ №1:
Хорошо, это звучит странно. «Обновление» не должно требоваться, хранимая процедура хранится в базе данных, и именно она выполняется. Пока вы не используете EBR, нет риска вызова разных версий, если вы выполняете точно такую же процедуру.
Наиболее вероятным объяснением является какая-то глупая ошибка, которую вы упустили из виду, поэтому начните с дальнейшего упрощения вашей процедуры. Вы уже подтвердили сообщением об ошибке, что оно вызывается каждый раз. Удалите другие части вашего кода, чтобы это был просто оператор insert into t_debug, возможно, сделайте так, чтобы он выбирал из dual, а не из другой вашей таблицы с фильтром. Удалите аргументы для процедуры. Попробуйте вставить в другую новую таблицу (возможно, у вас есть триггер). Если вам все же удастся воспроизвести поведение, когда вы упростили его до:
drop table my_table;
create table my_table (my_string varchar2(200));
create or replace procedure my_proc
is
begin
insert into my_table (my_string)
select 'error 1' from dual;
end;
/
exec my_proc
select * from my_table;
delete my_table;
create or replace procedure my_proc
is
begin
insert into my_table (my_string)
select 'error 2' from dual;
end;
/
exec my_proc
select * from my_table;
Тогда возникает проблема.
Комментарии:
1. Не могли бы вы подробнее рассказать
As long as you aren't using EBR
, пожалуйста? — Я не понимаю, что вы имеете в виду. Я попробовал, как вы предложили, и проблема продолжается. Я отредактировал свой вопрос, указав, что в этой таблице нет триггеров — это единственная таблица, используемая для временного хранения строк «проверки бизнес-логики» — Странная ситуация, не так ли?2. EBR — это переопределение на основе редакции. Это позволяет вам иметь несколько программ PL / SQL (и некоторые другие редактируемые объекты) под одним и тем же именем, сеанс будет вызывать ту, которая находится в той же редакции, что и сеанс. По сути, это позволяет выполнять онлайн-обновления с простым переключением на новые версии. Я не думаю, что это здесь уместно, поскольку вы не изменяете свою версию (и, вероятно, у вас даже не включена она).
3. Как только у вас будет упрощенная репликация проблемы от начала до конца, попробуйте ее в другой системе — вы можете использовать livesql.oracle.com для этого. Блок, который я написал, ведет себя точно так, как мы и ожидали. Если у вас этого не происходит, будет полезно поделиться полным случаем здесь.
4. Андрей, извините за поздний ответ. Проблема, к сожалению,
MY_STORED_PROC
в том, что это звено в цепочке, полная функциональность очень сложна, чтобы поделиться полным случаем здесь, и проблема возникает только в этой среде. Я масштабировал эту проблему с инженером в компании. Честно говоря, я не могу сделать больше, чем это. Я ценю вашу помощь.5. Тогда проблема, вероятно, связана с другими частями кода, которыми вы не можете поделиться. Суть в том, что после компиляции неотредактированной процедуры это версия, которую будут использовать все ее вызовы. Мое предложение по-прежнему заключается в том, чтобы начать упрощать, пока вы не обнаружите часть своего кода, которая не совсем соответствует вашим ожиданиям.
Ответ №2:
Я думаю, что две наиболее вероятные причины:
- вы меняете код в IDE, но забываете его «скомпилировать».
- у вас одна и та же процедура в двух разных схемах, и вы не выполняете ту же, которую редактируете.
Ответ №3:
Я, наконец, смог решить эту проблему.
Проблема была связана с данными; в самой базе данных слишком много таблиц, и она сложная, поэтому мне пришлось сгенерировать полный тест программы — после изменения образца текста в хранимой процедуре MY_STORED_PROC
на:
'Testing in LBASPOC - DATE: ' || TO_CHAR(SYSDATE, 'dd/MM/yyyy HH:mi:ss')
Результат был следующим:
Testing in LBASPOC - DATE: 09/11/2020 10:11:30
Когда я сгенерировал больше тестов, в таблицу были добавлены новые записи T_DEBUG
— и DATE
значение менялось в результатах каждого теста:
Примеры:
Testing in LBASPOC - DATE: 09/11/2020 10:12:29
Testing in LBASPOC - DATE: 09/11/2020 10:21:55
Testing in LBASPOC - DATE: 09/11/2020 10:37:41
Затем я обнаружил, что — в других частях программы (т.Е. В базе данных) — были добавлены другие записи (в таблице с именем « T_OBSERV
«) — эти записи были основаны на записях из таблицы « T_DEGUB
«.
Решение было следующим: измените SP « MY_STORED_PROC
» для «перед выполнением каких-либо действий» — удалите дублированные записи в « T_OBSERV
«.
Я был уверен, что проблема была в самом SP, но проблема действительно заключалась в дублированных данных.