首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 將資料表備份為 INSERT 腳本:TClientDataSet 通用匯出/匯入實現

     編輯:Delphi

前言

在開發、測試、部署階段,常需將特定資料表的資料導出為標準 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.

關鍵技術點解析

  1. 通用性: 僅依賴 TDataSet 介面,適用於任何支援 SELECT * 的資料集。
  2. 類型安全: GetFieldValue 針對字串/日期加引號、布林轉 1/0、NULL 正確輸出 NULL 關鍵字。
  3. 批次效能: 匯入時一次性 ExecuteSQL(Cmd.Text),由資料庫引擎批次提交,遠快於逐條執行。
  4. 冪等性: 匯入前 TRUNCATE 確保環境乾淨,避免主鍵衝突。

使用場景

  • 開發機 → 測試機:基礎資料(字典表、配置表)同步。
  • 版本控管:將核心資料表導出 .sql 納入 Git,追蹤資料變更歷史。
  • 容器化部署:建置 Docker Image 時執行匯入腳本初始化資料庫。

注意事項

  • 大量資料(>10 萬筆)建議分批 COMMIT 或使用資料庫原生匯出工具。
  • Blob/二進位欄位需特殊處理(Base64 編碼或十六進位字面值),本範例以 VarToStr 簡單轉換可能不適用。
  • 外鍵約束表需按相依順序匯入,或暫時停用約束。

結語

以 TClientDataSet 為橋樑,幾十行代碼即可實現「資料表 ↔ INSERT 腳本」雙向轉換,極大提升資料遷移與版控效率。代碼來源:cnblogs 詠南,經整理補全錯誤處理與註釋。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved