Таблица SQL для записи Delphi с использованием BCP

У меня есть сценарий, в котором я должен экспортировать данные около 500000 записей из таблицы SQL для использования в приложении Delphi. Данные должны быть загружены в упакованную запись. Есть ли метод, в котором я могу использовать BCP для записи файла данных, аналогичного записи записей в файл.

На данный момент я загружаю данные, используя этот псевдокод.

    // Assign the data file generated from BCP to the TextFile object.
    AssignFile(losDataFile, loslFileName);
    Reset(losDataFile);
    while not EOD(losDataFile) do
    begin
      // Read from the data file until we encounter the End of File
      ReadLn(losDataFile, loslDataString);

      // Use the string list comma text to strip the fields
      loclTempSlist.CommaText := loslDataString;

      // Load the record from the items of the string list.
      DummyRec.Name := loclTempSList[0];
      DummyRec.Mapped = loclTempSList[1] = 'Y';
    end;

Для удобства я перечислил тип Dummy rec ниже

    TDummyRec = packed record
      Name : string[255];
      Mapped : Boolean;
    end;

Итак, мой вопрос заключается в том, чтобы вместо экспорта данных в текстовый файл можно было экспортировать данные в двоичный файл, чтобы я мог читать из файла напрямую, используя тип записи?

лайк

   loclFileStream := TFileStream.Create('xxxxxx.dat', fmOpenRead or fmShareDenyNone);
   while loclFileStream.Position < loclFileStream.Size do
   begin
     // Read from the binary file
     loclFileStream.Read(losDummyData, SizeOf(TDummyRec));
     //-  -------- Do wat ever i want.
   end;

У меня нет большого опыта использования BCP. Пожалуйста, помогите мне с этим.

Спасибо Терминатор...

2 ответа

В вашей записи, string[255] создаст строку Ansi фиксированного размера (т.е. так называемый shortstring). Этот тип явно устарел и не должен использоваться в вашем коде.

Это будет ужасная трата пространства, чтобы сохранить его напрямую, используя TFileStream (даже если это будет работать). Каждая запись будет хранить 256 байтов для каждого имени.

И используя string[255] (т.е. так называемый shortstring) сделает скрытое преобразование в строку для большинства доступа к ней. Так что это не самый лучший вариант, ИМХО.

Я советую использовать динамический массив, а затем сериализовать / десериализовать его с нашими классами Open Source. Для вашего хранилища вы можете использовать динамический массив. Работает с Delphi 5 до XE2. И вы сможете использовать string в записи:

TDummyRec = packed record
  Name : string; // native Delphi string (no shortstring)
  Mapped : Boolean;
end;

Изменить после комментария ОП:

BCP - это просто инструмент командной строки, предназначенный для экспорта большого количества строк в таблицу SQL. Так что ИМХО BCP не является хорошим кандидатом для ваших целей.

Кажется, вам нужно импортировать много строк из таблицы SQL.

В этом случае:

  • С помощью shortstring в любом случае будет пустой тратой памяти, так что вы получите быстрее из памяти, чем с использованием хорошего string;
  • Вы можете попробовать наши классы с открытым исходным кодом, чтобы получить все строки данных одну за другой, а затем заполнить свои записи, используя эти данные: см. SynDB классы - он легче, чем ADO; Затем вы сможете извлекать данные записи по одной, а затем использовать наши функции сериализации записей для создания некоторого двоичного содержимого - или попробовать специальный более быстрый движок, такой как SynBigTable;
  • Здесь есть несколько статей об использовании напрямую функции OleDB, используемой BCP из кода Delphi - она написана на французском языке, но вы можете использовать Google для ее перевода и здесь для быстрого массового копирования; полный исходный код включен.

Вы хотите прочитать SQL-таблицу в запись, я понятия не имею, почему вы работаете с архаичным AssignFile.

Вы действительно должны использовать TADOQuery (или подходящий вариант) для вашей базы данных.
Поместите в него разумный SQL-запрос; что-то вроде:

SELECT field1, field2, field3 FROM tablename WHERE .....

Если вы сомневаетесь, вы можете использовать:

SELECT * FROM tablename

Который выберет все поля из таблицы.

Следующий код будет проходить через все записи и все поля, сохранять их в вариантах и ​​сохранять их в FileStream.

function NewFile(Filename: string): TFileStream;
begin
  Result:= TFileStream.Create(Filename, fmOpenWrite);
end;

function SaveQueryToFileStream(AFile: TFileStream; AQuery: TADOQuery): boolean;
const
  Success = true;
  Failure = false;
  UniqueFilePrefix = 'MyCustomFileTypeId';
  BufSize = 4096;
var
  Value: variant;
  Writer: TWriter;
  FieldCount: integer;
  c: integer;
  RowCount: integer;
begin
  Result:= Success;
  try
    if not(AQuery.Active) then AQuery.Open

    FieldCount:= AQuery.Fields.Count;
    Writer:= TWriter.Create(AFile, BufSize);
    try
      Writer.WriteString(UniqueFilePrefix)
      //Write the record info first
      Writer.WriteInteger(FieldCount);
      //Write the number of rows
      RowCount:= AQuery.RecordCount;
      WriteInteger(RowCount);
      AQuery.First;
      while not(AQuery.eof) do begin
        for c:= 0 to FieldCount -1 do begin
          Value:= AQuery.Fields[c].Value;
          Writer.WriteVariant(Value);
        end; {for c}
        AQuery.Next;
      end; {while}
    except 
      Result:= failure;
    end;
  finally
    Writer.Free;
  end;
end;
Другие вопросы по тегам