关系数据库都提供大文档的存储和提取。对于视频资料、音频资料、图象资料等大文档,一般需要 另外开辟字段用于存储摘要信息,因此在查询和检索时并不访问大字段,而只是在存储和提取时才操作 大字段。例如,你不能对oracle中的LONG RAW类型进行LIKE介词的查询,更不能使用等号“ =”查询。 这对于存储大段文本(容量超过2K)同时又需要全文检索是相当不便的。本文将介绍如何利用数据库的 字符串数据类型存取和查询大段文本。这里以Oracle数据库和Delphi应用程序为例,重点介绍如何在数据库中存取 RTF文档。

对于纯文本,可以简单地将其分割成若干个串,分别存储到VARCHAR(2000)字段中即可。在查询时 可以使用LIKE比较,从而达到全文检索的目的。为了保留换行等段落信息,应当将回车换行(#13#10) 也作为串的一部分进行保存。数据录入时可以提供Memo控件(不是DBMemo)进行录入,然后顺序连接各行,当连接成的串临近2000个字符(单字节字符)长度时,就存入一条记录,然后对剩余的行重复上述操作。这样,最终将纯文本存成若干长度不超过2000的VARCHAR(2000) 字段中。这里需要另外开辟字段 用于存储文本编号和子序号,以便区分不同的文本和读取文本时顺序连接所有的子串。查询纯文本时, 就可以象查询普通的VARCHAR 字段一样,可以使用LIKE,也可以使用等号“ =”(几乎不需要使用)。 需要注意的是,可能用户提供的关键字正好被存储在不同的子串中,这时是查询不到的。因此,在设计时应当考虑存储重复的串。例如,每个子串中仅有前1900个字符是有效字符,最后100 个字符用于存储 下一个子串的前100 个字符。这样就避免了关键字被分开的情况。唯一的不足是,必须限制用户输入的 查询关键字长度不得超过100 个字符(50个汉字),但这很正常,算不上不足。

事实上,同样可以利用这一技巧对 RTF文档进行存取和查询。这时,用于录入和显示 RTF文档的是 RichEdit控件(不是DBRichEdit),而不再是Memo控件。对于 RTF文档的存取,不能象存取纯文本那样 通过Memo的属性Lines.Strings[Index]进行操作(尽管RichEdit控件具有相同的属性),因为这样做就 无法保存文档的格式了。需要利用的是RichEdit的两个方法:SaveToFile和LoadFromFile。需要了解的 是, RTF文件中用纯字符描述字体、字号、文本等各种格式信息和内容信息。因此,存储和提取时可以 视为纯文本进行操作。但对于查询,就不能直接用LIKE加关键字的方式进行。因为 RTF文档中的每一个 汉字都是用特殊的表示方法存储,只有单字节字符是原样存储。所以在查询时要对关键字进行处理才能 用在查询语句中。

在测试这个例子之前,必须有如下的数据结构,这里以Oracle创建表的 SQL语句形式给出:

(*

CREATE TABLE TEST( { 表名为 TEST }

http://www.gaodaima.com/65614.htmlDelphi中对Oracle存取RTF文档_Delphi

DOCID NUMBER NOT NULL, { 文档编号 }

DOCNAME VARCHAR(40) NOT NULL, { 文档标题 }

SUBID NUMBER NOT NULL, { 文档子编号 }

TEXT VARCHAR(2000) NOT NULL, { 子文档内容 }

PRIMARY KEY(DOCID, SUBID)); { 联合主键 }

*)

下面是程序实例中的主要部分:

{ ... ... }

const

BufSize = 2000; { 串的最大容量 }

type

TBuffer = array [1..BufSize] of Char; { 串缓存 }

TFileOfChar = file of Char; { 字符类型文件 }

TChnChar = string[2]; { 汉字字符类型 }

{ SQL查询,返回首记录首字段的值 }

function SelectSQL(S: string): Variant;

begin

Result := NULL;

with TADOQuery.Create(Application) do try

Connection := FMain.ADOConnection1;

SQL.Append(S);

SQL.SaveToFile('c:/a.txt');

Open;

Result := Fields[0].AsVariant;

finally

Free;

end;

end;

{ 下面的函数将RTF文档存入数据库 }

function RTFToDB(ARichEdit: TRichEdit; { 文档容器 }

DocName: string; { 文档标题 }

ATable: TADOTable { 操作的表 }

): Boolean; { 返回类型 }

const

TmpFileName = 'c:/x.rtf'; { 临时文档 }

var

DocID, SubID, L: Integer; { 局部变量 }

S: string; { 串 }

F: TFileOfChar; { 字符文件 }

Buf: TBuffer; { 文本缓存 }

begin

ARichEdit.Lines.SaveToFile(TmpFileName);{ 先存入文件 }

AssignFile(F, TmpFileName); { 打开文件 }

Reset(F);

try

DocID := { 产生新的文档编号 }

SelectSQL('SELECT NVL(MAX(DOCID) + 1, 101) FROM TEST');

with ATable do if not Active then Active := True;{ 确认表打开 }

SubID := 0; { 初始化子编号 }

while not EOF(F) do begin

Inc(SubID);

BlockRead(F, Buf, BufSize, L); { 读取两千个字符 }

S := Buf;

SetLength(S, 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; { 存储成功 }

except

Result := False;{ 存储失败 }

end;

CloseFile(F); { 关闭文件 }

DeleteFile(TmpFileName);{ 删除文件 }

end;

{ 下面的函数从数据库中读取RTF文档,并在指定的容器中显示 }

function RTFFromDB(ARichEdit: TRichEdit;{ RTF文档容器 }

DocName: string; { 文档标题 }

AQuery: TADOQuery { 操作的数据集 }

): Boolean; { 返回类型 }

const

TmpFileName = 'c:/temp/x.rtf'; { 临时文件 }

var

S: string; { 局部串变量 }

F: TFileOfChar; { 字符文件 }

Buf: TBuffer; { 串缓存 }

I, L: Integer; { 局部变量 }

begin

ARichEdit.Clear; { 清除当前显示的内容 }

AssignFile(F, TmpFileName); { 关联文件 }

try

Rewrite(F); { 打开文件,准备写入从数据库读出的数据 }

with AQuery do begin

Active := False; { 关闭数据集 }

SQL.Clear; { 重建SQL语句 }

SQL.Append('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(TmpFileName);{ 从文件中装入RTF文档 }

Result := True; { 读取成功 }

except { 读取失败 }

try CloseFile(F); except end;

Result := False;

end;

DeleteFile(TmpFileName); { 删除临时文件 }

end;

{ 下面的函数将汉字单字转换成RTF中表示的形式。 }

{ 如表示汉字“国”的是ASCII(b9)和ASCII(fa),这里是十六进制; }

{ 那么在 RTF文件中对“国”字的表示占用了 8个字节: }

{ /'b9/'fa }

{ 因此,需要在查询之前进行转换。由于表示方法中含有Delphi用于 }

{ 字符串的分解符:单撇号“'”,因此在转换时需要考虑这一点, }

{ 否则就不能构造出正确的 SQL查询语句 }

function ChnCharToRTFCode(Ch: TChnChar): string;

var

C1, C2: Char;

O1, O2: Byte;

S: string;

begin

C1 := Ch[1];

C2 := Ch[2];

O1 := Ord(C1);

O2 := Ord(C2);

S := Format('/''''%2X', [O1]) + Format('/''''%2X', [O2]);

Result := Lowercase(S);{ 转换为小写 }

end;

{ 根据需要检索的关键字转换成LIKE中使用的串。 }

{ 这里用于区别汉字的方法是根据编码。 }

{ 按照Windows 中的双字节编码规则,对于双字节字符 }

{ 如汉字字符,是由两个字节构成,其中第一个字节是 }

{ 引导字符。汉字引导字符的ASCII 码大于 127,因此 }

{ 可以根据此特点来区分汉字和单字节字符。 }

function MakeLikeRTFString(StrToFind: string): string;

var

I: Integer;

ChnChar: TChnChar;

S: string;

begin

S := '';

I := 0;

while I < Length(StrToFind) do begin

Inc(I);

if Integer(StrToFind[I]) >= $80 then begin{ 汉字的首字节一定不小于128 }

ChnChar := StrToFind[I] + StrToFind[I + 1];

Inc(I);

S := S + ChnCharToRTFCode(ChnChar);

end else begin{ 单字节字符 }

S := S + StrToFind[I];

if StrToFind[I] = '''' then S := S + StrToFind[I];{ 单撇号的特殊处理 }

end;

end;

Result := S;

end;

{ 构造对关键字进行全文检索的查询语句 }

function MakeLikeString(StrToFind: string): string;

var

S: string;

begin

S := MakeLikeRTFString(StrToFind);

S := 'SELECT DISTINCT DOCNAME FROM TEST WHERE TEXT LIKE ''%' + S + '%''';

Result := S;

end;

欢迎大家阅读《Delphi中对Oracle存取RTF文档_Delphi》,跪求各位点评,若觉得好的话请收藏本文,by 搞代码

微信 赏一包辣条吧~

支付宝 赏一听可乐吧~

oracle有rtf函数,Delphi中对Oracle存取RTF文档_Delphi相关推荐

  1. Microsoft Windows 环境中NLS_LANG的正确设置 (文档 ID 1577370.1)

    Microsoft Windows 环境中NLS_LANG的正确设置 (文档 ID 1577370.1) 适用于: Oracle Database - Enterprise Edition - 版本 ...

  2. 查看本机中的python第三方库文档

    [转载] 原文链接:https://blog.csdn.net/weixin_43936250/article/details/105251049 本机系统为win10,在使用python编程的过程中 ...

  3. java打开密码pdf,在Java中使用密码解密PDF文档

    在Java中使用密码解密PDF文档 文档加密是确保企业与其外部客户之间安全地传递信息的最常用方法之一.所有PDF文件都提供了加密功能,可确保任何试图拦截信息的人都可以在没有密码的情况下打开它,密码应在 ...

  4. 在大数据中如何寻找相似的文档(shingle, minhash, LSH)(一)

    ps: 文章翻译与 Mining of Massive Datasets 场景:在一堆非常多的文档中,找到相似的文档,或者对文档间的相似性进行评估. 当应用于此类目的的时候,我们最常用的用来表示一篇文 ...

  5. HotPDF Delphi PDF VCL完全形成PDF文档

    HotPDF Delphi PDF VCL完全形成PDF文档 HotPDF Delphi PDF,用于创建和创建PDF文档的应用程序名称.您的公司已在您之前发布,以便在Delphi和C++中使用.事实 ...

  6. ubuntu中命令打开图片、文档、音乐、视频等

    ubuntu中命令打开图片.文档.音乐.视频等 安装播放软件 sudo apt install libdvdnav4 libdvdread4 gstreamer1.0-plugins-bad gstr ...

  7. Java 中的 XML:Java 文档模型的用法

    Java 中的 XML:Java 文档模型的用法 英文原文 内容: 代码对比 DOM JDOM dom4j Electric XML XPP 结束语 下一次... 参考资料 关于作者 对本文的评价 相 ...

  8. JAVA中利用DOM解析XML文档

    JAVA中利用DOM解析XML文档 package org.sws.utils; import java.io.File;import java.io.IOException; import java ...

  9. QTWebkit中的webkit/qt/api文档

    QTWebkit中的webkit/qt/api文档 概述 该目录下的文件均以前前缀qweb开头,主要用于支持前端的实现.核心的类为:qwebview.qwebpage.qwebframe等三个类.这三 ...

  10. Print2flash在.NET(C#)64位中的使用,即文档在线预览(转载)

    转:http://www.cnblogs.com/flowwind/p/3411106.html Print2flash在.NET(C#)中的使用,即文档在线预览 office文档(word,exce ...

最新文章

  1. Acwing第 25 场周赛【完结】
  2. Python + OpenCV 太好玩了,可惜你可能还不会
  3. linux下watch常见用法,watch命令详解(linux)
  4. 【踩坑记录】Tensorflow在Windows下使用
  5. 排序-选择类排序--堆排序简介
  6. Android,UbuntuCore,ROS;TuringOS,iBotOS,ROOBO
  7. python 连接MS sql server2005数据库
  8. sublime与python交互
  9. 由pthread_create引起的段错误
  10. 马化腾怒怼张一鸣;中兴产品下架;微信整改小程序 | CSDN 极客头条
  11. TCN-时间卷积网络
  12. 谷歌浏览器32位安装包_Chromium内核的edge浏览器终于来了,试用了半天,发现真香!...
  13. 计算机英语中级职称题库,职称计算机考试题库(中级职称需要考计算机吗)
  14. 微信视频文件保存在服务器吗,如何发送大的视频文件给朋友和家人
  15. python破解zip压缩包密码
  16. Gameplay框架
  17. Steave Jobs
  18. [YOLOv7]基于YOLO&Deepsort的交通车流量统计系统(源码&部署教程)
  19. 15000 字的 SQL 语句大全!
  20. 基于Java毕业设计学校图书馆管理系统源码+系统+mysql+lw文档+部署软件

热门文章

  1. 计算机打印字与印刷字的大小,字号与尺寸对表.doc
  2. 对称正定矩阵的Cholesky分解
  3. android安装svn,Android StudioSVN安装和使用
  4. HTML和JavaScript学习笔记
  5. 刚刚!2022年ABC中国大学排行榜发布
  6. Word:退出即关机(转)
  7. 化工热力学逸度计算_matlab程序,化工热力学逸度计算_Matlab程序
  8. 怎么把动图分解成图片?gif怎么拆分成几张?
  9. 【滑动窗口协议模拟】
  10. 基于ABAQUS蠕变储层稠油蒸汽吞吐开发过程数值模拟