目录
数据库
简介
1、分类: 大型 中型 小型
2、名词:
3、嵌入式数据库:
4、sqlite3的安装: LTS long term support
5.1、sqlite3的使用:
0、启动sqlite3
1、系统维护命令:===> .help
5.2、标准SQL语句:===》通用语法在其他平台可以直接使用。struct query language;
创建一个表:create table 表名(表字段1,表字段2,...);
删除一个表:drop table 表名;
向表中增加数据:
查询表中的数据:
修改表中数据:
删除表中数据:
插入时间列 int int;
自动增长列
维护命令:
1、数据的导出:
2、数据的导入:
3、可视化工具安装:
sqlite3 数据库编程接口:
int sqlite3_open(const char *filename, sqlite3 **ppDb);
参数说明
返回值
int sqlite3_exec(sqlite3 *db, const char ***sql, int (*****callback)(void*****,int,char**,char**), void *arg, char **errmsg);
参数说明
返回值
注意事项
回调函数
参数说明
回调函数返回值
void sqlite3_free(void *ptr);
参数说明
主要用途
int sqlite3_close(sqlite3 *db);
参数说明
返回值
主要用途
eg:使用数据库接口函数查询表中数据
Hw查字典
插入提速
打开事务的实例程序
数据库
简介
SQL struct query language 关系型数据库 非关系 芒果db
ddl data defination language 建表
dml 新增 修改 删除一行 data modifty
dql 查询 data query language 查询 select
1,新增
2.修改
3.删除一行
4,查询
数据库 sun solaris gnu
-
数据库:这是一个用于存储和管理数据的系统,可以帮助用户高效地存取、更新和管理数据。常见的数据库管理系统包括MySQL、PostgreSQL、Oracle等。
-
sun:这是指“Sun Microsystems”,一家知名的计算机公司,曾经开发了著名的数据库系统“Sun Microsystems's Solaris”。Sun Microsystems后来被Oracle公司收购了。
-
Solaris:这是Sun Microsystems开发的一个UNIX操作系统,广泛应用于企业级服务器和工作站上。Solaris操作系统以其高性能和稳定性著称。
-
GNU:GNU是一个自由软件操作系统的项目,由Richard Stallman发起,旨在创建一个完全自由的操作系统。GNU通常与Linux操作系统一起使用,形成了一个完整的开源操作系统环境(通常被称为GNU/Linux)。
1、分类: 大型 中型 小型
ORACLE MYSQL/MSSQL SQLITE DBII powdb
关系型数据库
2、名词:
DB 数据库 select update database
DBMS 数据库管理系统
MIS 管理信息系统
OA 办公自动化
3、嵌入式数据库:
sqlite3 www.sqlite.org www.kernal.org
GNU 特点:
1、开源 C语言开发
2、代码量少 1万行左右,总大小10M以内
3、绿色软件无需安装
4、文件型数据库,可以移动。
5、数据容量最大 2T
4、sqlite3的安装: LTS long term support
查看sqlite3有没有安装
whereis sqlite3
sqlite3://表示没有安装
1、在线安装 :
sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev//库,对应c语言库
使用c语言操作数据库,编译的时候要链接数据库gcc test.c -lsqlite3 -lpthread
2、验证是否安装成功:
sqlite3 --version
sqlite3 --help
5.1、sqlite3的使用:
0、启动sqlite3
sqlite3 xxx.db ===>用sqlite3 来打开一个名称为test.db的本地数据库。
创建一个数据库:
1、touch xxx.db
2、sqlite3 xxx.db
出现如下提示符:表明数据库管理系统启动。
sqlite>
退出数据库:
.q 命令
注意:如果一直出现如下符号:
...> 则写';'结束。
以下所有命令必须在 sqlite> 后执行。
1、系统维护命令:===> .help
出现所有相关的系统维护命令,都是以 "."开头。
.database 列出当前库和系统中那个文件在关联
.tables 列出当期数据库中的所有表
.schema xxx 列出当前指定的xxx表结构
.dump user ===>导出数据库
.headers on/off 显示表头
重定向(数据库的导入与导出)
sqlite3 test.db .dump > 123.sql
sqlite3 xxx.db < test.sql ===>导入数据库
5.2、标准SQL语句:===》通用语法在其他平台可以直接使用。struct query language;
注意:所有的sql语句都以';'结尾。
创建一个表:ddl
创建一个表:create table 表名(表字段1,表字段2,...);
eg: create table user(id,name,age); char
注意:以上表的表字段,支持如下数据类型。int text real(float) blob(二进制数据)
默认是text类型。
create table 表名 (表字段 类型,表字段 类型,。。。。);
eg:
create table user(id int ,name char,age int);
删除一个表:drop table 表名;
eg:drop table user;
数据库常规操作: 增加 删除 修改 查询
向表中增加数据:
insert into 表名 (字段名称 ) values (值名称);
eg:
insert into user (id,age) values (1,10);
insert into user values(3,"wang",11);
insert into user (age) values ( 12);
查询表中的数据:
select 列名 from 表名 条件;
eg:select * from user ;//查询表中的所有数据
select id from user;//查询表中的id
select*from user where name like "zhangsan%";
select id,name from user where not age <30//查询表中年龄不小于三十岁的,显示id和name
where name like '三一%'
% _ 通配符(%表示在该字符之后匹配任意多个字符,_表示在该字符之后匹配一个字符)
select *from user where age>20 or age<50 order by age desc limit 2 ;(limit 2表示只显示前两个)
且:and(&&) 或:or(||) 非:not
修改表中数据:
update 表名 set 表字段 = 值 满足条件:
eg: update user set id = 1 where name = 'li';
update user set id = 1 where name = "li" and passwd = "123";
update user set id = 2 where name = "li" or name = "zhao";
删除表中数据:
delete from 表名 满足条件:
eg:delete from user ; ///删除表中所有数据
delete from user where id = 1; ///删除id=1 的数据;
delete from user where id =1 and name = "zhang";
delete from user where id = 1 or id = 2;
>2022-1-1 and <2018-12-31
练习:
新建一个mydb.db数据库,并在库中新建一个student表
至少不能少3个字段,依次录入5条记录删除其中第一条和
倒数第二条记录。
插入时间列 int int;
CREATE TABLE user1(id int,name char,age int,dt datetime);
'2022-07-01 19:00:00'
insert into user1 values (2,'张三',23,datetime('now','+8 hours'));(因为使用的是欧洲时间,所以要+八个小时)
自动增长列
sqlite> CREATE TABLE user3(id INTEGER PRIMARY KEY ASC,name char,age int,dt datetime); 主键
sqlite> insert into user3 (NULL,'李四',23,datetime('now'));(直接输入NULL,id会自动增长)
where (group by having) order by [desc] limit;
select * from user where id<10 order by id limit 2;(limit 2表示只显示前两个)
维护命令:
1、数据的导出:
sqlite3 xxx.db .dump > xxx.sql(‘>’输出重定向)
//将数据库名称为xxx的数据库整体导出到脚本中。
xxx.db无法用vim打开,二进制文件,打开是一堆乱码
xxx.sql导出好的文件,可以用vim打开
数据导出命令在外部命令行使用
2、数据的导入:
sqlite3 xxx.db < xxx.sql
3、可视化工具安装:
sudo apt-get install sqlitebrowser
sqlitebrowser xxx.db
sqlite3 数据库编程接口:
自动对齐 ctrl+a ctrl+l
int sqlite3_open(const char *filename, sqlite3 **ppDb);
参数说明
-
filename
: 这是一个指向字符串的指针,表示要打开或创建的数据库文件的路径。可以是相对路径或绝对路径。如果传递的文件名是NULL
,函数将尝试打开一个内存数据库。 -
ppDb
: 这是一个指向sqlite3*
类型的指针的指针,用于接收数据库连接对象。如果成功打开或创建了数据库,*ppDb
将指向一个有效的sqlite3
对象,该对象代表与数据库的连接。否则,*ppDb
将是NULL
。
返回值
sqlite3_open
返回一个整数值,表示函数的执行状态:
-
SQLITE_OK
: 成功打开或创建了数据库文件。 -
SQLITE_ERROR
: 一般错误,如语法错误等。 -
SQLITE_BUSY
: 数据库文件被锁定,通常是由于其他进程正在访问该文件。 -
SQLITE_CANTOPEN
: 无法打开数据库文件,可能是由于文件路径无效或权限问题。 -
SQLITE_NOMEM
: 内存不足。 -
SQLITE_READONLY
: 数据库文件以只读模式打开,不能进行写操作。
int sqlite3_exec(sqlite3 *db, const char ***sql, int (*****callback)(void*****,int,char**,char**), void *arg, char **errmsg);
int sqlite3_exec(sqlite3 *db, const char *sql, int (*callback)(void*,int,char**,char**), void *arg, char **errmsg);
sqlite3_exec
是一个用于执行 SQL 语句的 SQLite API 函数,通常用于执行无需返回结果的 SQL 命令,如创建表、插入数据或删除数据。
参数说明
-
db
: 一个指向sqlite3
对象的指针,该对象表示与数据库的连接。这个连接应该是由sqlite3_open
函数打开的。 -
sql
: 指向一个以 null 结尾的 SQL 语句字符串的指针。这个 SQL 语句可以是单个 SQL 命令,也可以是多个命令,用分号分隔。 -
callback
: 一个指向回调函数的指针,这个函数会在每次查询返回一行数据时被调用。如果 SQL 语句没有结果集或不需要回调,可以将其设为NULL
。 -
arg
: 传递给回调函数的用户数据。这个参数可以是任何类型的指针,回调函数在执行时会接收到这个数据。若没有使用回调函数,可以将此参数设为NULL
。 -
errmsg
: 一个指向字符串的指针的指针。如果 SQL 语句执行失败,该指针将指向一个包含错误信息的字符串。调用者可以用sqlite3_free
释放该字符串。
返回值
sqlite3_exec
返回一个整数值,表示函数的执行状态:
-
SQLITE_OK
: SQL 语句执行成功。 -
SQLITE_ERROR
: 执行 SQL 语句时发生错误。 -
SQLITE_BUSY
: 数据库文件被锁定,通常由于其他进程正在访问。 -
SQLITE_MISUSE
: 函数调用不当或传递了无效的参数。
注意事项
-
回调函数: 如果 SQL 语句返回结果集且提供了回调函数,回调函数会被多次调用,每次传递一行数据。回调函数的任务是处理这些数据。
-
错误处理: 如果
sqlite3_exec
返回非SQLITE_OK
的值,错误信息会通过errmsg
参数返回。一定要检查和处理这些错误,并在适当的时候释放errmsg
指向的内存。 -
多语句执行:
sqlite3_exec
可以执行多个用分号分隔的 SQL 语句,但每个语句的结果都将被处理。如果 SQL 语句之间存在错误,sqlite3_exec
会返回错误代码,并且errmsg
将包含错误信息。
回调函数
int callback(void *data, int argc, char **argv, char **azColName);
int callback(void *data, int argc, char **argv, char **azColName);
参数说明
-
data
: 一个指向用户定义数据的指针。这个指针在调用sqlite3_exec
时传递,并在回调函数中可以用来传递上下文信息或状态。这个参数可以是任何类型的指针,回调函数会在每次调用时接收到这个数据。可以将其设置为NULL
如果没有需要传递的数据。 -
argc
: 查询结果的列数。在每次回调函数被调用时,这个值表示当前行的列数。对于每一行,这个值都是固定的。 -
argv
: 一个指向字符串指针数组的指针。每个argv[i]
指向当前行的第i
列的值。如果某列的值为空,argv[i]
将是NULL
。 -
azColName
: 一个指向字符串指针数组的指针,每个azColName[i]
指向对应列的名称。这个参数可以用来获取列名,从而更好地处理和解释数据。
回调函数返回值
回调函数应返回一个整数值,SQLite 将根据这个值决定是否继续处理查询结果:
-
0
: 继续处理下一行数据。如果返回 0,SQLite 会继续处理当前结果集中的下一行数据。 -
非零值: 停止处理查询结果集。如果回调函数返回一个非零值,
sqlite3_exec
将停止处理结果集,函数将返回到调用位置,并且 SQL 执行会中断。
void sqlite3_free(void *ptr);
参数说明
-
ptr
: 指向需要释放的内存块的指针。这通常是一个由 SQLite 的内存分配函数(如sqlite3_mprintf
)返回的指针。
主要用途
-
释放内存:
sqlite3_free
应用于释放由 SQLite 内部分配的内存。例如,在执行 SQL 语句时,如果使用了sqlite3_mprintf
或类似函数分配了字符串,使用后应调用sqlite3_free
来释放内存。 -
避免内存泄漏: 通过适时释放动态分配的内存,避免了长时间运行的程序中内存泄漏的问题。
int sqlite3_close(sqlite3 *db);
参数说明
-
db
: 指向一个 SQLite 数据库对象的指针。这个对象是通过sqlite3_open
或sqlite3_open_v2
函数创建的。
返回值
-
SQLITE_OK
: 表示成功关闭数据库连接。 -
SQLITE_BUSY
: 表示数据库在关闭时正忙,通常是因为仍有未完成的事务。 -
SQLITE_ERROR
: 表示发生了错误,数据库连接无法正常关闭。
主要用途
-
释放资源: 关闭数据库连接并释放所有与数据库相关的资源(如内存、文件句柄等)。
-
事务管理: 在关闭数据库之前,需要确保所有事务都已提交或回滚。否则,
sqlite3_close
可能返回SQLITE_BUSY
。
eg:使用数据库接口函数查询表中数据
#include <stdio.h>
#include <sqlite3.h>
int show(void*arg,int col,char**result,char**title)
{
static int flag = 0;
int i = 0 ;
if(0 == flag)
{
for(i = 0 ;i<col;i++)
{
printf("%s\t",title[i]);
}
printf("\n");
flag = 1;
}
for(i = 0 ;i<col;i++)
{
printf("%s\t",result[i]);
}
printf("\n");
return 0;
}
int main()
{
sqlite3* db=NULL;
int ret = sqlite3_open("/home/linux/20240812/sec4/aaa.db",&db);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"cant opendb,%s\n",sqlite3_errstr(ret));
sqlite3_close(db);
return 1;
}
char sql_cmd[128]="select * from user;";
char * errmsg=NULL;
ret = sqlite3_exec(db,sql_cmd,show,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
sqlite3_close(db);
printf("Hello World!\n");
return 0;
}
Hw查字典
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
int show(void*arg,int col,char**result,char**title)
{
int *t = (int *)arg;
*t = 1;
static int flag = 0;
int i = 0 ;
if(0 == flag)
{
for(i = 0 ;i<col;i++)
{
printf("%s\t",title[i]);
}
printf("\n");
flag = 1;
}
for(i = 0 ;i<col;i++)
{
printf("%s\t",result[i]);
}
printf("\n");
return 0;
}
int main(void)
{
sqlite3* db=NULL;
int ret = sqlite3_open("/home/linux/sqlite3/0904/03hw/tick.db",&db);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"cant opendb,%s\n",sqlite3_errstr(ret));
sqlite3_close(db);
return 1;
}
/*
FILE *fp = fopen("./dict.txt","r");
if(NULL == fp)
{
perror("fopen");
return 1;
}
while(1)
{
char sql_cmd[1024*4]={0};
char buf[1024] = {0};
char * p = fgets(buf,sizeof(buf),fp);
if(p == NULL)
{
break;
}
char * mean = buf;
mean = mean+17;
char * word = strtok(buf," ");
sprintf(sql_cmd,"insert into user values(NULL,\"%s\",\"%s\");",word,mean);
char * errmsg=NULL;
ret = sqlite3_exec(db,sql_cmd,show,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
}
*/
while(1)
{
char sql_cmd[1024*4]={0};
char buf[128] = {0};
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = '\0';
if(strcmp(buf,"#quit")==0)
{
break;
}
sprintf(sql_cmd,"select * from user where word like '%s';",buf);
char * errmsg=NULL;
int arg = 0;
ret = sqlite3_exec(db,sql_cmd,show,&arg,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
if(arg == 0)
{
printf("not found\n");
}
}
sqlite3_close(db);
return 0;
}
插入提速
1、使用vi打开xxx.sql可以看到BEGIN TRANSACTION;和COMMIT;开启事务和关闭事务;批量将数据插入数据库的时候,没插入一次都会开启一次事务,插入完成在进行关闭,速度会比较慢,可以在批量操作之前先开启事务,数据库就会知道是批量插入。
2、再提速,FRAGMA默认打开(文件同步)
3、再提速,sqlite3_prepare
打开事务的实例程序
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
int main()
{
char * errmsg=NULL;
sqlite3* db=NULL;
int ret = sqlite3_open("/home/linux/20240812/sec4/aaa.db",&db);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"cant opendb,%s\n",sqlite3_errstr(ret));
sqlite3_close(db);
return 1;
}
char sql_cmd[1024]={0};
sprintf(sql_cmd,"create table if not exists dict"
"(x INTEGER PRIMARY KEY ASC,word char,mean text);");
ret = sqlite3_exec(db,sql_cmd,NULL,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error create table,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
bzero(sql_cmd,sizeof(sql_cmd));
sprintf(sql_cmd,"delete from dict");
ret = sqlite3_exec(db,sql_cmd,NULL,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error create table,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
FILE* fp = fopen("/home/linux/dict.txt","r");
if(NULL == fp)
{
perror("fopen");
return 1;
}
// BEGIN TRANSACTION;
bzero(sql_cmd,sizeof(sql_cmd));
sprintf(sql_cmd,"BEGIN TRANSACTION;");
ret = sqlite3_exec(db,sql_cmd,NULL,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error create table,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
while(1)
{
//char sql_cmd[128]="insert into user values(7,'bbb',11);";
char line[512]={0};
if(NULL == fgets(line,sizeof(line),fp))
{
break;
}
char* word = strtok(line," ");
char *mean = strtok(NULL,"\r");
bzero(sql_cmd,sizeof(sql_cmd));
sprintf(sql_cmd,"insert into dict values(NULL,\"%s\",\"%s\");"
,word,mean);
ret = sqlite3_exec(db,sql_cmd,NULL,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
}
bzero(sql_cmd,sizeof(sql_cmd));
sprintf(sql_cmd,"COMMIT;");
ret = sqlite3_exec(db,sql_cmd,NULL,NULL,&errmsg);
if(SQLITE_OK!=ret)
{
fprintf(stderr,"exec error create table,%s\n",errmsg);
sqlite3_free(errmsg);
sqlite3_close(db);
return 1;
}
sqlite3_close(db);
printf("Hello World!\n");
return 0;
}