sqlite 日期加减(11.Lazarus数据库编程8.ZeosDBO与SQLite3综合示例)
sqlite 日期加减(11.Lazarus数据库编程8.ZeosDBO与SQLite3综合示例)数据模块组件如下图所示:表单窗体界面设计:以上 SQL 语句可以使用 DBeaver 等数据库管理工具连接到 SQLite3 数据库上执行。需求描述:通过主界面展现表中的数据,可以实现新增、修改和删除,新增和修改数据时,部门数据作为选项,在表单界面中可以选择,学历也可以进行选择,不过,选项数据是固定的。主窗体界面设计:
8.ZeosDBO与SQLite3综合示例本节将使用 ZeosDBO 与 SQLite3 数据完成一个数据库表 CRUD 的示例,数据表结构及数据如下:
create table c_dep (
dep_id varchar(64) primary key
dep_name varchar(16)
);
insert into c_dep (dep_id dep_name)
values ('yfb' '研发部');
insert into c_dep (dep_id dep_name)
values ('xsb' '销售部');
insert into c_dep (dep_id dep_name)
values ('jszcb' '技术支持部');
insert into c_dep (dep_id dep_name)
values ('cwb' '财务部');
insert into c_dep (dep_id dep_name)
values ('xzb' '行政部');
create table d_dep_staff (
staff_id varchar(64) primary key
dep_id varchar(64)
name varchar(32)
sex varchar(8)
birthday date
edu_level varchar(16)
school varchar(64)
speciality varchar(32)
native_place varchar(256)
);
INSERT INTO d_dep_staff
(staff_id dep_id name sex birthday edu_level school speciality native_place)
VALUES(hex(randomblob(16)) 'yfb' '张三' '女' '1981-9-10' '本科' '内蒙古大学' '经济管理' '内蒙古乌兰察布市集宁区');
INSERT INTO d_dep_staff
(staff_id dep_id name sex birthday edu_level school speciality native_place)
VALUES(hex(randomblob(16)) 'xsb' '刘五' '男' '1978-7-11' '本科' '内蒙古大学' '计算机科学与技术' '内蒙古鄂尔多斯市东胜区');
INSERT INTO d_dep_staff
(staff_id dep_id name sex birthday edu_level school speciality native_place)
VALUES(hex(randomblob(16)) 'xzb' '弓九' '女' '1983-3-10' '本科' '内蒙古科技大学' '计算机科学与技术' '内蒙古呼和浩特市托克托县');
在上面的数据表设计中,表的主键采用了字符串类型,一般情况下,我会考虑使用 UUID 来填充。UUID(Universal Unique Identifier)或者 GUID(Globally Unique Identifier)是一个 128 比特的数字,可以用于唯一标识每个网络对象或资源。由于它的生成机制,一个 UUID 可以保证几乎不会与其他 UUID 重复,因此常常用于生成数据库中的主键值。
SQLite 提供了一个 randomblob(N) 函数,可以用于返回一个 N 字节的伪随机字节 BLOB。利用该函数和 hex() 函数可以返回 GUID:
SELECT hex(randomblob(16)) AS guid;
guid |
--------------------------------|
BEA6B419172B9FAECE45883D13935690|
在上面数据表 d_dep_staff 的 Insert 语句中使用了该方法生成 UUID。
以上 SQL 语句可以使用 DBeaver 等数据库管理工具连接到 SQLite3 数据库上执行。
8.1 需求描述及界面设计需求描述:通过主界面展现表中的数据,可以实现新增、修改和删除,新增和修改数据时,部门数据作为选项,在表单界面中可以选择,学历也可以进行选择,不过,选项数据是固定的。
主窗体界面设计:
表单窗体界面设计:
数据模块组件如下图所示:
组件属性:
组件 |
属性 |
值 |
ZConnection1 |
Protocol |
SQLite-3 |
Database |
E:\workspace_of_lazarus\demodb.db | |
Connected |
True | |
ZReadOnlyQuery1 |
Connection |
ZConnection1 |
SQL |
SELECT staff_id s.dep_id name sex birthday edu_level school speciality native_place d.dep_name FROM d_dep_staff s left join c_dep d on s.dep_id = d.dep_id | |
Active |
True |
数据组件声明代码:
TDataModule1 = class(TDataModule)
ZConnection1: TZConnection;
ZReadOnlyQuery1: TZReadOnlyQuery;
// 字段
ZReadOnlyQuery1_birthday: TDateField;
ZReadOnlyQuery1_dep_id: TStringField;
ZReadOnlyQuery1_dep_name: TStringField;
ZReadOnlyQuery1_edu_level: TStringField;
ZReadOnlyQuery1_name: TStringField;
ZReadOnlyQuery1_native_place: TStringField;
ZReadOnlyQuery1_school: TStringField;
ZReadOnlyQuery1_sex: TStringField;
ZReadOnlyQuery1_speciality: TStringField;
ZReadOnlyQuery1_staff_id: TStringField;
private
public
end;
8.2.2 主窗体
主窗体组件如下图所示:
组件属性:
组件 |
属性 |
值 |
DataSource1 |
DataSet |
DataModule1.ZReadOnlyQuery1 |
DBNavigator1 |
DataSource |
DataSource1 |
VisibleButtons |
[nbFirst nbPrior nbNext nbLast] | |
Align |
alRight | |
DBGrid1 |
DataSource |
DataSource1 |
Options |
dgRowSelect=True | |
Align |
alClient |
主窗体声明代码:
TForm1 = class(TForm)
// 按钮
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
// 数据库组件
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
// 容器 - 放置按钮和数据导航组件
Panel1: TPanel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure DBGrid1DblClick(Sender: TObject);
private
public
end;
8.2.3 表单窗体
表单窗体如下图所示:
表单窗体的声明代码:
TForm2 = class(TForm)
Button1: TButton;
Button2: TButton;
// 数据编辑控件
DepComboBox: TComboBox;
GroupBox7: TGroupBox;
NativePlaceEdit: TEdit;
SpecialityEdit: TEdit;
SchoolEdit: TEdit;
EduLevelComboBox: TComboBox;
NameEdit: TEdit;
SexRadioGroup: TRadioGroup;
BirthdayDateTimePicker: TDateTimePicker;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
GroupBox3: TGroupBox;
GroupBox4: TGroupBox;
GroupBox5: TGroupBox;
GroupBox6: TGroupBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormActivate(Sender: TObject);
private
public
isNew: Boolean;
end;
8.3 功能实现代码8.3.1 主窗体功能代码
各部分功能代码与上一节《【11.Lazarus数据库编程】7.ZeosDBO Database CRUD》内容基本相同,在这里就不赘述了,有兴趣的读者可以阅读一下上一节内容。
procedure TForm1.Button1Click(Sender: TObject);
begin
// 新建
Form2.isNew := True;
if Form2.ShowModal = mrOk then
begin
DataModule1.ZReadOnlyQuery1.Refresh;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// 编辑
if DataModule1.ZReadOnlyQuery1.BOF then
if DataModule1.ZReadOnlyQuery1.RecordCount > 0 then
DataModule1.ZReadOnlyQuery1.First
else
Exit;
if DataModule1.ZReadOnlyQuery1.EOF then
if DataModule1.ZReadOnlyQuery1.RecordCount > 0 then
DataModule1.ZReadOnlyQuery1.Last
else
Exit;
Form2.isNew := False;
if Form2.ShowModal = mrOk then
begin
DataModule1.ZReadOnlyQuery1.Refresh;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
Query: TZQuery;
begin
// 删除
if DataModule1.ZReadOnlyQuery1.BOF then
if DataModule1.ZReadOnlyQuery1.RecordCount > 0 then
DataModule1.ZReadOnlyQuery1.First
else
Exit;
if DataModule1.ZReadOnlyQuery1.EOF then
if DataModule1.ZReadOnlyQuery1.RecordCount > 0 then
DataModule1.ZReadOnlyQuery1.Last
else
Exit;
Query := TZQuery.Create(Self);
try
Query.Connection := DataModule1.ZConnection1;
Query.Close;
Query.SQL.Text := 'DELETE FROM d_dep_staff where staff_id = :staffId';
Query.Params.ParamByName('staffId').AsString := DataModule1.ZReadOnlyQuery1_staff_id.Value;
Query.ExecSQL;
except
on D: EDatabaseError do
MessageDlg('Error' 'A database error has occurred. Technical error message: ' D.Message mtError [mbOK] 0);
end;
Query.Destroy;
DataModule1.ZReadOnlyQuery1.Refresh;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
// 刷新
DataModule1.ZReadOnlyQuery1.Refresh;
end;
procedure TForm1.DBGrid1DblClick(Sender: TObject);
begin
Button2Click(Sender);
end;
8.3.2 表单窗体功能代码
各部分功能代码与上一节《【11.Lazarus数据库编程】7.ZeosDBO Database CRUD》内容基本相同,在这里就不赘述了,有兴趣的读者可以阅读一下上一节内容。
procedure TForm2.Button1Click(Sender: TObject);
begin
// 取消
ModalResult := mrCancel;
end;
procedure TForm2.Button2Click(Sender: TObject);
var
Query: TZQuery;
index: Integer;
depId: String;
begin
// 确定
if NameEdit.Text = '' then
begin
MessageDlg('提示' '请输入姓名!' mtError [mbOK] 0);
Exit;
end;
if DepComboBox.ItemIndex < 0 then
begin
MessageDlg('提示' '请选择所在部门!' mtError [mbOK] 0);
Exit;
end;
index := DepComboBox.ItemIndex;
depId := PAnsiString(DepComboBox.Items.Objects[index])^;
Query := TZQuery.Create(Self);
try
Query.Connection := DataModule1.ZConnection1;
Query.Close;
if isNew then
begin
Query.SQL.Text := 'INSERT INTO d_dep_staff (staff_id dep_id name sex birthday edu_level school speciality native_place) VALUES(hex(randomblob(16)) :depId :name :sex :birthday :eduLevel :school :speciality :nativePlace)';
Query.Params.ParamByName('depId').AsString := depId;
Query.Params.ParamByName('name').AsString := NameEdit.Text;
if SexRadioGroup.ItemIndex = 0 then
Query.Params.ParamByName('sex').AsString := '男'
else
Query.Params.ParamByName('sex').AsString := '女';
Query.Params.ParamByName('birthday').AsDate := BirthdayDateTimePicker.Date;
Query.Params.ParamByName('eduLevel').AsString := EduLevelComboBox.Text;
Query.Params.ParamByName('school').AsString := SchoolEdit.Text;
Query.Params.ParamByName('speciality').AsString := SpecialityEdit.Text;
Query.Params.ParamByName('nativePlace').AsString := NativePlaceEdit.Text;
Query.ExecSQL;
end
else
begin
Query.SQL.Text := 'UPDATE d_dep_staff SET dep_id=:depId name=:name sex=:sex birthday=:birthday edu_level=:eduLevel school=:school speciality=:speciality native_place=:nativePlace WHERE staff_id=:staffId';
Query.Params.ParamByName('depId').AsString := depId;
Query.Params.ParamByName('name').AsString := NameEdit.Text;
if SexRadioGroup.ItemIndex = 0 then
Query.Params.ParamByName('sex').AsString := '男'
else
Query.Params.ParamByName('sex').AsString := '女';
Query.Params.ParamByName('birthday').AsDate := BirthdayDateTimePicker.Date;
Query.Params.ParamByName('eduLevel').AsString := EduLevelComboBox.Text;
Query.Params.ParamByName('school').AsString := SchoolEdit.Text;
Query.Params.ParamByName('speciality').AsString := SpecialityEdit.Text;
Query.Params.ParamByName('nativePlace').AsString := NativePlaceEdit.Text;
Query.Params.ParamByName('staffId').AsString := DataModule1.ZReadOnlyQuery1_staff_id.Value;
Query.ExecSQL;
end;
except
on D: EDatabaseError do
MessageDlg('Error' 'A database error has occurred. Technical error message: ' D.Message mtError [mbOK] 0);
end;
Query.Destroy;
ModalResult := mrOk;
end;
procedure TForm2.FormActivate(Sender: TObject);
var
Query: TZQuery;
index: Integer;
begin
// 初始化部门选项
try
Query := TZQuery.Create(Self);
Query.Connection := DataModule1.ZConnection1;
Query.Close;
Query.SQL.Text := 'SELECT dep_id dep_name FROM c_dep';
Query.Open;
DepComboBox.Items.Clear;
while not Query.EOF do
begin
DepComboBox.Items.AddObject(
Query.FieldByName('dep_name').AsString
TObject(NewStr(Query.FieldByName('dep_id').AsString))
);
Query.Next;
end;
except
on D: EDatabaseError do
MessageDlg('Error' 'A database error has occurred. Technical error message: ' D.Message mtError [mbOK] 0);
end;
// 初始化数据项
if isNew then
begin
NameEdit.Text:='';
SexRadioGroup.ItemIndex:=0;
SchoolEdit.Text:='';
SpecialityEdit.Text:='';
NativePlaceEdit.Text:='';
end
else
with DataModule1 do
begin
NameEdit.Text:=ZReadOnlyQuery1_name.Value;
if ZReadOnlyQuery1_sex.Value = '男' then
SexRadioGroup.ItemIndex:=0
else
SexRadioGroup.ItemIndex:=1;
index := DepComboBox.Items.IndexOf(ZReadOnlyQuery1_dep_name.Value);
DepComboBox.ItemIndex:=index;
BirthdayDateTimePicker.Date := ZReadOnlyQuery1_birthday.Value;
EduLevelComboBox.Text := ZReadOnlyQuery1_edu_level.Value;
SchoolEdit.Text := ZReadOnlyQuery1_school.Value;
SpecialityEdit.Text:=ZReadOnlyQuery1_speciality.Value;
NativePlaceEdit.Text:= ZReadOnlyQuery1_native_place.Value;
end;
end;