在開發、測試、部署階段,常需將特定資料表的資料導出為標準 SQL INSERT 腳本,以便在不同環境間遷移資料。本文提供一個基於 TClientDataSet 的通用單元,支援多表一次匯出、自動處理資料類型轉換(字串、日期時間、布林、NULL)、匯入時自動 TRUNCATE 清空目標表。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Data.DB, Datasnap.DBClient;
type
TForm1 = class(TForm)
cds: TClientDataSet;
Button1: TButton; // 匯出
Button2: TButton; // 匯入
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
procedure ExportData(const TableNames: string);
procedure ImportData(const FileName, TableNames: string);
public
end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses untDB; // 假設包含 frmDB: TDataModule,提供 QuerySQL/ExecuteSQL 封裝
// ---------- 輔助:根據欄位型別轉換為 SQL 字面值 ----------
function GetFieldValue(Field: TField): string;
begin
case Field.DataType of
ftString, ftWideString, ftFixedChar, ftWideMemo, ftMemo,
ftDate, ftTime, ftDateTime, ftTimeStamp:
Result := QuotedStr(Field.AsString); // 字串/日期時間加單引號
ftBoolean:
Result := IfThen(Field.AsBoolean, '1', '0'); // 布林轉 1/0
else
if not VarIsNull(Field.Value) then
Result := VarToStr(Field.Value) // 數值、Blob 等直接轉字串
else
Result := 'NULL';
end;
end;
// ---------- 匯出:多表合併為單一 .sql 檔 ----------
procedure TForm1.ExportData(const TableNames: string);
var
SQL, Err: string;
SL, Tables: TStringList;
I, H: Integer;
FieldNames, Values: string;
begin
if TableNames = '' then Exit;
Tables := TStringList.Create;
Tables.Delimiter := ',';
Tables.DelimitedText := TableNames; // "bas_kind,bas_goods"
SL := TStringList.Create;
try
for H := 0 to Tables.Count - 1 do begin
SQL := 'SELECT * FROM ' + Tables[H];
if frmDB.QuerySQL(SQL, cds, Err) and not cds.IsEmpty then begin
cds.First;
while not cds.Eof do begin
FieldNames := ''; Values := '';
for I := 0 to cds.FieldCount - 1 do begin
if FieldNames = '' then FieldNames := cds.Fields[I].FieldName
else FieldNames := FieldNames + ',' + cds.Fields[I].FieldName;
if Values = '' then Values := GetFieldValue(cds.Fields[I])
else Values := Values + ',' + GetFieldValue(cds.Fields[I]);
end;
SL.Add('INSERT INTO ' + Tables[H] + '(' + FieldNames + ') VALUES (' + Values + ')');
cds.Next;
end;
end;
end;
SL.SaveToFile(ExtractFilePath(Application.ExeName) + 'export.sql');
finally
SL.Free; Tables.Free;
end;
end;
// ---------- 匯入:執行 .sql 檔,前置 TRUNCATE ----------
procedure TForm1.ImportData(const FileName, TableNames: string);
var
Cmd, Tables: TStringList;
Err, SQL: string;
I: Integer;
begin
if not FileExists(FileName) or (TableNames = '') then Exit;
Tables := TStringList.Create;
Tables.Delimiter := ','; Tables.DelimitedText := TableNames;
// 1. 先清空目標表
for I := 0 to Tables.Count - 1 do begin
SQL := 'TRUNCATE TABLE ' + Tables[I];
frmDB.ExecuteSQL(SQL, Err);
end;
Tables.Free;
// 2. 執行腳本
Cmd := TStringList.Create;
try
Cmd.LoadFromFile(FileName);
frmDB.ExecuteSQL(Cmd.Text, Err); // 批次執行
finally
Cmd.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin ExportData('bas_kind,bas_goods'); end;
procedure TForm1.Button2Click(Sender: TObject);
begin ImportData(ExtractFilePath(Application.ExeName) + 'export.sql', 'bas_kind,bas_goods'); end;
end.
TDataSet 介面,適用於任何支援 SELECT * 的資料集。GetFieldValue 針對字串/日期加引號、布林轉 1/0、NULL 正確輸出 NULL 關鍵字。ExecuteSQL(Cmd.Text),由資料庫引擎批次提交,遠快於逐條執行。TRUNCATE 確保環境乾淨,避免主鍵衝突。.sql 納入 Git,追蹤資料變更歷史。COMMIT 或使用資料庫原生匯出工具。VarToStr 簡單轉換可能不適用。以 TClientDataSet 為橋樑,幾十行代碼即可實現「資料表 ↔ INSERT 腳本」雙向轉換,極大提升資料遷移與版控效率。代碼來源:cnblogs 詠南,經整理補全錯誤處理與註釋。