Конференция "Базы" » Ошибка при выполнении ХП [D7, FireBird 2.1.2]
 
  • Виталий Панасенко (17.04.09 16:54) [0]
    При выполнении простенькой, казалось бы ХП, получаю эксцепшн
    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...])
  • Виталий Панасенко (17.04.09 16:56) [1]
    не дописал полный текст сообщения об ошибке:
    The cursor identified in the update or delete statement is not positioned on a row. At procedure 'DOC_UPD' line: 15. col: 3
  • turbouser © (17.04.09 17:28) [2]

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

    Триггеров нет?
    Перекомпилировать процедуру - не помогает?
  • триггеры есть.. перекомпиляция - не помогает... я уже грешным делом поменял порядок следования параметров, думал, как с джоинами поможет.. не помогло.. триггеры: получить ИД и если PERIOD_BEG<>PERIOD_END, то "наплодить" на каждый месяц отдельную запись(чтобы можно было заказ в любом месте периода освободить, так сказать)
  • turbouser © (17.04.09 17:47) [4]

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

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

  • Виталий Панасенко(дом) (17.04.09 17:54) [5]
    сейчас попробую.. но весь прикол: сменить DOC_STATUS с 1 на 2 - без проблем, наоборот - указанный эксцепшн.. код отрабатывает один и тот же.. даже "прошил" 2 (может, думал, вычислил неправильно) в параметры  -эксцепшн
  • Виталий Панасенко(дом) (17.04.09 18:02) [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

  • Виталий Панасенко(дом) (17.04.09 18:03) [7]
    это где-то в районе then
  • Виталий Панасенко(дом) (17.04.09 18:16) [8]
    наврал на счет триггеров.. вот на этом спотыкается.. отключаю, все нормально, включаю - эксцепшн


    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
     /*&#207;&#240;&#238;&#226;&#229;&#240;&#234;&#224; &#237;&#224; &#241;&#243;&#249;&#229;&#241;&#242;&#226;&#238;&#226;&#224;&#237;&#232;&#229; &#228;&#240;&#243;&#227;&#238;&#227;&#238; &#231;&#224;&#234;&#224;&#231;&#224;,&#234;&#238;&#242;&#238;&#240;&#251;&#233; &#239;&#229;&#240;&#229;&#241;&#229;&#234;&#224;&#229;&#242;&#241;&#255; &#241; &#237;&#224;&#248;&#232;&#236;*/
     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
         --&#194;&#251;&#231;&#251;&#226;&#224;&#229;&#236; &#232;&#241;&#234;&#235;&#254;&#247;&#229;&#237;&#232;&#229;
         EXCEPTION period_exception 'Åñòü äðóãîé çàêàç ñ òàêèì ïåðèîäîì: ¹'||CAST(:id AS VARCHAR(18))||', êëèåíò: '||:client_shortname;
      END
     --&#194;&#241;&#242;&#224;&#226;&#234;&#224;
     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
         --&#194;&#251;&#231;&#251;&#226;&#224;&#229;&#236; &#232;&#241;&#234;&#235;&#254;&#247;&#229;&#237;&#232;&#229;
         EXCEPTION period_exception 'Åñòü äðóãîé çàêàç ñ òàêèì ïåðèîäîì: ¹'||CAST(:id AS VARCHAR(18))||', êëèåíò: '||:client_shortname;
      END
     /*&#207;&#238;&#228;&#241;&#247;&#229;&#242; &#247;&#232;&#241;&#235;&#224; &#236;&#229;&#241;&#255;&#246;&#229; &#226; &#239;&#229;&#240;&#232;&#238;&#228;&#229;*/
     EXECUTE PROCEDURE sp_monthsbetween(NEW.period_beg, NEW.period_end) RETURNING_VALUES :MB;
     NEW.monthsbetween = :MB;
     /*&#211;&#228;&#224;&#235;&#232;&#242;&#252; &#226;&#241;&#229; &#208;&#197;&#199;&#197;&#208;&#194;&#219; &#228;&#235;&#255; &#228;&#224;&#237;&#237;&#238;&#233; &#239;&#235;&#238;&#241;&#234;&#238;&#241;&#242;&#232;, &#229;&#241;&#235;&#232; &#232;&#245; &#239;&#229;&#240;&#232;&#238;&#228; &#239;&#229;&#240;&#229;&#241;&#229;&#234;&#224;&#229;&#242;&#241;&#255; &#241; &#237;&#224;&#248;&#232;&#236;*/
     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

  • Виталий Панасенко(дом) (17.04.09 18:17) [9]
    видимо, здесь
    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));

  • Виталий Панасенко(дом) (17.04.09 18:19) [10]
    да, именно там.. коментирую кусок, работает.. спасибо за подсказку
  • Виталий Панасенко(дом) (17.04.09 18:23) [11]
    все, спасибо.. решилось, как НЕ говорил Холмс, "элементарно"...:-)

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


    можно ветку закрывать
 
Конференция "Базы" » Ошибка при выполнении ХП [D7, FireBird 2.1.2]
Есть новые Нет новых   [134477   +39][b:0][p:0.007]