Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.03.29;
Скачать: CL | DM;

Вниз

Stream and AdoCommand   Найти похожие ветки 

 
Viod ©   (2008-07-11 11:40) [0]

Здравствуйте!
Есть такая задача: нужно сохранить rtf файл в базу данных, затем из базы данных получить и загрузить в редактор.
rtf передается в поток TMymoryStream.
Для записи в базу данных используется хранимая процедура типа:
@code image
AS
INSERT INTO temp_table(code) VALUES(@code)
-----------------------------------------------------

var mystream:Tmemorystream; // сюда передаю rtf

Пользуюсь компонентом ADOCommand

ADOCommand1.CommandType:=cmdStoredProc;
ADOCommand1.CommandText:="p_inferno_temp2;1";
ADOCommand1.Parameters.Clear;
ADOCommand1.Parameters.Add;
ADOCommand1.Parameters[0].Direction:=pdInput;
ADOCommand1.Parameters[0].Name:="@code";   ADOCommand1.Parameters[0].LoadFromStream(mystream,ftBlob);

Параметру не передается значение из потока.
такой вариант записи в базу вобще возможен?


 
Ega23 ©   (2008-07-11 11:53) [1]

with ADOCommand1 do
begin
 Connection := ....;
 CommandText := "exec s_MyProc @code=:code";
 Parameters.ParamByName("code").DataType := ftBlob;
 Parameters.ParamByName("code").LoadFromStream(mystream,ftBlob);
 try
   Execute;
 except
   ......
 end;
end;


 
Viod ©   (2008-07-11 13:03) [2]

Это осилил, спасибо, а как теперь из базы выгрузить в stream?


 
Ega23 ©   (2008-07-11 13:09) [3]

with TADODataSet.Create(nil) do
begin
 try
   Connection := .....;
   CommandText := "Select code from temp_table";
   try
     Open;
     if IsEmpty then Exit;
     ms := TMemoryStream.Create;
     try
       TBLOBField(FieldByName("code")).SaveToStream(ms, ftBLOB);
       ms.Position := 0;
       ... Работаем с ms
     finally
       ms.Free;
     end;  
   except
     .....
   end;
 finally
   Free;
 end;
end;


 
Viod ©   (2008-07-11 13:12) [4]

спасибо за оперативность :)
пойду пробовать


 
Viod ©   (2008-07-11 13:25) [5]

Все работает.
Теперь пытаюсь сделать вывод с помощью хранимой процедуры

если просто то:
CREATE PROCEDURE temp_out
AS
select code from temp_table
GO

В принципе я вызываю процедуру, она мне возвращает набор, и я его обрабатываю как описано выше... Так будет работать?


 
Ega23 ©   (2008-07-11 13:32) [6]


> Так будет работать?
>


Да.
Только я бы сделал такую процедуру:

CREATE PROCEDURE s_temp_table
 @ActNam varchar(32)="NONE",
 @Code image =NULL
AS
Declare  @result int;
         
Set NoCount On;
Set @ActNam=LTrim(RTrim(Upper(@ActNam)));
Set @result=0;

if @ActNam="SEL"
begin
 Select code from temp_table;
 Goto Fin;
end;

if @ActNam="ADD"
begin
 Insert into temp_table (code) Values (@code);
 Goto Fin;
end;

FIN:
 return(@result);

GO


Ну и вызов в случае добавления - exec s_temp_table @ActNam="ADD", @code=:code
выборки - exec s_temp_table @ActNam="SEL"


 
Viod ©   (2008-07-11 13:42) [7]

Круто, сейчас у меня глаза на место встанут (они на стол выпали), и я разберусь..
Пока все временное, просто пробую - потом конечно все это обрастет кодом ;)

Спасибо за точный и быстрый ответ


 
Viod ©   (2008-07-14 06:17) [8]

А еще такой вопросик, не стал новую тему создавать...
Слышал, что в новых версиях msSQL не будет типа данных image. На сколько эти слуи - правда?


 
Anatoly Podgoretsky ©   (2008-07-14 08:35) [9]

> Viod  (14.07.2008 6:17:08)  [8]

Тип будет, имени не будет.
А зачем слухами пользуешься?


 
Viod ©   (2008-07-14 10:01) [10]

Да не то чтобы пользуюсь - услышал и спросил по быстрому.
Имени не будет... Так процедуры хранимые переписывать придется при переводе на новую версию сервера?


 
clickmaker ©   (2008-07-14 11:12) [11]

> if @ActNam="SEL"
> begin
> Select code from temp_table;
> Goto Fin;
> end;

Хм... а почему goto, а не else?


 
Anatoly Podgoretsky ©   (2008-07-14 11:50) [12]


> Имени не будет... Так процедуры хранимые переписывать придется
> при переводе на новую версию сервера?

Возможно и придется, имя типа будет другое.


 
Ega23 ©   (2008-07-14 19:43) [13]


> Хм... а почему goto, а не else?


Это лишь шаблон, там этих @AcNam до чёртиков может быть.
Короче, привык так...  :)


 
Viod ©   (2008-07-28 10:09) [14]

А вот такой вопрос: для того чтобы вытащить из базы blob поле в Stream  мы используем ADODataSet. По методу Open он как я понимаю должен вернуть набор записей. А если записи не вернулись, тоесть хранимая процедура не вернула набор записей - дебаггер оворит, что все плохо :)

Хранимая процедура выглядит так:
IF EXISTS(select .......)
    BEGIN
       SELECT ...........
       RETURN 0
    END
    ELSE RETURN -1

Так вот когда RETURN -1, тогда Open сделать не выходит...
Как обработать этот случай. Или как получить blob с помощью AdoCommand.

Пробовал AdoCommand.Execute.Fields[номер поля].value вроде возвращает обычные типы данных а вот blob не хочет


 
Ega23 ©   (2008-07-28 10:18) [15]


> Хранимая процедура выглядит так:


А не надо так делать. Возвращай Select в любом случае. т.е. вместо

IF EXISTS(select .......)
   BEGIN
      SELECT ...........
      RETURN 0
   END
   ELSE RETURN -1


делай


SELECT .....
RETURN 0


А вот на клиенте уже проверяй:

with DataSet do
begin
 try
   Open;
   if IsEmpty then ....    // <- записей нет
   else  ....                  // <- записи есть

 except
   ....
 end;
end;


 
Viod ©   (2008-07-28 10:42) [16]

Ясно... Ну а чисто теоретически с AdoCommand реально?


 
Ega23 ©   (2008-07-28 10:47) [17]


> Ну а чисто теоретически с AdoCommand реально?


Реально. _RecordSet же есть.
Но не советую. В смысле, как у тебя запрос был сформирован. В одном случае НД возвращается, а в другом - нет. Причём заранее определить нельзя - вернётся он или нет.
Это потенциальная дыра.


 
Viod ©   (2008-07-28 10:50) [18]

так вот интересно.
rec:_recordset;

rec:=AdoCommand.execute;
Это вобще правильно или нет?


 
sniknik ©   (2008-07-28 10:51) [19]

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

имхо, то что ты делаешь и в процедуру то "заворачивать" смысла нет... (как и 90% написанных sql процедур, их пишут не потому что они действительно нужны, а потому что начинающему сказали что это "круто"/правильно/лучше/удобнее(?)/...)


 
sniknik ©   (2008-07-28 10:53) [20]

> В одном случае НД возвращается, а в другом - нет.
в любом случае возвращается.


 
Viod ©   (2008-07-28 11:00) [21]

просто хочется всю безопасность со своего кода на sql переложить


 
Ega23 ©   (2008-07-28 11:01) [22]


> в любом случае возвращается.



IF EXISTS(select .......)
  BEGIN
     SELECT ...........
     RETURN 0
  END
  ELSE RETURN -1


Где тут НД возвращается, если not exists?


 
Viod ©   (2008-07-28 11:03) [23]

Ниче не вернет если нот ексистс проверено :)


 
Viod ©   (2008-07-28 11:08) [24]

sniknik, а че плохо чтоле? Получил 0 - работай, получил -1 не работай.
А если тебе нужно по сложному алгоритму что-то из базы получать. Клиентская машина итак еле шевелится. Перекладываешь все на SQL"ник и все. Код в дельфи прилично выглядит: не приходится запросы писать, а они ведь бывают очень длинными. Да и потом хранимые процедуры и с представлениями могут работать.. Попробуй ка все в делфи впихнуть :)
А проверки в хранимых процедурах... пустой набор записей когда возвращается - тоже вроде не очень приятно?


 
Viod ©   (2008-07-28 11:08) [25]

sniknik, а че плохо чтоле? Получил 0 - работай, получил -1 не работай.
А если тебе нужно по сложному алгоритму что-то из базы получать. Клиентская машина итак еле шевелится. Перекладываешь все на SQL"ник и все. Код в дельфи прилично выглядит: не приходится запросы писать, а они ведь бывают очень длинными. Да и потом хранимые процедуры и с представлениями могут работать.. Попробуй ка все в делфи впихнуть :)
А проверки в хранимых процедурах... пустой набор записей когда возвращается - тоже вроде не очень приятно?


 
sniknik ©   (2008-07-28 11:10) [26]

> Где тут НД возвращается, если not exists?
AdoCommand.execute:_recordset;

> Ниче не вернет если нот ексистс проверено :)
тебе это просто не показывают... а на самом деле возвращается, без рекордсета оно не может, там кроме данных в структуре еще информационная инфа есть т.что. в любом случае. гарантированно.


 
sniknik ©   (2008-07-28 11:13) [27]

> sniknik, а че плохо чтоле? Получил 0 - работай, получил -1 не работай.
то же самое от запроса. никакой выгоды... как минус разнесение логики на 2 места. (возможно именно это и нужно, но это как раз входит в оставшиеся 10% вместе со сложными процедурами. вряд ли твой случай)


 
Viod ©   (2008-07-28 11:15) [28]

Ну тут я не знаю.. Не специалист. Просто на деле получается исключение. Предлагаешь отключить integrated debugging и смотреть IsEmpty как ни в чем не бывало?


 
sniknik ©   (2008-07-28 11:17) [29]

> Просто на деле получается исключение.
sniknik ©   (28.07.08 10:51) [19]
> просто по пустому в твоем случае уже ADODataSet генерит исключение

> AdoCommand.execute


 
Viod ©   (2008-07-28 11:31) [30]

sniknik, мы не поняли друг друга. На 2 проверки все разносится потому что я не могу использовать AdoCommand для выборки из базы blob поля. Если бы я это сделал - я бы использовал возвращаемые хранимой процедурой значения. А поскольку мне приходится использовать aDodataSet - получается что я сделал мартышкин труд. Когда я все это планировал - думал использовать только AdoCommand и только проверки внутри хранимой процедуры.
Объясни лучше как получить значение Blob поля из выборки, исползуя  AdoCommand. Blob поле будет допустим в fields[0]


 
sniknik ©   (2008-07-28 11:52) [31]

> На 2 проверки все разносится потому что я не могу использовать AdoCommand для выборки из базы blob поля.
тебе не предлагали использовать AdoCommand для blob, это было предложено уже для проверки, что и RETURN -1 вернет рекордсет.

по твоей "проблеме" нормальное решение предложил Ega23 ©   (28.07.08 10:18) [15], проверка в одном месте.

> Объясни лучше как получить значение Blob поля из выборки, исползуя  AdoCommand.
это будет ненормальное решение... но раз так хочется, присвой результат execute рекордсету в ADODataSet и работай уже с ним (или посмотри как он это делает, и повтори... если желаешь еще больше мазохистских удовольствий.).


 
sniknik ©   (2008-07-28 11:54) [32]

> А поскольку мне приходится использовать aDodataSet - получается что я сделал мартышкин труд.
именно им ты сейчас и занимаешься. нужно упрощать то, что делаешь а не усложнять.

-----------------------------
усложнять просто, упрощать сложно! © не помню чей


 
Viod ©   (2008-07-28 12:03) [33]

:) Сижу и не могу... Давай так: однозначный ответ на вопрос "можно вытащить из базы блоб поле и загрузить его в Stream используя AdoCommand, но не используя AdoDataSet"? Да или Нет? :)

Я же говорю, чисто теоретически. Проблема уже решена благодаря Ega23, за что большое спасибо.

Просто изначально планировалось, что с базой будет работать один единственный компонент AdoCommand. Вот я и мучаю себя и остальных, чтобы однозначно понять реально это или нет


 
Ega23 ©   (2008-07-28 12:10) [34]


> можно вытащить из базы блоб поле и загрузить его в Stream
> используя AdoCommand, но не используя AdoDataSet


Можно. Но не стОит.


 
Ega23 ©   (2008-07-28 12:12) [35]


> Просто изначально планировалось, что с базой будет работать
> один единственный компонент AdoCommand.


Это не самый лучший вариант. Есть такая вещь, как скомпилированные запросы (Prepared:=True); на такие лучше свой экземпляр TADODataSet или TADOCommand держать.


 
sniknik ©   (2008-07-28 12:14) [36]

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

> что с базой будет работать один единственный компонент AdoCommand.
а смысл? на компонентах экономить не стоит, раз уж чтото используется, то используется, хоть 1 раз встреченное хоть 128, на размере exe не скажется, проверь, добавь несколько пустышек (без запросов внутри, они то добавятся, а код нет. ООП однако.)


 
Viod ©   (2008-07-28 12:32) [37]

Не могу ниче понять. Может туплю...
Вот t-sql:

CREATE PROCEDURE s_select_vopros_by_id
 @id_vopros int=0
AS
SELECT * FROM new_test.dbo.t_vopros WHERE id_vopros=@id_vopros

Вот Delphi:

with data.ADODataSet1 do begin
   CommandText:="exec s_select_vopros_by_id @id_vopros=:id_vopros";
   Parameters.ParamByName("id_vopros").Direction:=pdInput;
   Parameters.ParamByName("id_vopros").Value:=number;
   Open;
   If not(IsEmpty) then
     Showmessage(FieldByName("id_vopros").value);
end;

Первый раз код делфи проходит с number: = 110 - все норм, второй раз с number:=112  - showmessage ВОЗВРАЩАЕТ 110.

Как так?


 
Ega23 ©   (2008-07-28 12:36) [38]


>
> Как так?


А где Close?


 
Viod ©   (2008-07-28 12:41) [39]

Удалено модератором


 
Ega23 ©   (2008-07-28 12:43) [40]


> Спасибо за помощь, думаю не последний раз написал ;)


Не за что, удачи!


 
Anatoly Podgoretsky ©   (2008-07-28 13:01) [41]

> sniknik  (28.07.2008 12:14:36)  [36]

На размере ехе скажется как раз один AdoCommand - не в лучшую сторону конечно.


 
Viod ©   (2008-07-29 10:05) [42]

Ко вчерашнему спрору о проверке внутри процедуры или в делфи:
Допустим хранимая процедура получает параметром идентификатор записи. Смотрит есть ли эта запись if EXISTS(SELECT... WHERE Idn=@idn) и удаляет запись и возвращает 0. Если записи нет, то возвращает -1.
Как мне в этом случае оставить проверку на стороне приложения? В смысле как это сделать более-менее коротко и красиво?


 
Ega23 ©   (2008-07-29 10:16) [43]

Способ 1.
Declare @X int;
Select @X=exec S_MyProc @Id=18;
Select Result=@X;


Способ 2.


CREATE PROCEDURE s_MyProc

 @ID int =-1,
 @SelOut int = 1,
 @Debug int =0
As
 Declare @result int;

if Exists (Select ... from ... where id=@ID)
begin
 Delete from ... where ID=@ID
 Set @Result=0
end
else
 Set Result=-1;

if @SelOut=1
 Select Result=@result;

return(@result);

GO


Вызов второго варианта.
Если хочешь получить результат, то через TADODataSet.Open:
exec S_MyProc @ID=...
Если не хочешь получить результат, то через TADOCommand.Execute:
exec S_MyProc @ID=..., @SelOut=0


 
Viod ©   (2008-07-29 12:54) [44]

Спс.


 
sniknik ©   (2008-07-29 13:32) [45]

> удаляет запись и возвращает 0. Если записи нет, то возвращает -1.
способ 3... правильный. (бредите вы этими процедурами чтоли?)

- простейший запрос в ADOCommand1, внесенный в десигне, вида
delete from ... where ID=:ID
 
выполнение
var
 RecAff: integer;
begin
 ADOCommand1.Parameters.ParamByName("ID").Value:= ...;
 ADOCommand1.Execute(RecAff);
 if RecAff > 0
   then //есть запись, а может и не одна (что подразумевает ID?)
   else //нет записей
end;


все. и зачем сложности с процедурами? не нужна она тут.



Страницы: 1 2 вся ветка

Текущий архив: 2009.03.29;
Скачать: CL | DM;

Наверх




Память: 0.6 MB
Время: 0.034 c
15-1232091715
TUser
2009-01-16 10:41
2009.03.29
Философия математики


15-1232824673
Unknown user
2009-01-24 22:17
2009.03.29
Модель приложения, основанная на сообщениях.


3-1217396216
Alexandra
2008-07-30 09:36
2009.03.29
Учетная запись-посредник для процедуры xp_cmdshell


2-1233895829
des
2009-02-06 07:50
2009.03.29
Как отловить ошибку 405?


1-1208685519
Kolan
2008-04-20 13:58
2009.03.29
Сложный кросс таб отчет. Варианты реализации.