VisualFreeBasic控件_SQLiteBox 本地小型数据库

2026-1-21 / 0 评论 / 951 阅读

SQLite3数据库是一个轻量级的嵌入式数据库引擎,广泛应用于各种应用程序中,包括移动设备、桌面应用程序和嵌入式系统。以下是SQLite3数据库的详细说明:

一、概述

  • 轻量级与高效:SQLite3以其轻量级和高效的特点著称,它占用的资源少,消耗总量小,适合在资源受限的环境中使用。
  • 嵌入式数据库:SQLite3可以直接嵌入到应用程序中,无需独立的数据库服务器。这种无服务器的架构简化了部署和管理,减少了与服务器通信的开销。
  • 零配置:使用SQLite3不需要复杂的配置过程,只需在应用程序中包含SQLite3的库文件即可开始使用。
  • 跨平台支持:SQLite3是一个跨平台的数据库引擎,可以在多种操作系统上运行,包括Windows、Linux、macOS、Android等。

二、特性

  1. 自包含性:SQLite3数据库是自包含的,它将所有的数据和数据库管理功能封装在一个文件中。这意味着你可以将整个数据库文件复制到其他地方,或者将它嵌入到另一个应用程序中,而不需要额外的配置或安装步骤。
  2. 数据类型支持:SQLite3支持多种数据类型,包括NULL、INTEGER、REAL、TEXT、BLOB和NUMERIC等,以满足不同类型数据的存储需求。同时,它也是一个动态类型的数据库引擎,允许在同一列中存储不同类型的值。
  3. 事务支持:SQLite3支持事务处理,允许从多个进程或线程安全地访问数据库。
  4. ACID兼容性:SQLite3的事务是完全兼容ACID(原子性、一致性、隔离性、持久性)的,确保了数据的一致性和可靠性。
  5. 简单易用:SQLite3使用简单的SQL语言进行数据操作,不需要独立的管理工具或复杂的设置过程。

三、应用场景

  • 移动应用:SQLite3是许多移动操作系统的默认数据库,适用于iOS和Android应用程序的本地存储。
  • 桌面应用:许多桌面应用程序,如文本编辑器、图像编辑软件等,使用SQLite作为其本地数据库,简化数据管理。
  • 嵌入式系统:由于其小巧的特性,SQLite3非常适合嵌入式设备,如家庭自动化系统、智能家居设备和汽车娱乐系统。
  • 开发与测试:SQLite3在开发和测试环境中也非常流行,方便开发者在不需要复杂数据库服务器的情况下进行数据测试和调试。

四、内置或外带DLL

内置的话会让 EXE 增加 1.5MB左右文件大小,外带 DLL,就是 需要带一个 sqlite3.dll 文件
默认是外带DLL,要想内置,你需要自己操作:
控件:
打开文件夹:VisualFreeBasic6\Control\SQLite3\lib
1,把32和64的文件夹删除,2,把里面的静态库文件,复制到“lib” 里面,
库:
打开文件夹:VisualFreeBasic6\Libs\public\database\SQLite3\lib
1,把32和64的文件夹删除,2,把里面的静态库文件,复制到“lib” 里面,
还可以在VFB里,库列表,右键选择“SQLite3”,弹出菜单中选择静态或动态库,即可。

本数据库,有“控件”和“库”使用,自己觉得那个方便,就用那个,但不可以同时使用,有了“控件”,就无法使用“库”编译会报重复的。

五、打开一个数据库文件

控件
在窗口放置一个控件,控件其实就是一个全局变量,不用自己声明全局变量,其它和库没分别,看大家习惯。

If SQLiteBox1.Open("c:\数据库文件.dp") =0 Then Print "打开失败" 

使用完成后,需要关闭数据库,因为控件是全局的,不关闭影响全局。

SQLiteBox1.Close 


需要自己声明变量,可以是局部,可以是全局。

dim dp as SQLiteDB 
If dp.Open("c:\数据库文件.dp") =0 Then Print "打开失败" 

使用完成后,局部变量,变量销毁会自动关闭,全局变量需要关闭

dp.Close 

打开有密码的数据库
控件

If SQLiteBox1.Open("c:\数据库文件.dp","密码") =0 Then Print "打开失败" 

If dp.Open("c:\数据库文件.dp","密码") =0 Then Print "打开失败" 

控件和库操作一样,后面就不重复举例

六、查询数据库

注意1:查询代码分W字符版和UTF8字符版,可以根据自己的需要使用,例题说明不提及UTF8字符版
注意2:返回的字符文字全部是 UTF8字符格式,使用时需要转换字符编码
查询相关参数说明

  • Table 表名
    如果特殊字符,比方包含空格、关键词、中文等,可以添加双引号 "表名"[表名] 不然会报错
   SQLiteBox1.Find("表名".....普通表名
   SQLiteBox1.Find("""表名""".....特殊表名
   SQLiteBox1.Find("[表名]".....特殊表名
   SQLiteBox1.Find("表名1,表名1".....多表联合查询
  • Cond 条件
    如ID>0 等等,就是字段名>、= 、<、<= 、>= 某值 还有 or and 等,和我们代码的 if 同样道理,无条件将查出全部 还有 id IN(2,10,30) 等列表条件,可以查阅相关的 SQL 条件说明 LIKE '%AA%' 模糊查找,%号表示任意字符,模糊条件不区分大小写。 字符串用单引号( ' ),如同 B语法的双引号,遇到值是单引号( ' ) ,那么和 B语法一样,用连续2个单引号 ( '' ) 表示1个单引号的值。
 SQLiteBox1.Find("表名","id>3".... 普通数值查询
 SQLiteBox1.Find("表名", "(id>3 And id<10) Or id=10 "....表达式查询,网上搜索SQL命令 ,和 Basic的条件语法很相似
 SQLiteBox1.Find("表名","[字段名]='文本'".... 字符查询
 SQLiteBox1.Find("表名"," [字段名] LIKE '%文本%'".... 字符模糊查询,%号表示任意字符,模糊条件不区分大小写
 SQLiteBox1.Find("表名", " id IN(2,10,30) "....多值查询,等通于:id = 2 Or id = 10 Or id = 30
  • rs() 返回查出的内容
    1:查询多行时是2维数组,rs(行,列) 0行为字段名称:如 rs(0,0 rs(0,1) 数据从 rs(1,x) 开始
    2:查询单行时是1维数组 rs(列)
    3:变量类型是 String ,不表示是 A字符,是原始数据,如果字段是字符,需要转换后使用。 如果字段是数字,用 val() valint() 转换,如果是字符,用 Utf8toStr 或Utf8toStringW 转换
  • Col 字段名称(列名)
    需要查询出什么字段,可以用 字段名1,字段名2,... 查出结果为指定列,将影响 rs() 结果
   SQLiteBox1.Find(表名, 条件, rs(), "*"....全部字段
   SQLiteBox1.Find(表名, 条件, rs(), "字段名1,字段名2,字段名2"....部分字段,为了节约查询时间,提供查询速度
  • Orderby 查出的数据按那个字段排序
    这里是 字段名称(列名)
    默认升序,倒序:字段名 DESC ,字段名称+空格+DESC ,默认值是ASC 可以多字段排序:字段名1,字段名2,字段名3 等等,也可以加 DESC 倒序,先排序 字段1,字段1里的内容字段2排序......
    SQLiteBox1.Find(表名, 条件, rs(), "*", "字段名1"....查出结果按[字段名1]从小到大排序
   SQLiteBox1.Find(表名, 条件, rs(), "*", "字段名1 DESC"....查出结果按[字段名1]从大到小排序
   SQLiteBox1.Find(表名, 条件, rs(), "*", "字段名1,字段名2,字段名3"....先按[字段名1]排序,字段1相同的按[字段名2]排序,以此类推。
  • Page 分页查询
    第 Page 页(最小是 1页),每页 Pagesize 行。不设置 Pagesize ,将查出全部内容。
  • Pagesize 1页多少条数据
  SQLiteBox1.Find(表名, 条件, rs(), 字段, 排序, 1,100)  查询第1页,每页100行                                                                                                                                                                                                                 

查询的行数太多,建议用分页查询,来保障软件执行效率。

六-1、查询多行数据

Dim rs() as String
   Dim as Long x,y
   If SQLiteBox1.Find("表名","条件", rs()) Then
      Print “行数=” &UBound(rs) & “,列数=” & UBound(rs, 2)
      For y = 0 To UBound(rs)  ' y = 0 时将显示字段名
         dim bb as String 
         For x = 0 To UBound(rs, 2)
            bb &=rs(y, x) & " , " ;  '如果是文本,因为是 UTF8 编码,需要转换后输出
         Next
         Print bb 
      Next
   Else
      Print "出错:"
   End If 

六-2、查询单行数据

有时候,只需要一行数据,返回全部字段

   Dim rs() as String 
   Dim as Long x,y
   If SQLiteBox1.FindOne("表名","条件", rs()) Then
      dim bb as String 
      For x = 0 To UBound(rs)
        bb &= rs(x) & " , " ;
      Next
   Else
      Print "出错:"
   End If 

六-3、查询单字段数据

查询出一行当中的一个字段,假如查询出多个字段,就返回第一个字段,当返回空时,表示查询失败。

uid = ValInt(Form1.SQLiteBox1.FindOnly("User" ,"uName='" & 账号 & "'" ,"uID")) 

六-4、查询带二进制字段的数据

当字段中,有一个二进制字段,就需要使用二进制查询来查,不然无法返回二进制内容

   SQLiteBox1.FindByte 查询多行
   SQLiteBox1.FindOneByte 查询单行
   SQLiteBox1.FindOnlyByte 查询单字段

使用方法参考 六-1 -2 -3 ,方法一样。方法内容也是一样。只是把二进制字段保存在 Str字符串中。

七、统计行数

和查询一样,这只是返回行数,条件参数查看查询里的说明。

行数=SQLiteBox1.Count(表名,条件)  

八、新增记录(一行)

返回=SQLiteBox1.AddItem(表名, 字段赋值列表)

字段赋值列表 有字段名和值组成,用英文逗号隔开

返回=SQLiteBox1.AddItem(表名, "字段名1=值1,字段名2=值2,字段名3=值3,字段名4=值4")

如果字段名是特殊字符,比如SQL命令里的关键词、非法字符等,用双引用或中括号 ”字段名“ 或 [字段名]
如果”值“是字符串,用单引用包裹,如:'文字内容' ,假如文字是单引用,那么用 2个单引号代表1个单引号
如果数据库表中字段没在赋值列表中,那么就按数据库表的默认值自动赋值。也就是说,字段有 10个,你只给1个字段赋值,那么其它的就按默认赋值。
返回: 当有自增主键(通常是 ID字段)就返回当前新增的ID,当无这样的字段,返回可能是0。当新增失败,返回0.

九、删除记录(多行)

  返回行数=  SQLiteBox1.DeleteItem(表名, 条件)

条件:参考查询里的条件说明,就是查询出的所有行,被删除
返回:假如失败,返回 -1,成功返回 删除了多少行。

十、更新记录(修改记录)

  • 普通更新
返回= SQLiteBox1.Update(表名, 条件,更新列表)

表名: 参考查询
条件: 参考查询
更新列表: 参考新增中的 字段赋值列表
返回: 假如失败,返回 -1,成功返回 更新了多少行。

  • 二进制数据更新
SQLiteBox1.UpdateByte(表名, 条件,字段名,数据指针,数据长度)

二进制数据一次只能更新一个,假如你有多个字段,就需要多次执行这个代码。
假如新增记录时,有二进制数据字段,那些,先新增,取的 ID字段值,然后再执行更新操作来写入数据。

十一、内存数据库

将数据库全部加载到内存中使用,加快数据库速度

SQLiteBox1.MemOpen(数据库文件,密码,同步)

允许同步后,关闭数据库后会自动更新到文件中,不同步的话,需要自己执行以下代码

SQLiteBox1.MemSave

数据库文件为空,那么创建一个无文件的空的内存数据库

十二、事务(大量数据操作)

当你有大量的新增或更新操作,你会发现执行速度非常慢,为了解决这个问题,就有了事务操作,看操作的数量,速度可能要快几十倍,几百倍的速度。

   SQLiteBox1.TransactionBegin()
   ........大量更新和新增操作
   SQLiteBox1.TransactionEnd()

十三、直接执行SQL

SQLiteBox1.SqlFind (sql命令,返回())

假如命令中有返回,比如查询,就有返回内容,假如命令中无返回,比如更新,这个返回就无效。
注意: SQL命令是 UTF8 编码的字符,返回的也是UTF8

十四、流式查询数据库(只支持库,不支持控件)

用于大数据查询,不经过数组转换,不占用内存,高效率
上面普通的查询,一般查询几十条,上百条记录,要是遇到 几千,上万,几十万,那么普通查记录就效率低,占用内存大。那么就需要用到这个查询

相关成员
Declare Function StreamFind(表名 As Wstring, 条件 As Wstring, 字段名列表 As Wstring = "*", 排序方式 As Wstring = "", 第几页 As Long = 1, 每页行数 As Long = 0) As sqlite3_stmt Ptr '流式查询数据库 (大数据查询),成功返回stmt指针,失败返回0,stmt指针可以用来直接用 sqlite3的API写代码,会效率更高。
   Declare Function StreamFindUtf(表名 As String, 条件 As String, 字段名列表 As String = "*", 排序方式 As String = "", 第几页 As Long = 1, 每页行数 As Long = 0) As sqlite3_stmt Ptr '流式查询数据库 (大数据查询),成功返回stmt指针,失败返回0,stmt指针可以用来直接用 sqlite3的API写代码,会效率更高。
   Declare Function StreamColCount() As Long '字段列数 读取查询到字段的数量
   Declare Function StreamColName(colIdx As Long) As String '字段名 读取colIdx字段的字段名,是UTF8编码(colIdx从0开始)
   Declare Function StreamColType(colIdx As Long) As Long '字段类型 读取colIdx字段的类型编号(colIdx从0开始)注意:必须在 StreamNext 执行后才可以获取 {=.SQLITE_INTEGER 整数.SQLITE_FLOAT 浮点数.SQLITE_TEXT 文本.SQLITE_BLOB 二进制.SQLITE_NULL 空值}
   Declare Function StreamNext() As Boolean  '查询下一个 返回False没有记录了,用 While db.StreamNext() 来循环读取即可,注意:当返回False,会自动释放了 StreamFind 返回的 流指针,你获得的指针就无效了,不要再使用,否则可能发生崩溃
   Declare Function StreamColIsNull(colIdx As Long) As Boolean '判断是否空值 如果这个字段为空,返回True (colIdx从0开始)
   Declare Function StreamColInt32(colIdx As Long) As Long '读取32位数值 读取colIdx字段的32位值(colIdx从0开始)
   Declare Function StreamColInt64(colIdx As Long) As LongInt '读取64位数值 读取colIdx字段的64位值(colIdx从0开始)
   Declare Function StreamColDouble(colIdx As Long) As Double '读取浮点数值 读取colIdx字段的浮点数(colIdx从0开始)
   Declare Function StreamColStr(colIdx As Long) As String '读取文本 读取colIdx字段的文本,是UTF8编码(colIdx从0开始)
   Declare Function StreamColBlob(colIdx As Long) As String '读取二进制数据 读取colIdx字段的二进制Blob数据,返回的字符串是二进制数据,不是文本字符串(colIdx从0开始)

具体使用例题

   Dim dp As SQLiteDB
   dp.Open(App.Path & "蒸馏20步-30分.nyk")   '打开数据文件
   dp.TransactionBegin      '启用事务操作(可以理解为开启大量数据读写操作,主要是写操作,不开启会非常慢)
   Print dp.CountUtf("bhobk")  '打印数据库这个表有多少行数据
   dp.StreamFindUtf("bhobk", "")  '使用流查询
   Dim by As String, i As Long, jj1 As Long,jj2 As Long , tt As ULong = GetTickCount
   While dp.StreamNext()   '读取流查询
      by = dp.StreamColBlob(2) '获取字段索引2的内容,索引从0开始
      '以下是业务处理代码,只是例题
      For i = 5 To Len(by) Step 4
         If Mid(by, 1, 2) = Mid(by, i, 2) Then
            by = Left(by, i -1)
            dp.UpdateByteUtf("bhobk", "id=" & dp.StreamColInt32(0), "move", StrPtr(by), Len(by))  '更新数据
            jj2+=1
            Exit For
         End If
      Next
      jj1+=1
      If GetTickCount - tt > 300 Then '每300毫秒输出,假如数据很多,要处理很久,需要定时输出,表示还在工作,不是死机
         tt = GetTickCount
         Print jj1,jj2
      End If
   Wend
   dp.TransactionEnd  '结束事务
   dp.Vacuum      '整理数据库,去除未使用数据,减少数据库文件大小
   Print "全部完成",jj1,jj2

使用 StreamFindUtf 查询,然后循环使用 StreamNext ,StreamCol** 读取各字段内容。

其它更多功能

除了以上基本功能,本控件还封装了好多实用功能,需要自己来测试研究,这里就不再把所有的功能都介绍一遍,因为都带有简单是中文说明,很容易明白
功能:创建表、新增字段、创建索引、读取\保存配置、求和,整理数据库 等等

评论一下?

OωO
取消