首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Delphi 搭配 Oracle 以 VARCHAR2 分段儲存與全文檢索 RTF 文件

     編輯:Oracle 資料庫基礎

背景與挑戰

Oracle LONG RAW 不支援 LIKE/= 查詢,無法滿足「大文本儲存 + 全文檢索」雙重需求。本文方案:將 RTF 內容切割為 ≤2000 字元的 VARCHAR2(2000) 片段儲存,配合重疊區設計實現跨片段關鍵字搜尋。

資料表結構

CREATE TABLE TEST (
  DOCID   NUMBER NOT NULL,      -- 文件編號
  DOCNAME VARCHAR2(40) NOT NULL, -- 文件標題
  SUBID   NUMBER NOT NULL,      -- 片段流水號
  TEXT    VARCHAR2(2000) NOT NULL, -- 片段內容
  PRIMARY KEY (DOCID, SUBID)
);

核心技巧

  1. 分段儲存:TRichEdit.SaveToFile 存臨時 .rtf → 以 BlockRead 每次讀 2000 字元 → 寫入 TEXT 欄位,SUBID 遞增。
  2. 重疊區設計:每片段保留前 1900 字元有效內容,後 100 字元儲存下一片段的前 100 字元。確保關鍵字不會被切斷在兩片段交界處;查詢關鍵字長度限制 ≤100 字元 (50 中文字)。
  3. RTF 編碼轉換:RTF 中中文字以 \'xx\'yy 形式儲存。查詢前需將使用者輸入的關鍵字轉為同樣編碼 (雙位元組字元首位元 ≥ $80 判斷),單引號需轉義。
  4. 還原顯示:依 SUBID 讀出所有片段 → BlockWrite 重組臨時 .rtf → TRichEdit.LoadFromFile 顯示,完整保留格式。

關鍵 Delphi 函式

function ChnCharToRTFCode(Ch: string): string; // 雙位元組字元 → \'xx\'yy
function MakeLikeRTFString(StrToFind: string): string; // 完整關鍵字轉 RTF 編碼
function MakeLikeString(StrToFind: string): string; // 產生最終 SQL: SELECT DISTINCT DOCNAME FROM TEST WHERE TEXT LIKE '%...%'

完整程式碼片段 (節錄)

// 存入
function RTFToDB(ARichEdit: TRichEdit; DocName: string; ATable: TADOTable): Boolean;
var DocID, SubID, L: Integer; S: string; F: TFileOfChar; Buf: TBuffer;
begin
  ARichEdit.Lines.SaveToFile('c:\x.rtf');
  AssignFile(F, 'c:\x.rtf'); Reset(F);
  DocID := SelectSQL('SELECT NVL(MAX(DOCID)+1,101) FROM TEST');
  SubID := 0;
  while not EOF(F) do begin
    Inc(SubID); BlockRead(F, Buf, 2000, L); S := Copy(Buf,1,L);
    with ATable do begin Append; FieldByName('DOCID').AsInteger:=DocID;
      FieldByName('DOCNAME').AsString:=DocName; FieldByName('SUBID').AsInteger:=SubID;
      FieldByName('TEXT').AsString:=S; Post; end;
  end; Result:=True; CloseFile(F); DeleteFile('c:\x.rtf');
end;

// 讀出
function RTFFromDB(ARichEdit: TRichEdit; DocName: string; AQuery: TADOQuery): Boolean;
var S: string; F: TFileOfChar; Buf: TBuffer; I,L: Integer;
begin
  ARichEdit.Clear; AssignFile(F, 'c:\temp\x.rtf'); Rewrite(F);
  with AQuery do begin Active:=False; SQL.Clear;
    SQL.Add('SELECT SUBID, TEXT FROM TEST WHERE DOCNAME='''+DocName+''' ORDER BY SUBID'); Open;
    if RecordCount>0 then begin First; repeat
      S:=FieldByName('TEXT').AsString; L:=Length(S);
      for I:=1 to L do Buf[I]:=S[I]; BlockWrite(F, Buf, L); Next; until EOF; end; end;
  CloseFile(F); ARichEdit.Lines.LoadFromFile('c:\temp\x.rtf'); Result:=True;
  DeleteFile('c:\temp\x.rtf');
end;

優缺點總結

  • ✅ 相容標準 SQL LIKE,無需 Oracle Text/InterMedia 授權。
  • ✅ 完整保留 RTF 格式 (字型、顏色、段落)。
  • ⚠ 需限制查詢關鍵字長度;寫入/讀出需臨時檔案 I/O。
  • ⚠ 適用中小型文件;超大文件建議改用 Oracle Text / SecureFiles LOB。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved