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)
);
TRichEdit.SaveToFile 存臨時 .rtf → 以 BlockRead 每次讀 2000 字元 → 寫入 TEXT 欄位,SUBID 遞增。\'xx\'yy 形式儲存。查詢前需將使用者輸入的關鍵字轉為同樣編碼 (雙位元組字元首位元 ≥ $80 判斷),單引號需轉義。SUBID 讀出所有片段 → BlockWrite 重組臨時 .rtf → TRichEdit.LoadFromFile 顯示,完整保留格式。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;
LIKE,無需 Oracle Text/InterMedia 授權。