Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Ошибка при выполнении ХП [D7, FireBird 2.1.2]


Виталий Панасенко ©   (2009-04-17 16:54:00) 

При выполнении простенькой, казалось бы ХП, получаю эксцепшн
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...])


Виталий Панасенко(дом)   (2009-04-17 18:23:00) [1]

все, спасибо.. решилось, как НЕ говорил Холмс, "элементарно"...:-)

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));

можно ветку закрывать


Виталий Панасенко(дом)   (2009-04-17 18:19:00) [2]

да, именно там.. коментирую кусок, работает.. спасибо за подсказку


Виталий Панасенко(дом)   (2009-04-17 18:17:00) [3]

видимо, здесь
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));


Виталий Панасенко(дом)   (2009-04-17 18:16:00) [4]

наврал на счет триггеров.. вот на этом спотыкается.. отключаю, все нормально, включаю - эксцепшн


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 idNEW.id and DOC_STATUS=1
             AND ((period_beg = NEW.period_beg)) )) THEN
  BEGIN
    FOR
     SELECT MAX(id) FROM doc
     WHERE num_id=NEW.num_id AND idNEW.id
             AND ((period_beg = 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_beg)) )) THEN
  BEGIN
    FOR
     SELECT MAX(id) FROM doc
     WHERE num_id=NEW.num_id
             AND ((period_beg = 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_beg));
END


Виталий Панасенко(дом)   (2009-04-17 18:03:00) [5]

это где-то в районе then


Виталий Панасенко(дом)   (2009-04-17 18:02:00) [6]

не помогло....теперь строка 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


Виталий Панасенко(дом)   (2009-04-17 17:54:00) [7]

сейчас попробую.. но весь прикол: сменить DOC_STATUS с 1 на 2 - без проблем, наоборот - указанный эксцепшн.. код отрабатывает один и тот же.. даже "прошил" 2 (может, думал, вычислил неправильно) в параметры  -эксцепшн


turbouser   (2009-04-17 17:47:00) [8]


> Виталий Панасенко(дом)   (17.04.09 17:42) [3]

А если сделать
if exists(select * from doc where id = :id) then
begin
 update doc
...
end


Виталий Панасенко(дом)   (2009-04-17 17:42:00) [9]

триггеры есть.. перекомпиляция - не помогает... я уже грешным делом поменял порядок следования параметров, думал, как с джоинами поможет.. не помогло.. триггеры: получить ИД и если PERIOD_BEG<>PERIOD_END, то "наплодить" на каждый месяц отдельную запись(чтобы можно было заказ в любом месте периода освободить, так сказать)


turbouser   (2009-04-17 17:28:00) [10]


> Виталий Панасенко   (17.04.09 16:56) [1]

Триггеров нет?
Перекомпилировать процедуру - не помогает?


Виталий Панасенко   (2009-04-17 16:56:00) [11]

не дописал полный текст сообщения об ошибке:
The cursor identified in the update or delete statement is not positioned on a row. At procedure 'DOC_UPD' line: 15. col: 3


Наверх

Титульная страница Поиск, карта сайта Написать письмо