NeferSky
Постоялец
Offline
Бессмертный
|
|
« : 18-06-2015 06:50 » |
|
Доброго времени суток. Разъясните мне кто-нибудь, пожалуйста, как именно обращаться с параметрами в IBDataSet. Тут: http://www.ibase.ru/devinfo/ibx.htm русским по белому написано, что Вместо запросов в InsertSQL/UpdateSQL/DeleteSQL ( ... ) можно указывать вызов хранимых процедур. Именно так я и хочу делать. Суть вопроса: IDE - Delphi7. Есть этот самый датасет dsShop. У него есть InsertSQL: execute procedure shop_ins(:shop_num, :org_name, :city, :address, :merchant)
Сохраненка, которую он вызывает: create or alter procedure SHOP_INS ( SHOP_NUM type of column SHOP.SHOP_NUM, ORG_NAME type of column SHOP.ORG_NAME, CITY type of column SHOP.CITY, ADDRESS type of column SHOP.ADDRESS, MERCHANT type of column SHOP.MERCHANT) as begin insert into shop ( id, shop_num, org_name, city, address, merchant, active_flag) values ( gen_id(shop_id, 1), :shop_num, :org_name, :city, :address, :merchant, 1); end^ Как я это делаю сейчас: with dsShop do begin Open; Insert; FieldByName('shop_num').AsString := frmShopEdit.edtShopNum.Text; FieldByName('org_name').AsString := frmShopEdit.edtOrgName.Text; FieldByName('city').AsString := frmShopEdit.edtCity.Text; FieldByName('address').AsString := frmShopEdit.edtAddress.Text; FieldByName('merchant').AsInteger := StrToInt(frmShopEdit.edtMerchant.Text); Post; Close; end;
Но, насколько я понимаю, Insert/Post - это некая "прямая" вставка, в обход сохраненки. Или нет? Исходя из статьи на ibase.ru, видимо, надо делать так: with dsShop do begin Open; Prepare; ParamByName('shop_num').AsString := frmShopEdit.edtShopNum.Text; ParamByName('org_name').AsString := frmShopEdit.edtOrgName.Text; ParamByName('city').AsString := frmShopEdit.edtCity.Text; ParamByName('address').AsString := frmShopEdit.edtAddress.Text; ParamByName('merchant').AsInteger := StrToInt(frmShopEdit.edtMerchant.Text); Insert; Close; end;
но в ответ получаю, что Field "shop_num" not found. Так как, все-таки, надо передавать параметры в сохраненку?
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #1 : 18-06-2015 07:38 » |
|
Но, насколько я понимаю, Insert/Post - это некая "прямая" вставка, в обход сохраненки. Или нет? нет. если указан InsertSQL, то он и будет вызываться. и в него будут попадать значения, которые вы передаете в поля (не в параметры) в режиме dsInsert/dsEdit. т.е. должен нормально работать ваш текущий вариант, и он должен вызывать сохраненку сам. з.ы. и не заморачивайтесь с Prepare, для статических запросов он вызовется автоматически, да и смысл он имеет только в том случае, если происходит многократный вызов одного и того же параметризованного запроса или если в рантайм надо, например, получить план выполнения запроса без отправки самого запроса на сервер.
|
|
« Последнее редактирование: 18-06-2015 07:41 от x77 »
|
Записан
|
|
|
|
NeferSky
Постоялец
Offline
Бессмертный
|
|
« Ответ #2 : 18-06-2015 07:55 » |
|
Гм... А для чего же тогда используются параметры? Только для методов типа ExecQuery?
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #3 : 18-06-2015 08:07 » |
|
параметры используются не только в IBDataset. и нужны они для обращения к параметрам, а в вашем случае вам надо обращаться к полю, т.к. IBDataset - это шняга, работающая с двунаправленным набором данных. преобразования значений полей (по сути - буфера) в параметры для вызова нижележащих процедур датасет будет делать сам.
|
|
|
Записан
|
|
|
|
NeferSky
Постоялец
Offline
Бессмертный
|
|
« Ответ #4 : 18-06-2015 10:24 » |
|
Что-то я все равно не могу состыковать вызов... Аналогичный датасет dsKKM. InsertSQL: execute procedure kkm_ins(:shop_name, :kkm_num, :description)
Сохраненка: create or alter procedure KKM_INS ( SHOP_NAME varchar(50), KKM_NUM type of column KKM.KKM_NUM, DESCRIPTION type of column KKM.DESCRIPTION) as begin insert into kkm( id, shop_id, kkm_num, description, active_flag) values ( gen_id(kkm_id, 1), (select s.id from shop s where s.shop_num = :shop_name), :kkm_num, :description, 1); end^ Вызов: with dsKKM do begin Open; Insert; FieldByName('shop_name').AsString := frmKKMEdit.cbShopNum.Text; FieldByName('kkm_num').AsInteger := StrToInt(frmKKMEdit.edtKKMNum.Text); FieldByName('description').AsString := frmKKMEdit.memDescription.Text; Post; Close; end; Результат: dsKKM: Field 'shop_name' not found Если датасет работает с полями - это значит, что в сохраненку ничего постороннего (не соответствующего набору полей) пихать нельзя?
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #5 : 18-06-2015 10:38 » |
|
а в SelectSQL что?
|
|
|
Записан
|
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #6 : 18-06-2015 10:40 » |
|
просто чтобы параметры обрабатывались автоматически, их имена должны совпадать с именами столбцов таблицы. а для этого их надо сначала получить.
|
|
|
Записан
|
|
|
|
NeferSky
Постоялец
Offline
Бессмертный
|
|
« Ответ #7 : 18-06-2015 11:02 » |
|
SelectSQL: Сохраненка: create or alter procedure KKM_SEL returns ( ID type of column KKM.ID, SHOP_ID type of column KKM.SHOP_ID, KKM_NUM type of column KKM.KKM_NUM, DESCRIPTION type of column KKM.DESCRIPTION, ACTIVE_FLAG type of column KKM.ACTIVE_FLAG) as begin for select id, shop_id, kkm_num, description, active_flag from kkm into :id, :shop_id, :kkm_num, :description, :active_flag do begin suspend; end end^
их имена должны совпадать с именами столбцов таблицы Наверное, это и будет ответом на тему...
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #8 : 18-06-2015 11:04 » |
|
попробуйте, не получится - будем копать дальше.
|
|
|
Записан
|
|
|
|
NeferSky
Постоялец
Offline
Бессмертный
|
|
« Ответ #9 : 18-06-2015 20:12 » |
|
Попробовал, конечно, поле попереименовывать, но делу это не помогло. Похоже, лучшим решением будет дергать сохраненку IBSQL'ем с параметрами, а датасет использовать только для просмотра. У датасета все запросы - те же IBSQL, поэтому и хотелось завести все одним компонентом. Отпишусь о результатах.
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #10 : 18-06-2015 21:05 » |
|
решайте задачу поэтапно. задайте SelectSQL, проверьте, что все работает, задайте InsertSQL, отладьте, потом - UpdateSQL. потом заверните их в процедуру.
судя по коду выше, вы пытаетесь вставлять запись, передавая ей код справочника магазинов. этот код вы получаете по имени, которое передаете параметром.
если я правильно понял, то в вашем случае имя магазина - это именно параметр, и задаваться он должен через ParamByName,а значения для вставки непосредствено в таблицу - через FieldByName.
ругань происходит потому, что селект отрабатывает только по таблице с ККМ-ами, shop_name там нет. поэтоум также можно попробовать переписать селект, подтащив по джойну название магазина из справочника.
но сами по себе все эти телодвижения мне кажутся лишними, и если вы сформулируете задачу, то наверное можно будет посоветовать что-то по-существу.
|
|
|
Записан
|
|
|
|
NeferSky
Постоялец
Offline
Бессмертный
|
|
« Ответ #11 : 22-06-2015 07:12 » |
|
В общем, исправил много недочетов в коде. 1) В БД выкинул использование доменов. (Где-то в документации по InterBase/FireBird указывалось, что домен можно редактировать, и при этом изменения коснутся всех полей и переменных, которым присвоен тип этого домена. Ни разу не получилось так сделать, только ограничения лишние накладывали) create or alter procedure KKM_INS ( ID integer, SHOP_ID integer, KKM_NUM bigint, DESCRIPTION varchar(255), ACTIVE_FLAG smallint) as begin insert into kkm( id, shop_id, kkm_num, description, active_flag) values ( :id, :shop_id, :kkm_num, :description, :active_flag); end^
2) В код Delphi в блоки Insert/Post Edit/Post включил все поля таблиц, с которыми работают датасеты. Соответственно, пришлось получать ID'шники из программы, и добавлять их в блоки, а не просто в БД их генерировать и присваивать. То же самое касается значений "по умолчанию". С самого начала я не добавлял в параметры сохраненки абсолютно все поля. Для инсерта, например, значения по умолчанию и ID не указывал. frmKKMEdit: // Get shop param by name with frmMain.sqlSber do begin SQL.Text := 'select * from get_shop_by_name(:shop_name)'; ParamByName('shop_name').AsString := cbShopName.Text; <- Находим ID того, что выбрал пользователь ExecQuery; end; ShopID := frmMain.sqlSber.Fields[0].AsInteger; frmMain.sqlSber.Close;
frmMain: // Get new ID with sqlSber do begin SQL.Text := 'select * from get_kkm_gen'; ExecQuery; end; KKMID := sqlSber.Fields[0].AsInteger; sqlSber.Close;
// Insert with dsKKM do begin Open; Insert; FieldByName('id').AsInteger := KKMID; FieldByName('shop_id').AsInteger := frmKKMEdit.ShopID; FieldByName('kkm_num').AsInteger := StrToInt(frmKKMEdit.edtKKMNum.Text); FieldByName('description').AsString := frmKKMEdit.memDescription.Text; FieldByName('active_flag').AsInteger := Integer(frmKKMEdit.cbActive.Checked); Post; Close; end;
3) Также пришлось получать в программе id-значения "выбираемых" полей из связанных таблиц.(Например, id значения, выбранного в комбобоксе). Можно, конечно, и массивы сюда прикрутить, типа локального кэша "id-value" таблицы, из которой заполняется комбобокс, но... излишество, имхо. Сначала я пытался просто передавать значение в сохраненку, чтобы БД сама находила нужный ID. execute procedure kkm_ins(:id, :shop_id, :kkm_num, :description, :active_flag)
Вот... С исправлением всего этого работает, тема закрыта. X77 благодарю за объяснение, советы и подсказки. зы: После работы над этим проектом сделаю программу-демку, в которой все-таки попробую еще раз создать сохраненку инсерта с какими попало параметрами, и вызвать ее Edit/Post'ом А то аж за живое задело - "а я хочу так!"
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
x77
Модератор
Offline
Пол:
меняю стакан шмали на обратный билет с Марса.
|
|
« Ответ #12 : 22-06-2015 07:19 » |
|
посмотрите на FIBPlus. там почти такой же набор компонентов, как в IBX, но при этом они умеют делать львиную часть рутинной работы. например, каждому датасету можно сразу указать, какое поле является ключевым и значением какого генератора заполняется, и многое другое.
|
|
|
Записан
|
|
|
|
NeferSky
Постоялец
Offline
Бессмертный
|
|
« Ответ #13 : 22-06-2015 07:26 » |
|
датасету можно сразу указать, какое поле является ключевым и значением какого генератора заполняется
IBX тоже так умеют) Спасибо за информацию, попробую. Однако, всегда стараюсь обходиться минимумом сторонних компонент, чтобы не расслабляться)
|
|
|
Записан
|
Не тронь налаженный механизм, и он тебя не подведет. Делать надо хорошо, а плохо - само получится.
|
|
|
|