Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.03.2015, 14:26   #1
TimurUfa
 
Регистрация: 16.01.2015
Сообщений: 5
По умолчанию Работа с BLOB полем MySQL в Delphi

Здравствуйте, понимаю, что тема не новая, но я так и не нашел ее решения, везде натыкался на "Да таких тем сотни, ищи в гугле".
Суть моей задачи:
Имеется таблица Certificates
Код:
(
    id tinyint not null auto_increment,
    FIO varchar(100),
    type varchar(100),
    image mediumblob,
    startdate date,
    finishdate date,
    primary key (id)
)
Возникает проблема с добавлением именно BLOB переменной (представляет собой картинку, открываемую с помощью OpenDialog). приведу пример своего кода, который смог написать, но понимаю что он нифига не рабочий(

Код:
filename:=ExtractOnlyFileName(StringGrid1.Cells[0,i]);
        //выделяем из имени файла (filename) фио, тип удостоверения, дату начала и окончания действия
        GetStringData(filename,j,4,',');
        jp.LoadFromFile(StringGrid1.Cells[0,i]);
        FIO:=str[1];
        CerType:=str[2];
        sdatestr:=str[3];
        fdatestr:=str[4];
        //форматируем даты в нужный для MySQL формат
        GetStringData(sdatestr,j,3,'.');
        startdate:=str[3]+'-'+str[2]+'-'+str[1];
        GetStringData(fdatestr,j,3,'.');
        finishdate:=str[3]+'-'+str[2]+'-'+str[1];
        DataModule.Query.Active:=False;
        DataModule.Query.SQL.Clear;
        with DataModule.Query.SQL do
          begin
            Add('INSERT INTO Certificates (FIO, Type, image, StartDate, FinishDate)');
            Add('VALUES (''' + FIO + ''',''' + CerType + ''',' +  jp + ',''' + startdate + ''',''' + finishdate +''')');
          end;
        DataModule.Query.ExecSQL;
        DataModule.Table.Active:=False;
        DataModule.Table.Active:=True;
Буду крайне признателен за кусок рабочего кода) Или подсказки к исправлению моего
TimurUfa вне форума Ответить с цитированием
Старый 06.03.2015, 14:40   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Делай через параметры формирование запроса и у параметра есть методы для загрузки блоб-поля из файла или потока
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 06.03.2015, 15:45   #3
TimurUfa
 
Регистрация: 16.01.2015
Сообщений: 5
По умолчанию

Это я примерно понимаю, даже нашел пару примеров, но вот именно загрузку в MySQL изображения через переменную найти не смог.
Может есть какой-то код, иллюстрирующий загрузку через INSERT INTO?
TimurUfa вне форума Ответить с цитированием
Старый 06.03.2015, 15:54   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
загрузку в MySQL изображения через переменную найти не смог
И не найдешь. В файле же есть эта картинка. Можно из него напрямую методом параметра LoadFromFile, можно из потока методом LoadFromStream
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 06.03.2015, 16:13   #5
TimurUfa
 
Регистрация: 16.01.2015
Сообщений: 5
По умолчанию

Примерно понял, я уже в принципе рассматривал этот вариант на примере:
Код:
  AdoTable1.Edit;
  AdoTable1Ole.LoadFromFile(OpenDialog1.FileName); //загружаем картинку
  AdoTable1.Post;
И не раз видел такие варианты, но везде используется Post/Edit. Ни разу не видел использование INSERT. Можно конечно сначала создавать запись, вносить часть данных, затем возвращаться в эту запись и пользоваться Edit'ом, но как-то это рукожопо, неужели нету способа добавления через INSERT вместе с остальными полями?(
TimurUfa вне форума Ответить с цитированием
Старый 06.03.2015, 16:32   #6
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Вот что такое параметризованный запрос примерно к твоему случаю
Код:
  try
    Query.SQL.Text:='INSERT INTO Certificates (FIO,Type,image,StartDate,FinishDate) VALUES (:FIO,:Type,:image,:StartDate,:FinishDate)';
    Query.ParamByName('FIO').Value:=FIO;
    Query.ParamByName('Type').Value:=CerType;
    Query.ParamByName('image').LoadFromFile(StringGrid1.Cells[0,i],ftBlob);
    Query.ParamByName('StartDate').Value:=startdate;
    Query.ParamByName('FinishDate').Value:=finishdate;
    Query.ExecSQL;
  except
  //здесь обработка ошибки
  end;
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 06.03.2015, 17:29   #7
TimurUfa
 
Регистрация: 16.01.2015
Сообщений: 5
По умолчанию

ОГРОМНОЕ СПАСИБО!)
Пытался уже до этого пробовать параметризированный запрос, но наступал на грабли и бросил этот путь, а сейчас все получилось)
Правда до полного запуска получил по лбу еще 2 граблями, но вроде исправил и данные в бд занес)
Теперь буду корпеть над следующим этапом, выборке из бд и сражению с "bitmap is not valid")
Еще раз огромное спасибо за подсказку, если вдруг кому понадобится, то вот полный листинг:

Код:
unit WordChange;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.ComCtrls,
  Vcl.Grids, Vcl.DBGrids, COMobj, ActiveX, Vcl.ExtCtrls, Vcl.DBCtrls, DB;

type
  TUpdateWord = class(TForm)
    BitBtn1: TBitBtn;
    BitBtn3: TBitBtn;
    ProgressBar1: TProgressBar;
    StringGrid1: TStringGrid;
    DBGrid1: TDBGrid;
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  UpdateWord: TUpdateWord;
  str: array[1..50] of string;
  filename, FIO, CerType, sdatestr, fdatestr, startdate, finishdate: string;
  i, j: integer;

implementation

{$R *.dfm}

uses Data;

//процеура для извлечения из полного пути только имени, без расширения
function ExtractOnlyFileName(const FileName: string): string;
begin
  result:=StringReplace(ExtractFileName(FileName),ExtractFileExt(FileName),'',[]);
end;

//процедура для выделения из строки StrText отдельных слов, разделенных символом Sym
procedure GetStringData (StrText: string; step, k: integer; Sym: char);
begin
  for step := 1 to k do
    //проверяем наличие символа в строке
    if Pos(Sym, StrText)<>0 then
    begin
      //копируем из строки слово начиная с первой буквы до символа Sym
      Str[step]:=Copy(StrText,1,Pos(Sym,StrText)-1);
      //удаляем из строки слово и символ Sym
      Delete(StrText,1,Pos(Sym,StrText));
    end
    else
      Str[step]:=Copy(StrText,1,length(StrText));
end;

//процедура загрузки имен открытых файлов в таблицу
procedure TUpdateWord.BitBtn1Click(Sender: TObject);
begin
  if DataModule.OpenDialog.InitialDir='' then
      DataModule.OpenDialog.InitialDir:= ExtractFilePath(ParamStr(0));
  if DataModule.OpenDialog.Execute then
  begin
    StringGrid1.RowCount:=DataModule.OpenDialog.Files.Count+1;
    for I := 1 to StringGrid1.RowCount-1 do
      StringGrid1.Rows[i].Clear;
    for i := 1 to DataModule.OpenDialog.Files.Count do
      StringGrid1.Cells[0,i]:=DataModule.OpenDialog.Files.Strings[i-1];
  end;
end;

//процедура занесения информации из имени файла и самого файла в БД
procedure TUpdateWord.BitBtn3Click(Sender: TObject);
begin
  if StringGrid1.Cells[0,1]<>'' then
    begin
      ProgressBar1.Position:=0;
      ProgressBar1.Step:=1;
      ProgressBar1.Max:=StringGrid1.RowCount-1;
      for i := 1 to StringGrid1.RowCount-1 do
      begin
        ProgressBar1.StepIt;
        filename:=ExtractOnlyFileName(StringGrid1.Cells[0,i]);
        //выделяем из имени файла (filename) фио, тип удостоверения, дату начала и окончания действия
        GetStringData(filename,j,4,',');
        FIO:=str[1];
        CerType:=str[2];
        sdatestr:=str[3];
        fdatestr:=str[4];
        //форматируем даты в нужный для MySQL формат
        GetStringData(sdatestr,j,3,'.');
        startdate:=str[3]+'-'+str[2]+'-'+str[1];
        GetStringData(fdatestr,j,3,'.');
        finishdate:=str[3]+'-'+str[2]+'-'+str[1];
        //очищаем SQL
        DataModule.Query.Active:=False;
        DataModule.Query.SQL.Clear;
        with DataModule.Query do
          begin
          SQL.Text:='INSERT INTO Certificates (FIO, Type, image, StartDate, FinishDate) VALUES (:FIO, :Type, :image, :StartDate, :FinishDate)';
          Parameters.ParamByName('FIO').Value:=FIO;
          Parameters.ParamByName('Type').Value:=CerType;
          Parameters.ParamByName('image').LoadFromFile(StringGrid1.Cells[0,i],ftBlob);
          Parameters.ParamByName('StartDate').Value:=startdate;
          Parameters.ParamByName('FinishDate').Value:=finishdate;
          ExecSQL;
          end;
        DataModule.Table.Active:=False;
        DataModule.Table.Active:=True;
      end;
    end
    else
    ShowMessage('Выберите файлы для добавления');
end;

procedure TUpdateWord.FormCreate(Sender: TObject);
begin
  StringGrid1.ColWidths[0]:=StringGrid1.Width-100;
  StringGrid1.Cells[0,0]:='Наименование документа';
  StringGrid1.Cells[1,0]:='Статус';
end;

end.
TimurUfa вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
MySQL Delphi Поля BLOB xxbesoxx БД в Delphi 0 03.11.2013 22:42
Работа с BLOB полем Anubys C++ Builder 7 23.03.2012 00:05
Удаление из базы с BLOB-полем artemavd БД в Delphi 3 03.03.2012 22:12
Ошибка работы с blob полем, в похожем проекте все работает Lokos БД в Delphi 6 25.02.2010 08:17
Проблема с Blob полем Constellation БД в Delphi 6 24.01.2008 18:58