百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

「11.Lazarus数据库编程」5.Lazarus和FireBird embedded

ztj100 2024-11-23 00:03 71 浏览 0 评论

5.Lazarus 和 FireBird embedded

5.1 Firebird embedded

【以下内容翻译自官网】

https://wiki.freepascal.org/Firebird_embedded

什么是 Firebird Embedded

Firebird Embedded 是 Firebird 数据库服务器的特殊版本。它允许您在没有专用数据库服务器的情况下运行程序。相反,您将一个库 (DLL/.so/.dylib) 添加到您的应用程序中并让您的应用程序使用该库访问您的 Firebird .fdb 数据库文件。这类似于 Microsoft Access 和 LibreOffice Base 等程序的工作方式。

优点

  • 在许多架构上运行(Linux、macOS、Windows、FreeBSD、Solaris)
  • 无需单独的服务器设置,降低复杂性
  • 您可以轻松地从嵌入式切换到完整的客户端/服务器 - 无需更改一行代码(连接字符串除外)。与 sqlite 相比,这可能是一个不错的优势。

缺点

  • 仅单用户访问
  • 分发时需要与您的程序一起分发一些库(除非您可以静态链接它们)

安装

在 Windows 上,Firebird 嵌入式和常规 Firebird 客户端库是不同的文件。Firebird Embedded 始终可以用作常规客户端,使其成为您安装中的合理选择。

Windows

下载并解压缩 Firebird 嵌入式套件。确保 .dll 和 .manifest 文件是:

  • 在您的项目目录和可执行输出目录(生成 .exe 的位置)或
  • 在 PATH 中的目录中(不是系统目录)(如果您不想继续复制 dll,则很有用)

请注意,位数必须匹配:如果您为 64 位编译程序,则必须使用 64 位嵌入式版本,如果您正在编写 32 位程序,则必须使用 32。还要确保将 .dlls 和 .manifest 文件放置在您的项目输出(可执行)目录中,并将它们与您的应用程序以及许可证文件一起分发。

作为指示,Firebird 2.5 的最低必要文件是:

fbembed.dll
firebird.msg
ib_util.dll
icudt30.dll
icuin30.dll
icuuc30.dll
IDPLicense.txt
IPLicense.txt
Microsoft.VC80.CRT.manifest
msvcp80.dll
msvcr80.dll

Linux

对于 Debian,可能与 Ubuntu 类似:

获取库文件以及符号链接:例如 /usr/lib/x86_64-linux-gnu/libfbembed.so 链接到 /user/lib/x86_64-linux-gnu/libfbembed.so.bla.xy

aptitude install libfbembed2.5 firebird-dev

至少对于 Firebird 2.5+:不要指定用户名或密码,因为这将强制查找 security.fdb,如果无法访问系统范围的 security.fdb,则可能会失败。请在 Firebird 2.5+ 上指定角色 RDB$ADMIN,因为这应该让您完全控制数据库文件。

将这些文件放在您的项目目录中(要做:测试是否都需要):

firebird/libfbembed.so (or perhaps libfbembed.so.2.5)
firebird.conf
firebird/security.fdb #perhaps not necessary
firebird/intl/fbintl
firebird/udf/fbudf.so

对于 Firebird 3,您将需要:

firebird/libfbclient.so
plugins/libEngine12.so

您需要更改插件目录变量。如果你不能这样做,你需要将 libEngine 放到它的原始目录中。

已经在 firebird.conf 中设置了这个(要做:检查这是否都需要)

RootDirectory=./firebird #replace with your directory
DatabaseAccess = Full #probably useful
ExternalFileAccess = Full #probably useful
UdfAccess = Full #probably useful
#disable
#TempDirectories = /tmp #=> didn't fix /tmp/firebird lock issues
#TempDirectories = ~/tmp #=> didn't fix /tmp/firebird lock issues

应用程序启动前需要设置两个环境变量。假设应用程序安装在 /home/pascaldev/embed 中:

# tell dynamic loader where to find embedded lib:
LD_LIBRARY_PATH=/home/pascaldev/embed/firebird
# tell server where to find files (messages, config etc)
FIREBIRD=. #or use absolute path: /home/pascaldev/embed

如果您遇到错误,例如

EIBDatabaseError/ : DoInternalConnect :
 -Can't access lock files' directory /tmp/firebird

您可能有其他用户拥有的陈旧锁定文件删除 /tmp/firebird 目录有效,但问题是它将在您自己的本地权限下重新创建

连接到 Firebird 服务器

如前所述,嵌入式 Firebird 可以像普通的 Firebird 客户端一样工作。因此,使用嵌入式 Firebird 库而不是客户端/服务器 Firebird 库可以帮助您的应用程序更加灵活。

注意:至少在 Firebird 嵌入式 2.5.3 和 FPC 2.6.4 中存在一个错误,在关闭与远程服务器的连接时会崩溃。此错误已在 FPC 中继中修复。

使用

一旦您在正确的路径中拥有了正确的 Firebird 嵌入式库(见上文),您需要指定您连接到嵌入式而不是客户端服务器环境。将 IBConnection 对象的主机名属性留空。其余属性的工作方式与客户端/服务器版本类似,例如 DatabaseName 是您的 .fdb 文件的完整路径,如果它与 fbembed.dll 位于同一目录中,则只是数据库名称。此外,旧版本的 FPC(FPC 2.6.2+ 当然不需要这个)可能需要您将UseEmbeddedFirebird属性设置为 true。SQLDB 单元中不存在该属性,但您需要将 ibase60dyn 添加到您的 uses 子句中。

创建数据库

使用 Firebird ISQL

您可以使用 Firebird isql 应用程序创建数据库(例如,在常规 Firebird(客户端)包中提供)。在 Windows 上,此可执行文件应与 fbembed.dll 位于同一目录中。注意:isql 需要 fbclient 库,而不是 fbembed;您可以复制并重命名 fbembed,例如 Windows 上的 fbclient.dll,以解决此问题。运行isql,然后执行:

create database 'employee.fdb' user 'SYSDBA' password 'masterkey' page_size 16384 default character set UTF8;
exit;

删除数据库基本上意味着删除文件,但您也可以运行: isql

connect 'employee.fdb' user 'sysdba' password 'masterkey';
drop database;
commit;
exit;

以编程方式创建数据库

您还可以在程序中创建数据库。下面创建测试数据库部分中的程序显示了如何检测丢失的数据库并动态创建它们。在初始化表单(FormShow 事件)时,可以在 Lazarus 应用程序中调用类似的过程。

创建表、视图、触发器等对象...

在 Firebird 和 Firebird 嵌入式中创建对象,与大多数事情一样是相同的。

手动创建数据库

isql

create database 'test.fdb' user 'SYSDBA' password 'masterkey' page_size 16384 default character set UTF8;
exit;

以编程方式创建数据库

您可以以编程方式创建数据库。下面的示例创建了一个本地的嵌入式数据库,但可以轻松地将其更改为远程数据库(调整主机名和必要时的路径):

program firebirdembeddedtest;
{$mode objfpc}{$H+}

uses 
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF} 
  Classes, SysUtils,
  sqldb, IBConnection {for Firebird};

const
  // Name for the database. Be sure to specify the same name in your database.ini
  DatabaseFile = 'test.fdb'; //Sensible name for a test database, right?
var
  Fire: TIBConnection;

begin
  //Connection to Firebird database
  // The next line is needed for quite old FPC versions
  // Newer versions will first look for fbembed.dll in the application directory automatically
  //UseEmbeddedFirebird:=true; // Using embedded (and fbembed.dll) or regular client/server (fbclient.dll), requires ibase60dyn in uses
  Fire:=TIBConnection.Create(nil);
  try
    Fire.HostName := ''; //must be empty for embedded Firebird; must be filled for client/server Firebird
    Fire.DatabaseName := DatabaseFile; //(path and) filename
    // Username and password do not matter for authentication, but you do get authorizations in the database
    // based on the name (and optionally role) you give.
    Fire.Username := 'SYSDBA';
    Fire.Password := 'masterkey'; //default password for SYSDBA
    Fire.Charset := 'UTF8'; //Send and receive string data in UTF8 encoding
    Fire.Dialect := 3; //Nobody uses 1 or 2 anymore.
    Fire.Params.Add('PAGE_SIZE=16384'); //I like a large page size (used when creating a database). Useful for larger indexes=>larger possible column sizes

    // Find out if there is a database in the application directory.
    // If not, create it. Note: this may fail if you don't have enough permissions.

    // If you use client/server, you obviously don't need this part of the code.
    if (FileExists(DatabaseFile)=false) then
    begin
        writeln('File '+DatabaseFile+' does not exist.');
        writeln('Creating a Firebird embedded database...');
        // Create the database as it doesn't exist
        try
          Fire.CreateDB; //Create the database file.
        except
          on E: Exception do
          begin
            writeln('ERROR creating database. Probably problems loading embedded library:');
            writeln('- not all files present');
            writeln('- wrong architecture (e.g. 32 bit instead of 64 bit)');
            writeln('Exception message:');
            writeln(E.ClassName+'/'+E.Message);
          end;
        end;
        Fire.Close;
    end;
  finally
    Fire.Free;
  end; 
end.

5.2 使用 FireBird Embedded 进行数据库开发

1.在 Lazarus 环境下创建一个应用

2.将 FireBird Embedded 数据库解压缩到某个目录,我采用的是:

Firebird-2.5.9.27139-0_x64_embed.zip

解压缩后的文件如下图所示:

3.将如下文件复制到 Lazarus 应用所在目录

fbembed.dll
firebird.msg
ib_util.dll
icudt30.dll
icuin30.dll
icuuc30.dll
IDPLicense.txt
IPLicense.txt
Microsoft.VC80.CRT.manifest
msvcp80.dll
msvcr80.dll

4.将同版本号的 FireBird C/S 版本的 isql.exe 文件复制到Lazarus 应用所在目录,我采用的是:

Firebird-2.5.9.27139-0_x64.zip

5.复制 fbembed.dll 文件并重命名为 fbclient.dll

6.在 cmd 命令提示符下执行:

> cd <Lazarus 应用所在目录>
> isql
Use CONNECT or CREATE DATABASE to specify a database
SQL>

说明 FireBird Embedded 安装成功

7.通过 SQL 命令创建数据库

SQL> create database 'test.fdb' user 'SYSDBA' password 'admin' page_size 16384 default character set UTF8;
SQL>

8.创建数据表

SQL> create table d_students1 (
CON>    student_id varchar(64) primary key,
CON>    name varchar(16),
CON>    sex varchar(8),
CON>    birthday date,
CON>    department_id integer,
CON>    total_score decimal(9,1)
CON> );

9.插入数据

SQL> INSERT INTO d_students1
CON> (student_id, name, sex, birthday, department_id, total_score)
CON> VALUES('x-20210001', 'ZhangSan', 'Man', '2000-05-06', 1, 520);
SQL> INSERT INTO d_students1
CON> (student_id, name, sex, birthday, department_id, total_score)
CON> VALUES('x-20210002', 'LiSi', 'Man', '2000-03-09', 1, 539);
SQL> INSERT INTO d_students1
CON> (student_id, name, sex, birthday, department_id, total_score)
CON> VALUES('x-20210003', 'ZhouWu', 'Woman', '2001-09-10', 2, 528);
SQL> INSERT INTO d_students1
CON> (student_id, name, sex, birthday, department_id, total_score)
CON> VALUES('x-20210004', 'ZhaoLiu', 'Woman', '2000-08-28', 1, 517);
SQL> INSERT INTO d_students1
CON> (student_id, name, sex, birthday, department_id, total_score)
CON> VALUES('x-20210005', 'JiangQi', 'Woman', '2000-07-06', 2, 547);
SQL> INSERT INTO d_students1
CON> (student_id, name, sex, birthday, department_id, total_score)
CON> VALUES('x-20210006', 'HeBa', 'Man', '2000-11-01', 2, 533);

数据中没有使用中文,原因是使用 UTF8 字符集创建数据库,而 Windows 的命令提示符使用默认的字符集 GBK,互相之间不兼容。

5.3 在应用程序中显示数据

应用程序中使用的组件:

  • TIBConnection
  • TSQLTransaction
  • TSQLQuery
  • TDataSource
  • TDBGrid

在窗体上拖放以上组件,如下图所示:

组件属性设置如下:

组件

属性

IBConnection1

DatabaseName

E:\workspace_of_lazarus\laz1104\TEST.FDB


UserName

sysdba


Password

admin


Transaction

SQLTransaction1


Connected

True


KeepConnection

True


LoginPrompt

False

SQLTransaction1

Database

IBConnection1


Active

True

SQLQuery1

Database

IBConnection1


Transaction

SQLTransaction1


SQL

select * from d_students1


Active

True

DataSource1

DataSet

SQLQuery1

DBGrid1

DataSource

DataSource1


Align

alClient


Options

dgRowSelect=True

【备注】

当设置 IBConnection1 的 Connected 属性为 True,可能会出现不能正常连接数据库的情况,原因是没有使用 fbembed.dll 库连接,如果本机上同时安装了 FireBird C/S 版,则可能会使用 C/S 版的类库进行连接,此时关闭 Lazarus,打开命令行工具,执行如下命令:

set PATH=<Lazarus应用程序所在目录>  本例为:E:\workspace_of_lazarus\laz1104
cd <Lazarus安装目录>
lazarus

Lazarus 启动后再去连接数据库,即设置 IBConnection1 的 Connected 属性为 True。

按下 F9,运行程序,效果如下图所示:

相关推荐

sharding-jdbc实现`分库分表`与`读写分离`

一、前言本文将基于以下环境整合...

三分钟了解mysql中主键、外键、非空、唯一、默认约束是什么

在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。...

MySQL8行级锁_mysql如何加行级锁

MySQL8行级锁版本:8.0.34基本概念...

mysql使用小技巧_mysql使用入门

1、MySQL中有许多很实用的函数,好好利用它们可以省去很多时间:group_concat()将取到的值用逗号连接,可以这么用:selectgroup_concat(distinctid)fr...

MySQL/MariaDB中如何支持全部的Unicode?

永远不要在MySQL中使用utf8,并且始终使用utf8mb4。utf8mb4介绍MySQL/MariaDB中,utf8字符集并不是对Unicode的真正实现,即不是真正的UTF-8编码,因...

聊聊 MySQL Server 可执行注释,你懂了吗?

前言MySQLServer当前支持如下3种注释风格:...

MySQL系列-源码编译安装(v5.7.34)

一、系统环境要求...

MySQL的锁就锁住我啦!与腾讯大佬的技术交谈,是我小看它了

对酒当歌,人生几何!朝朝暮暮,唯有己脱。苦苦寻觅找工作之间,殊不知今日之事乃我心之痛,难道是我不配拥有工作嘛。自面试后他所谓的等待都过去一段时日,可惜在下京东上的小金库都要见低啦。每每想到不由心中一...

MySQL字符问题_mysql中字符串的位置

中文写入乱码问题:我输入的中文编码是urf8的,建的库是urf8的,但是插入mysql总是乱码,一堆"???????????????????????"我用的是ibatis,终于找到原因了,我是这么解决...

深圳尚学堂:mysql基本sql语句大全(三)

数据开发-经典1.按姓氏笔画排序:Select*FromTableNameOrderByCustomerNameCollateChinese_PRC_Stroke_ci_as//从少...

MySQL进行行级锁的?一会next-key锁,一会间隙锁,一会记录锁?

大家好,是不是很多人都对MySQL加行级锁的规则搞的迷迷糊糊,一会是next-key锁,一会是间隙锁,一会又是记录锁。坦白说,确实还挺复杂的,但是好在我找点了点规律,也知道如何如何用命令分析加...

一文讲清怎么利用Python Django实现Excel数据表的导入导出功能

摘要:Python作为一门简单易学且功能强大的编程语言,广受程序员、数据分析师和AI工程师的青睐。本文系统讲解了如何使用Python的Django框架结合openpyxl库实现Excel...

用DataX实现两个MySQL实例间的数据同步

DataXDataX使用Java实现。如果可以实现数据库实例之间准实时的...

MySQL数据库知识_mysql数据库基础知识

MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...

如何为MySQL中的JSON字段设置索引

背景MySQL在2015年中发布的5.7.8版本中首次引入了JSON数据类型。自此,它成了一种逃离严格列定义的方式,可以存储各种形状和大小的JSON文档,例如审计日志、配置信息、第三方数据包、用户自定...

取消回复欢迎 发表评论: