Не обновляются данные в таблице из ХП

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
koren
Сообщения: 12
Зарегистрирован: 19 апр 2006, 13:11

Не обновляются данные в таблице из ХП

Сообщение koren » 19 апр 2006, 14:09

Firebird 1.5.3
Есть таблица

Код: Выделить всё

SET SQL DIALECT 3;

SET NAMES WIN1251;
CREATE TABLE GOODS (
    ID         CHAR(13) NOT NULL,
    NAME       VARCHAR(50),
    VLOG       INTEGER,
    COST       DOUBLE PRECISION DEFAULT 0 NOT NULL
);
ALTER TABLE GOODS ADD CONSTRAINT PK_GOODS PRIMARY KEY (ID);


Есть порцедура
CREATE PROCEDURE INSTAL_PRICE (
    ID_GOOD CHAR(13),
    NEW_COST DOUBLE PRECISION,
    D_PRICE DATE)
AS
DECLARE VARIABLE S_COST DOUBLE PRECISION;
begin

    for select goods.cost from goods where goods.id = :id_good
    into :s_cost
    do begin
        if  (s_cost <> new_cost) then
        begin
            update goods set cost = :new_cost where (goods.id = :id_good);
        end
        exit;
    end
Вызов производится из 1с
Соединение = СоздатьОбъект("ADODB.Connection");
Cоединение.ConnectionString = "driver={Firebird/InterBase(r) driver};server=C:\Program Files\Firebird\Firebird_1_5\bin\fbserver.exe;uid=SYSDBA;pwd=masterkey;database=D:\FB_Base\BOOK_PRICE.FDB;";
Соединение.Open(Соединение.ConnectionString);
Комманда = СоздатьОбъект("ADODB.Command");
Комманда.ActiveConnection = Соединение;


Выборка документов и установка последней цены в таблице GOODS производится с помощью ХП
Комманда.CommandText = "INSERT INTO goods VALUES ('"+ИдОбТов+"'"+","+"'"+Лев(Док.Номенклатура.Наименование, 50)+"',"+Док.Номенклатура.ОсновнаяЕдиница.Коэффициент+",0"+",0"+")";
Комманда.Execute();
Если такой товар есть то FB сам проконтролирует наличие записи по ID (PK)
Комманда.CommandText = "EXECUTE PROCEDURE INSTAL_PRICE('"+ИдОбТов+"'"+","+"'"+Док.Цена+"'"+","+"'"+Док.ДатаДок+"'"+")";
Комманда.Execute();

Обновление таблицы происходит, но почему-то не всех позиций, некоторые остаются с нулевой ценой. Подключение к серверу из 1с всего одно. В чем может быть проблема.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 19 апр 2006, 14:22

В одинэсе я не силен, но почему бы не селектить из процедуры, вместо экзекута? и из процедуры можно вернуть, к примеру, кол-во проапдеченых записей.

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

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 19 апр 2006, 14:38

значит s_cost временами бывает null. добавь проверку

if ((s_cost <> new_cost) or (s_cost is null)) then

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 19 апр 2006, 14:39

Причем не с копейкой, а с абс(копейкой). Но здесь вообще-то не про это, про это он в следующий раз спросил бы. Он цену ведь не с нулём сравнивает, а с параметром на неравенство, то есть может проапдейтить нечаянно лишнее, уже установленное, отличающееся в последнем разряде, большой беды не будет. Здесь имхо в символьном ID дело. То ли регистры каких-то символов у параметра и полей в пропущенных записях разные, то ли непечатные символы либо в параметре либо в базе на хвостах.

koren
Сообщения: 12
Зарегистрирован: 19 апр 2006, 13:11

Сообщение koren » 19 апр 2006, 15:52

Заменил EXECUTE на SELECT, убрал лишние пробелы справа в ID, убрал пока проверку IF, чтоб наверняка. Вообще перестало работать, т.е. COST по нулям.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 19 апр 2006, 16:01

Ну естественно. Ты же сам завершаешь процедуру на первой же выбранной записи. Или что там по-твоему делает exit?

koren
Сообщения: 12
Зарегистрирован: 19 апр 2006, 13:11

Сообщение koren » 19 апр 2006, 16:04

Извините забыл дописать. Exit в процедуре заменил на SUSPEND.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 20 апр 2006, 08:23

koren писал(а):Заменил EXECUTE на SELECT, убрал лишние пробелы справа в ID, убрал пока проверку IF, чтоб наверняка. Вообще перестало работать, т.е. COST по нулям.
Давай код, чего ты там наизменял, потому как первоначально у тебя цикл for select и безусловный выход после первой записи, он и не должен проапдейтить больше одной записи. :)

koren
Сообщения: 12
Зарегистрирован: 19 апр 2006, 13:11

Сообщение koren » 20 апр 2006, 10:59

Код: Выделить всё

begin
    count_filds = 0;
    for select goods.cost from goods where goods.id = :id_good
    into :s_cost
    do begin
         update goods set cost = :new_cost where (goods.id = :id_good);
         count_filds = count_filds + 1;
        suspend;
    end


end
Вообще по смуслу одну запись обновить и необходимо, ID_GOOD в селекте первичный ключ таблицы GOODS и там не должно быть более одной записи

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 20 апр 2006, 13:45

А где заголовок процедуры? А способ вызова точно SELECT? А транзакцию ты потом коммитишь? А в какой транзакции смотришь были ли изменения (параметры)? А коммитишь ли ее? В-общем, рассказывай как ты дошел до жизни такой что не срабатывают простейшие запросы.
Кстати, может ты ей просто передаешь неверный ig_good поэтому она, естественно, ничего не выбирает и ничего не апдейтит.
Последний раз редактировалось Dimitry Sibiryakov 20 апр 2006, 13:56, всего редактировалось 1 раз.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 20 апр 2006, 13:50

У тебя процедура, по идее вернет нарастающим итогом от 1 и до N набор данных, где N и будет число обработанных записей. Поставь саспенд после цикла.

И вообще чего тут путано все... в принципе процедура должна проапдейтить одну запись, нафиг тогда фор селект??? или апдейтить надо всю таблицу?

Ответить