-
При выполнении простенькой, казалось бы ХП, получаю эксцепшн the cursor identified in the update or delete statement is not positioned on a row.
В инете нашел(тут, например http://www.sql.ru/forum/actualthread.aspx?tid=283188), что данная ошибка возникала в ФБ при смешивании явных и неявных джоинов или таблиц с ХП. Но в моем случае ХП на изменение.
CREATE PROCEDURE DOC_UPD (
id bigint,
num_id varchar(10),
summa numeric(15,2),
doc_status smallint,
period_beg varchar(6),
period_end varchar(6),
opis_id bigint,
client_id bigint,
sujet varchar(50))
as
begin
update doc
set num_id = :num_id,
summa = :summa,
period_beg = :period_beg,
period_end = :period_end,
doc_status = :doc_status,
--srok_date = :srok_date,
opis_id = :opis_id,
client_id = :client_id,
--doc_date = :doc_date,
sujet = :sujet
where (id = :id);
end Структура таблицы
CREATE GENERATOR GEN_DOC_ID;
CREATE TABLE DOC (
ID BIGINT NOT NULL,
NUM_ID VARCHAR(10) NOT NULL COLLATE WIN1251_UA,
SUMMA CURRENCY /* CURRENCY = NUMERIC(15,2) DEFAULT 0 NOT NULL */,
DOC_STATUS SMALLINT DEFAULT 0,
PERIOD_BEG VARCHAR(6) NOT NULL COLLATE WIN1251_UA,
PERIOD_END VARCHAR(6) NOT NULL COLLATE WIN1251_UA,
MONTHSBETWEEN SMALLINT,
SROK_DATE DATE,
FULL_SUMMA COMPUTED BY (summa * monthsbetween),
OPIS_ID BIGINT DEFAULT 1 NOT NULL,
CLIENT_ID BIGINT NOT NULL,
DOC_DATE DATE NOT NULL,
USER_ID VARCHAR(32) DEFAULT current_user NOT NULL,
SUJET VARCHAR(50) COLLATE WIN1251_UA,
REPSTATUS SMALLINT DEFAULT 0 NOT NULL,
DOC_NUM BIGINT
);
/******************************************************************************/
/*** Primary Keys ***/
/******************************************************************************/
ALTER TABLE DOC ADD CONSTRAINT PK_DOC PRIMARY KEY (ID);
И самый больший прикол, что изменение значение поля DOC_STATUS с 1 на 2 происходит без проблем, а вот наоборот, с 2 на 1 - получаю исключение. Никто с подобным не сталкивался? Изначально сервер был 2,1,1. только что стянул 2,1,2 - не помогло...Вызов ХП осуществляется с помощью FIBQuery.ExecuteProcedure('NAME', [param, param...])
-
не дописал полный текст сообщения об ошибке: The cursor identified in the update or delete statement is not positioned on a row. At procedure 'DOC_UPD' line: 15. col: 3
-
> Виталий Панасенко (17.04.09 16:56) [1]
Триггеров нет? Перекомпилировать процедуру - не помогает?
-
триггеры есть.. перекомпиляция - не помогает... я уже грешным делом поменял порядок следования параметров, думал, как с джоинами поможет.. не помогло.. триггеры: получить ИД и если PERIOD_BEG<>PERIOD_END, то "наплодить" на каждый месяц отдельную запись(чтобы можно было заказ в любом месте периода освободить, так сказать)
-
> Виталий Панасенко(дом) (17.04.09 17:42) [3]
А если сделать if exists(select * from doc where id = :id) then
begin
update doc
...
end
-
сейчас попробую.. но весь прикол: сменить DOC_STATUS с 1 на 2 - без проблем, наоборот - указанный эксцепшн.. код отрабатывает один и тот же.. даже "прошил" 2 (может, думал, вычислил неправильно) в параметры -эксцепшн
-
не помогло....теперь строка 13, колонка 47 в процедуре
CREATE PROCEDURE DOC_UPD (
id bigint,
num_id varchar(10),
summa numeric(15,2),
doc_status smallint,
period_beg varchar(6),
period_end varchar(6),
opis_id bigint,
client_id bigint,
sujet varchar(50))
as
begin
if (exists(select * from doc where id = :id)) then
update doc
set num_id = :num_id,
summa = :summa,
period_beg = :period_beg,
period_end = :period_end,
doc_status = :doc_status,
--srok_date = :srok_date,
opis_id = :opis_id,
client_id = :client_id,
--doc_date = :doc_date,
sujet = :sujet
where (id = :id);
end
-
это где-то в районе then
-
наврал на счет триггеров.. вот на этом спотыкается.. отключаю, все нормально, включаю - эксцепшн
CREATE OR ALTER TRIGGER DOC_BI0 FOR DOC
ACTIVE BEFORE INSERT OR UPDATE POSITION 0
as
declare variable id bigint;
declare variable client_shortname varchar(50);
declare variable mb smallint;
BEGIN
/*Ïðîâåðêà íà ñóùåñòâîâàíèå äðóãîãî çàêàçà,êîòîðûé ïåðåñåêàåòñÿ ñ íàøèì*/
if (updating) then
IF (EXISTS (SELECT * FROM doc
WHERE num_id=NEW.num_id AND id<>NEW.id and DOC_STATUS=1
AND ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg)) )) THEN
BEGIN
FOR
SELECT MAX(id) FROM doc
WHERE num_id=NEW.num_id AND id<>NEW.id
AND ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg))
INTO :id
DO
BEGIN
SELECT c.client_shortname FROM doc d
JOIN clients c ON (c.client_id=d.client_id)
WHERE d.id=:id
INTO :client_shortname;
END
--Âûçûâàåì èñêëþ÷åíèå
EXCEPTION period_exception 'Åñòü äðóãîé çàêàç ñ òàêèì ïåðèîäîì: ¹'||CAST(:id AS VARCHAR(18))||', êëèåíò: '||:client_shortname;
END
--Âñòàâêà
if (inserting) then
IF (EXISTS (SELECT * FROM doc
WHERE num_id=NEW.num_id and DOC_STATUS=1
AND ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg)) )) THEN
BEGIN
FOR
SELECT MAX(id) FROM doc
WHERE num_id=NEW.num_id
AND ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg))
INTO :id
DO
BEGIN
SELECT c.client_shortname FROM doc d
JOIN clients c ON (c.client_id=d.client_id)
WHERE d.id=:id
INTO :client_shortname;
END
--Âûçûâàåì èñêëþ÷åíèå
EXCEPTION period_exception 'Åñòü äðóãîé çàêàç ñ òàêèì ïåðèîäîì: ¹'||CAST(:id AS VARCHAR(18))||', êëèåíò: '||:client_shortname;
END
/*Ïîäñ÷åò ÷èñëà ìåñÿöå â ïåðèîäå*/
EXECUTE PROCEDURE sp_monthsbetween(NEW.period_beg, NEW.period_end) RETURNING_VALUES :MB;
NEW.monthsbetween = :MB;
/*Óäàëèòü âñå ÐÅÇÅÐÂÛ äëÿ äàííîé ïëîñêîñòè, åñëè èõ ïåðèîä ïåðåñåêàåòñÿ ñ íàøèì*/
if (new.doc_status=1) then
delete from doc
where num_id=NEW.NUM_ID and doc_status=2 and ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg));
END
-
видимо, здесь if (new.doc_status=1) then
delete from doc
where num_id=NEW.NUM_ID and doc_status=2 and ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg));
-
да, именно там.. коментирую кусок, работает.. спасибо за подсказку
-
все, спасибо.. решилось, как НЕ говорил Холмс, "элементарно"...:-)
if (inserting) then
if (new.doc_status=1) then
delete from doc
where num_id=NEW.NUM_ID and doc_status=2 and ((period_beg <= NEW.period_end)AND
(period_end >= NEW.period_beg));
можно ветку закрывать
|