sqlite与delphi

来源:互联网 发布:常用域名服务器地址 编辑:程序博客网 时间:2024/05/16 14:03

之前在公司中编写了一个webservice服务,通过调用服务,才能继续后续操作其中webservice中自己做了cookie的保存以及session的处理,当时的session是通过hash存储的,但是后来在并发测试中发现会出现有hash是找不到的,后来在网上查了资料才知道是由于webmoudle的处理导致的创建了多个hash,最红找错了对象导致的,后来将hash完全存储为一个唯一的对象,解决了这个问题,不过最近在iis中发布后,为了提高效率将iis的进程数调整到了10个,结果又出现了类似的情况,现在就行将hash中维护的值,进行真正的唯一化,所以想使用sqlite处理。

       简单介绍一下sqlite:

       SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。

         不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。

        SQLite的数据类型

  首先你会接触到一个让你惊讶的名词: Typelessness(无类型). 对! SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中, 无论这列声明的数据类型

是什么(只有在一种情况下不是, 稍后解释). 对于SQLite来说对字段不指定类型是完全有效的. 如:

  Create Table ex1(a, b, c);

  诚然SQLite允许忽略数据类型, 但是仍然建议在你的Create Table语句中指定数据类型. 因为数据类型对于你和其他的程序员交流, 或者你准备换掉你的数据库引擎时能起到一个提示或帮助的作用. SQLite支持常见的数据类型, 如:

  CREATE TABLE ex2( a VARCHAR(10), b NVARCHAR(15), c TEXT, d INTEGER, e FLOAT, f BOOLEAN, g CLOB, h BLOB, i TIMESTAMP, j NUMERIC(10,5), k VARYING CHARACTER (24), l NATIONAL VARYING CHARACTER(16) );

  前面提到在某种情况下, SQLite的字段并不是无类型的. 即在字段类型为”Integer Primary Key”时.

        SQLite虽然很小巧,但是支持的SQL语句不会逊色于其他开源数据库,它支持的SQL包括:

  ATTACH DATABASE

        BEGIN TRANSACTION

  comment

  COMMIT TRANSACTION

  COPY

  CREATE INDEX

  CREATE TABLE

  CREATE TRIGGER

  CREATE VIEW

  DELETE

  DETACH DATABASE

  DROP INDEX

  DROP TABLE

  DROP TRIGGER

  DROP VIEW

  END TRANSACTION

  EXPLAIN

  expression

  INSERT

  ON CONFLICT clause

  PRAGMA

  REPLACE

  ROLLBACK TRANSACTION

  SELECT

  UPDATE 。

delphi如何使用sqlite呢?请看下面的简单的例子:

1 、准备工作part1

       delphi版本:delphi2007 for win32 update3。任意安装版本即可。

       sqlite dll版本:3.5.3。目前最新版本的sqlite引擎。[ http://www.sqlite.org/ ]

       sqlite for delphi:simple sqlite 3.0 for delphi。

2 、准备工作part2

      新建一个窗体应用程序工程,并设定保存的文件夹。将simple sqlite 3.0 for delphi 中的 sqlite3.pas,sqlite3table.pas,sqlite3udf.pas拷贝至工程所在的文件夹。并在工程中添加这三个文件。拷贝 sqlite.dll到编译生成exe文件的文件夹。
3、初步测试

      引用SQLiteTable3.pas单元。

在窗体上创建一个叫btnVersion的按钮(Tbutton)。在btnVersion的click事件中写入下面的代码。

procedure TfrmAbout.btnVersionClick(Sender: TObject);varSqliteDB:TSQLiteDatabase;beginSqliteDB:=TSQLiteDatabase.Create('');showmessage('Sqlite dll version:'+SqliteDb.version);SqliteDB.Free;end;

      编译运行,成功的话,将会显示当前的sqlite dll的版本号。


4 、简单工作原理描述

      在simple sqlite3.0 for delphi的几个文件中,主要用到两个文件。分别是sqlite3.pas,sqlite3table.pas。

      sqlite3.pas实现sqlite.dll的接口外部定义。

      sqlite3table.pas进行简单的访问函数封装。

      在delphi中,通过sqlite3table.pas来实现对sqlite数据库的各种访问。

     关于sqlite3udf.pas,根据作者的描述,主要用与创建用户自定义函数,具体功能未测试。


5、 读取数据

      假设,我们有一个叫做database.db的sqlite数据库文件,在编译生成的exe文件所在的目录。里面有一个叫做countries的表格。

      表格创建语句如下。

CREATE TABLE "Countries" (Name VARCHAR NOT NULL PRIMARY KEY UNIQUE, Capital VARCHAR NOT NULL, Area INTEGER NOT NULL, Pop INTEGER NOT NULL, PCI INTEGER NOT NULL );

我们该如何访问其中的第一条数据呢。

var
SqliteDB:TSQLiteDatabase;
SqliteTB:TSQLiteTable;
begin
SqliteDB:
=TSQLiteDatabase.Create('database.db');
SqliteTB:
=SqliteDB.GetTable('Select * from countries');
显示控件1.text:
=SqliteTB.FieldAsString(SqliteTB.FieldIndex['Name']);
显示控件2.text:
=SqliteTB.FieldAsString(SqliteTB.FieldIndex['Capital']);
显示控件3.text:
=SqliteTB.FieldAsString(SqliteTB.FieldIndex['Area']);
显示控件4.text:
=SqliteTB.FieldAsString(SqliteTB.FieldIndex['Pop']);
显示控件5.text:
=SqliteTB.FieldAsString(SqliteTB.FieldIndex['PCI']);
SqliteTB.free;
SqliteDB.free;
end;

TSQLiteTable类有两个方法,分别是Next和Previous,是用来向后和向前移动数据游标的。配合这两个方法,我们可以读取表格任意数据 内容。例如select * from countries where area >8000000的数据。


6、 写入数据

      我们可以读取数据,就可以写入数据。如何来做到呢?还是以Countries表为例。

var
SqliteDB:TSQLiteDatabase;
begin
SqliteDB:
=TSQLiteDatabase.Create('database.db');
SqliteDB.ExecSQL(
'Insert Into Countries (Name,Capital,Area,Pop,PCI) values ("China","Beijing",9600000,1500000000,6000)');
SqliteDB.Free; 
end;

同样,数据的update方法也可以按照这种方法来实现。在这里可以看到,字符类数据可以用双引号来标记起来,而不是通常sqlserver的单引号标记。
7、字符编码

      访问过MySql数据库数据的朋友应该记得噩梦般的中文数据存取经历。数据库里用了一种编码,程序又是另一种编码,导致中文数据变成乱码。

sqlite中,数据库内用的是UTF-8存取,DELPHI取出的数据是ASCII编码。也就是说,我们需要在存取的同时做编码转换。

有这样两个方法,utf8decode(),utf8encode()。当从数据库中读取数据时,我们用utf8decode();当向数据库中写入数据时,我们用utf8encode();

例如:

显示控件.text:=utf8decode(sltb.FieldAsString(sltb.FieldIndex['Name']));SqliteDB.ExecSQL(utf8encode('Insert Into Countries (Name,Capital,Area,Pop,PCI) values ("中国","北京",9600000,1500000000,6000)'));

 在有更好的方法之前,我们只能这么用……


8、 Blob 

      某些时候,我们会需要向数据库中存储和读取图片,视频,音频等信息的数据,例如:前女友们的性感照片。sqlite中有一种数据类型叫做Blob,可以满足我们的要求。如何访问和读取呢?

下面以在database.db数据库中PhotoLib表格中存取一个JPEG图片为例:

CREATE TABLE "PhotoLib" (Id Integer NOT NULL PRIMARY KEY UNIQUE, Photo BLOB);写入:varSqliteDB: TSQLiteDatabase;FS: TFileStream;beginSqliteDB:=TSQLiteDatabase.Create('database.db');FS := TFileStream.Create('test.jpeg',fmOpenRead);SqliteDB.UpdateBlob('UPDATE PhotoLib set Photo = ? WHERE ID = 1',FS);FS.free;SqliteDB.Free;end;读取至TImage控件显示:varMS: TMemoryStream;PIC: TJPegImage;SqliteDB: TSQLiteDatabase;SqliteTB: TSQLIteTable;beginSqliteDB:=TSQLiteDatabase.Create('database.db');SqliteTB:=SqliteDB.GetTable('Select * From PhotoLib Where Id=1');MS := SqliteTB.FieldAsBlob(SqliteTB.FieldIndex['photo']);
if (MS = nil) thenbeginshowmessage('该条记录没有前女友照片数据.');exit;end;MS.Position := 0;PIC := TJPEGImage.Create;PIC.LoadFromStream(ms);self.Image2.Picture.Graphic := PIC;MS.free;PIC.Free;end;
0 0
原创粉丝点击