CRUD на хранимках
CRUD на хранимках
Подскажите пожалуйста, я пытаюсь сделать так чтобы набор данных полностью работал через ХП.
Я создал хранимку для Insert, она вставляет значение в таблицу с автоинкрементом, а последней строкой возвращает только что вставленную строку полностью, вместе с ключевым полем и всеми остальными полями, посути таже команда что используется для SELECT но возвращается только одна строка.
Я бы хотел использовать эти возвращенные данные для того чтобы обновить на клиенте датасет в который я вставил данные, так как фактически мне придет не только значение ключевого поля, но и еще рад полей которые автоматически рассчитались на сервере.
Как я могу это сделать?
Я создал хранимку для Insert, она вставляет значение в таблицу с автоинкрементом, а последней строкой возвращает только что вставленную строку полностью, вместе с ключевым полем и всеми остальными полями, посути таже команда что используется для SELECT но возвращается только одна строка.
Я бы хотел использовать эти возвращенные данные для того чтобы обновить на клиенте датасет в который я вставил данные, так как фактически мне придет не только значение ключевого поля, но и еще рад полей которые автоматически рассчитались на сервере.
Как я могу это сделать?
Re: CRUD на хранимках
Добрый день,
Пожалуйста, уточните с какими БД Вы работаете?
Пожалуйста, уточните с какими БД Вы работаете?
Re: CRUD на хранимках
Конкретно сейчас MSSQL 2008.
Набросал примерчик SELECT
А вот так выглядит INSERT, пример не совсем реальный, просто для понимания принципа
Набросал примерчик SELECT
Код: Выделить всё
CREATE PROCEDURE [dbo].[SchetSelect] (
@KOD INT
)
AS
BEGIN
SELECT
Schet.Kod,
KodBaseLPU,
God,
Mes,
NSchet,
DSchet,
SummaVyst,
VidPom,
CASE VidPom
WHEN 1 THEN 'стац'
WHEN 2 THEN 'д.стац'
WHEN 3 THEN 'пол'
WHEN 4 THEN 'стом'
WHEN 5 THEN 'с.п.'
ELSE '-'
END as VidPomName,
Dict_Ref_BaseLPU.Naim
FROM
Schet
JOIN Dict_Ref_BaseLPU ON
Dict_Ref_BaseLPU.Kod = Schet.KodBaseLPU
WHERE
((@KOD is NULL) OR
(Schet.Kod=@KOD))
END
Код: Выделить всё
CREATE PROCEDURE [dbo].[InsertSchet] (
@NSchet nvarchar(20),
@SummaVyst numeric(15, 2)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @KOD int
select @KOD=MAX(Kod)+1 from Schet
INSERT INTO Schet (
Kod,
KodBaseLPU,
God,
Mes,
NSchet,
DSchet,
SummaVyst,
VidPom )
VALUES (
@KOD,
1,
CONVERT(int, YEAR(GETDATE())),
CONVERT(int, MONTH(GETDATE())),
@NSchet,
GETDATE(),
@SummaVyst,
3)
exec dbo.SchetSelect @KOD
END
Re: CRUD на хранимках
Извините за задержку с ответом.
Для возвращения данных на клиент Вы можете использовать выходные параметры хранимых процедур. Например:, где test это следующая таблица:, selecttest и inserttest это следующие хранимые процедуры:
Для возвращения данных на клиент Вы можете использовать выходные параметры хранимых процедур. Например:
Код: Выделить всё
begin
MSStoredProc1.StoredProcName := 'selecttest';
MSStoredProc1.SQLInsert.Text := 'execute inserttest :id out, :dt out, @txt=:txt';
MSStoredProc1.Options.ReturnParams := True;
MSStoredProc1.PrepareSQL;
MSStoredProc1.Open;
MSStoredProc1.Append;
MSStoredProc1.FieldByName('txt').AsString := 'test';
MSStoredProc1.Post;
end;
Код: Выделить всё
CREATE TABLE test(
id INT NOT NULL,
dt DATETIME NULL,
txt VARCHAR(50) NULL,
CONSTRAINT PK_test PRIMARY KEY (id)
) ON [PRIMARY]
Код: Выделить всё
CREATE PROCEDURE selecttest
AS
SELECT * FROM test
Код: Выделить всё
CREATE PROCEDURE inserttest
@id INT OUT,
@dt DATETIME OUT,
@txt VARCHAR(50)
AS
BEGIN
SELECT @id = max(ID) + 1 FROM test;
SET @dt = getdate();
INSERT INTO test(id, dt, txt) VALUES (@id, @dt, @txt);
END
Re: CRUD на хранимках
Андрей, спасибо за пример
Реализация на OUT параметрах в принципе неплоха если делаешь проект с нуля.
У нас к сожалению сложилась ситуация когда хочется перевести клиента с Ado+Ehlib на Unidac+DevEx(Grid), не трогая весь функционал работающий на хранимках.
Есть ли возможность обработать курсор, возвращенный с сервера при процедуре вставки в БД?
Т.е именно в той реализации которую я показал?
Реализация на OUT параметрах в принципе неплоха если делаешь проект с нуля.
У нас к сожалению сложилась ситуация когда хочется перевести клиента с Ado+Ehlib на Unidac+DevEx(Grid), не трогая весь функционал работающий на хранимках.
Есть ли возможность обработать курсор, возвращенный с сервера при процедуре вставки в БД?
Т.е именно в той реализации которую я показал?
Re: CRUD на хранимках
На данный момент такой возможности в UniDAC нет. Приведите пожалуйста пример демонстрирующий данный подход при использовании ADO.
Re: CRUD на хранимках
Это скорее фишка именно Ehlib
там существует свой собственный memtable и драйвера доступа к разным БД, посути драйвер представляет собой TUpdateSQL. Причем довольно гибкий, например можно сказать что delete или update возвращают датасет, а не просто делают exec команды написанной в DeleteSQL и UpdateSQL. Для перехвата датасета возвращаемого с сервера при этих операциях есть эвент в котором я получаю датасет, возвращенный с сервера при выполнении команды update и т.д.
Поэтому я могу из возвращенного датасета спокойно поправить memtable без реального его редактирования. Вот пример вставки договора, обратно отваливается датасет из которого я использую автоинкрементарное поле dogovor_id и рассчитанное на сервере hourcost.
Мне очень нравится данный подход, гибкость того что я могу сделать просто великолепная.
Единственная проблема это то что драйвер по сути транслирует все команды в ADO, а затем загружает результат выполнения в memtable. Это влечет за собой проблемы при банальном селекте, сначала в памяти создается TADOQuery, он открывается, а затем все копируется из TADOQuery->MemTable. И вот эта операция копирования ой какая не быстрая, я столкнулся с тем что у меня датасет на 10к записей с сервера загружается за 10сек, а затем еще 40с копируется в memtable
там существует свой собственный memtable и драйвера доступа к разным БД, посути драйвер представляет собой TUpdateSQL. Причем довольно гибкий, например можно сказать что delete или update возвращают датасет, а не просто делают exec команды написанной в DeleteSQL и UpdateSQL. Для перехвата датасета возвращаемого с сервера при этих операциях есть эвент в котором я получаю датасет, возвращенный с сервера при выполнении команды update и т.д.
Поэтому я могу из возвращенного датасета спокойно поправить memtable без реального его редактирования. Вот пример вставки договора, обратно отваливается датасет из которого я использую автоинкрементарное поле dogovor_id и рассчитанное на сервере hourcost.
Код: Выделить всё
procedure TDM.drvDogGetBackUpdatedValues(DataDriver: TADODataDriverEh;
MemRec: TMemoryRecordEh; Command: TADOCommandEh; ResDataSet: TDataSet);
begin
if Assigned(ResDataSet) then
begin
MemRec.DataValues['dogovor_id', dvvValueEh]:= ResDataSet.FieldByName('dogovor_id').Value;
MemRec.DataValues['hourcost', dvvValueEh]:= ResDataSet.FieldByName('hourcost').Value;
end;
end;
Единственная проблема это то что драйвер по сути транслирует все команды в ADO, а затем загружает результат выполнения в memtable. Это влечет за собой проблемы при банальном селекте, сначала в памяти создается TADOQuery, он открывается, а затем все копируется из TADOQuery->MemTable. И вот эта операция копирования ой какая не быстрая, я столкнулся с тем что у меня датасет на 10к записей с сервера загружается за 10сек, а затем еще 40с копируется в memtable
Re: CRUD на хранимках
UniDAC не имеет такую функциональность. Вы можете оставить свое предложение на нашей UserVoice странице: http://devart.uservoice.com/forums/1046 ... components . Если Ваше предложение наберет много голосов от других пользователей, мы реализуем его.
Re: CRUD на хранимках
В версии 6.0.1 пример на OUT параметрах от AndreyZ не работает. На debug видно что не смотря что в тексте sql запроса на insert параметры заданы как out, в списке параметров передаваемых на сервер они заданы как in и соответственно возвращенные с сервера знаения не обрабатываются и не появляются в датасете.
В чем может быть дело?
В чем может быть дело?
Re: CRUD на хранимках
Для ранее указанного мной примера, кроме установления свойства TUniStoredProc.Options.ReturnParams в True, укажите, что параметры с именами 'id' и 'dt'(из свойства TUniStoredProc.SQLInsert.Tex) являются OUT параметрами. Для этого, в событии TUniStoredProc.BeforeUpdateExecute, задайте свойству параметра TDAParam.ParamType значение ptOutput. Например:
Код: Выделить всё
procedure TForm1.UniStoredProc1BeforeUpdateExecute(Sender: TDataSet;
StatementTypes: TStatementTypes; Params: TDAParams);
begin
if stInsert in StatementTypes then begin
Params.ParamByName('id').ParamType := ptOutput;
Params.ParamByName('dt').ParamType := ptOutput;
end;
end;
Re: CRUD на хранимках
А это нормальное поведение или баг? Просто раньше необходимости в ручной установке типа параметра небыло необходимости. Парсер сам брал SQL запрос и параметры out делал как ptOutput.
Т.е будет ли это поправлено или это теперь нормальное поведение компонента и ничего не изменится?
Т.е будет ли это поправлено или это теперь нормальное поведение компонента и ничего не изменится?
Re: CRUD на хранимках
Это корректное поведение и мы не меняли его много времени. Пожалуйста, уточните номер версии UniDAC, в которой out параметрам автоматически устанавливался тип ptOutput.
Re: CRUD на хранимках
Ну точно не скажу, но судя по дате сообщения версия unidac доступная 10 мая 2013 года. В вышеприведенном примере кстати тоже ничего не упоминается о ручной установке out параметров, т.е на момент написания примера out параметры в тексте запроса работали без ручной настройки.
Да и тогда вообще непонятно зачем в запросе параметры помечать как out если перед запуском мы их все равно правим руками.
Да и тогда вообще непонятно зачем в запросе параметры помечать как out если перед запуском мы их все равно правим руками.
Re: CRUD на хранимках
В версии 5.0.1 и последней версии, данное поведение UniDAC не отличается.
В SQL запросе для выполнения хранимой процедуры необходимо указывать типы параметров out, чтобы SQL Server вернул значения для этих параметров запроса.
Задавать свойству TDAParam.ParamType значение ptOutput необходимо, чтобы UniDAC вернул значения для этих параметров датасета из параметров запроса.
В SQL запросе для выполнения хранимой процедуры необходимо указывать типы параметров out, чтобы SQL Server вернул значения для этих параметров запроса.
Задавать свойству TDAParam.ParamType значение ptOutput необходимо, чтобы UniDAC вернул значения для этих параметров датасета из параметров запроса.
Re: CRUD на хранимках
Но в выше опубликованном примере от 10 мая 2013, написанном Вами, никакой ручной установки типов параметров нет, и при этом пример замечательно работал тогда, я проверял сразу после Вашего ответа.