![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ADO и MS SQL - посоветуйте хорошую ссылку [MSSQL]
kaif © (2008-09-08 21:03:00)Пишу приложение для базы MSSQL. Решил в приложении использовать ADO. Не могу найти хорошей статьи с примерами.
Например, у меня есть справочники.
Конструкция типа:
INSERT INTO GOODS(GOODS_NAME) VALUES(:NAME)
SELECT :ID = @@IDENTITY
у меня в ADOQuery.ExecSQL не сработала. То есть сработала, но несмотря на то, что я явно задал 2 параметра (NAME и ID), один как Dirction = pdInput, а другой - pdOutput, после ExecSQL у меня в выходном параметре присутствует NULL.
Я написал хранимую процедуру, возвращающую набор данных:
CREATE PROCEDURE SP_INSERT_GOOD(@NAME VARCHAR(60))
AS
BEGIN
INSERT INTO GOODS(GOOD_NAME) VALUES(@NAME)
SELECT :ID = @@IDENTITY
END
И, используя метод ADOQuery.Open, получил желаемое.
Однако мне это решение кажется каким-то кривым.
Хотелось бы увидеть что-нибудь традиционно принятое в этой связке Delphi6-ADO-MSSQL2000.
Буду благодарен за любую информацию.
С уважением.
Медвежонок Пятачок (2008-09-08 23:56:00) [81]запрос был в дизайнтайме и после смены текста commandtext тип параметра сбрасывался в инпут
Медвежонок Пятачок (2008-09-08 23:52:00) [82]ой нет. все работает
Медвежонок Пятачок (2008-09-08 23:50:00) [83]я уже раза четыре проверил.
sniknik (2008-09-08 23:48:00) [84]> set устанавливает значение, select не устанавливает
не может быть... это разные формы одного и того же.
счас проверю.
sniknik (2008-09-08 23:47:00) [85]> О чем речь, о получение идентити?
да
> Тогда просто insert + select в одной команде.
это вариант от "пятачка", а изначально попытка вернуть через параметр. оба варианта работают. если бы не 17я строка...
Медвежонок Пятачок (2008-09-08 23:44:00) [86]у меня аналогично.
set устанавливает значение, select не устанавливает
insert into test_table(name) values('test')
set :id = @@identity
sniknik (2008-09-08 23:42:00) [87]> Однако все равно не работает.
в коде нет указания типа параметра, а говоришь что он pdOutput.
как знал, что врешь.
kaif (2008-09-08 23:35:00) [88]В принципе мне нравится решение Медвежонок Пятачок © (08.09.08 22:18) [5], если перевести в TAdoDataSet. Мне не очень нравится запрашивать @@IDENTITY по честному. Но это похоже на мое решение с хранимой процедурой. Неприятно то, что для того чтобы сделать инсерт я в программе вынужден делать Open. Как-то неаккуратненько.
К тому же я не люблю не разобравшись в причине брать альтернативное решение. А вдруг мне еще где-нибудь понадобится вернуть параметр?
Что я буду делать?
Вот я сделал такой запрос для исследования:
with ADOCommand1 do
begin
CommandText := 'SELECT :ID = @@Error';
Execute;
ShowMessage(IntToStr(Parameters.ParamByName('ID').Value));
end;
Все отлично. Выходной параметр установлен, значение равно 0.
Значит дело в том, что у меня пакет.
Вот такой текст уже не сработал:
with ADOCommand1 do
begin
CommandText := 'INSERT INTO GOODS(GOOD_NAME) VALUES (:NAME)'#13+
'SELECT :ID = @@Error';
Parameters.ParamByName('NAME').Value := AName;
Execute;
ShowMessage(IntToStr(Parameters.ParamByName('ID').Value));
end;
Причем запись вставилась, а вот второй запрос, похоже, то ли не отработал вообще, то ли не сумел донести выходной параметр до места назначения.
А вот так сработало:
with ADOCommand1 do
begin
CommandText :=
' BEGIN TRAN'#13+
'INSERT INTO GOODS(GOOD_NAME) VALUES (:NAME)'#13+
'SELECT :ID = @@IDENTITY'#13+
' COMMIT TRAN';
Parameters.ParamByName('NAME').Value := AName;
Execute;
ShowMessage(IntToStr(Parameters.ParamByName('ID').Value));
end;
Буду благодарен за комментарии к этому месту. Что произошло?
И подскажите, пожалуйста, как написать так, чтобы транзакция не повисла в случае, например нарушения уникального ключа при вставке.
kaif (2008-09-08 23:17:00) [89]stas © (08.09.08 22:56) [10]
странно, поставь дирекшин InputOutput
Давно стоит.
Если у всех это работает, буду биться с настройками, транзакциями и т.п.
я проверил, не стоит ли режим IMPLICIT_TRANSACTIONS на сервере.
select case when (@@options & 2) = 2 then 'IMPLICIT' else 'NOT IMPLICIT' end
Вроде бы не стоит.
Даже не знаю, с чем это все может быть связано.
stas (2008-09-08 22:56:00) [90]странно, поставь дирекшин InputOutput
kaif (2008-09-08 22:52:00) [91]2 sniknik © (08.09.08 22:06) [3]
Ух ты, спасибо, я вообще не разглядел ADOCommand на палитре...
Однако все равно не работает.
with ADOCommand1 do
begin
CommandText := 'INSERT INTO GOODS(GOOD_NAME) VALUES (:NAME)'#13+
'SET :ID = @@IDENTITY';
Parameters.ParamByName('NAME').Value := AName;
Execute;
ShowMessage(IntToStr(Parameters.ParamByName('ID').Value));
end;
Ошибка та же. Значение выходного параметра все равно имеет значение Null (в смысле variant).
Пробовал оба синтаксиса, и SELECT и SET. Разницы никакой.
Медвежонок Пятачок (2008-09-08 22:37:00) [92]можно и в одном. еще лучше пересесть на 2005 и заюзать output для инсерта
Anatoly Podgoretsky (2008-09-08 22:34:00) [93]> sniknik (08.09.2008 22:27:06) [6]
О чем речь, о получение идентити?
Тогда просто insert + select в одной команде.
sniknik (2008-09-08 22:27:00) [94]Медвежонок Пятачок © (08.09.08 22:18) [5]
нет смысла разделять команды. опасно. а если возвращать значение через рекордсет, то тогда и инсерт тоже в TAdoDataSet перенести.
Медвежонок Пятачок (2008-09-08 22:18:00) [95]TAdoCommand + 'insert into TABLENAME values(.........)'
+
TAdoDataSet + select IDENT_CURRENT('TABLENAME')
Медвежонок Пятачок (2008-09-08 22:08:00) [96]у меня в ADOQuery.ExecSQL не сработала.
ADODataSet и ADOCommand. Все остальное не использовать.
sniknik (2008-09-08 22:06:00) [97]> ADOQuery
кстати заменил бы ты его на ADOCommand
sniknik (2008-09-08 22:04:00) [98]> после ExecSQL у меня в выходном параметре присутствует NULL.
либо врешь либо ошибка в 17й строке.
stas © (08.09.08 21:08) [1]
> SET :ID = @@IDENTITY
SELECT :ID = @@IDENTITY то же самое по сути, только стиль новее.
stas (2008-09-08 21:08:00) [99]
INSERT INTO GOODS(GOODS_NAME) VALUES(:NAME)
SET:ID = @@IDENTITY
ADOQuery.ExecSQL