SQLite3 操作命令以及c/c++编程API和例子

news2024/11/20 10:30:43

文章目录

  • 数据库系统
  • SQLite
    • SQLite数据类型
    • SQLite语句介绍
    • 表的创建和查看
    • 表的删除插入和修改
    • 表数据的删除
    • 复制表和修改表结构
    • 事务处理
    • 函数操作
    • 数据分组group by
    • 约束
    • 联结表
    • 视图view
    • 触发器trigger
    • 日志操作
    • 索引 index
  • SQLite c/c++编程
    • sqlite3_open
    • sqlite3_close
    • sqlite3_exec
    • sqlite3_get_table
    • 实现数据库操作example1.c
    • sqlite3_prepare_v2
    • sqlite3_step
    • sqlite3_colmun_xxx
    • 实现数据库操作example2.c

数据库系统

DBMSdata base management system (数据库管理系统)。数据库管理系统通过数据模型对数据进行存储和管理。数据模型三要素:数据结构、数据操作、完整性约束。数据库管理系统采样的数据模型注意有三种:层次模型、网状模型、关系模型。

  1. 层次模型:

    • 有且仅有一个节点无父结点,这个节点被称为根节点
    • 其他节点有且仅有一个父节点
    • 同一父节点的子节点被称为兄弟节点
    • 没有子节点的节点被称为页节点
  2. 网状模型

    • 允许一个以上的节点无父节点
    • 一个节点可以有多个的父节点
  3. 关系模型

    • 每一列的分量是类型相同的数据

    • 列的顺序可以是任意的

    • 行的顺序可以是任意的

    • 表中的分量是不可再分割的最小数据项,即表中不允许有子表。

    • idnameaddr
      1王五北京
      2张三上海
      3李四珠海

常用的数据库:ORACLE、Mysql、SQL server、Access、Sybase、SQLite。

SQLite

SQite是一个开源的、内嵌式的关系型数据库。下载地址:https://www.sqlite.org/download.html 。学习网站菜鸟教程: https://www.runoob.com/sqlite/sqlite-tutorial.html 。

特点:零配置、灵活、可移植、自由授权、紧凑、可靠、简单、易用。

SQLite数据类型

  • interger:带符号的整型(最大64位)
  • real:8字节表示的浮点类型
  • text:字符类型,支持多种编码(UTF-8、UTF-16等),大小无限制
  • blob:任意数据类型,大小无限制。BLOB(binary large object)二进制大对象,使用二进制保持数据
  • null:null值,表示空

SQLite语句介绍

  • 创建打开数据库:splite3 xxx.dbsqlite3>.open test.db
  • 退出数据库:sqlite3>.quit/sqlite3>.exit
  • 查看数据库列表:splite3>.databases
  • 导出完整的数据库在一个文本文件中: sqlite3 testDB.db .dump > testDB.sql,恢复使用:sqlite3 testDB.db < testDB.sql
  • 所有的SQL语句都是使用分号结尾,不区分大小写,两个减号“--”代表注释。

表的创建和查看

create table 数据库.表名称(列名称1 数据类型,列名称2 数据类型,列名称3 数据类型,....);
.tables -- 查看创建的表名称
-- sqlite> .tables
-- tbl
.schema -- 查看表格的语句
-- sqlite> .schema
-- CREATE TABLE tbl(id interger,name text,addr text);
select * from tbl;  -- 查询表中的内容
-- 在设计表时,通过primary key手动设置主键,每个表只能由一个主键,设置主键的列的数据不能重复。
create table persons(id integer primary key,name text,addr text);

表的删除插入和修改

drop table table_name; -- 删除表
-- alter语句,在已有的表中添加或者删除列以及修改表名
alter table 表名 add 列名 数据类型; -- 添加列
alter table persons add column sex text;
alter table 表名 rename to 新表名 -- 修改表名
-- 插入新行 insert into
insert into 表名 values(列值1,列值2,列值3,.....); -- 当列值位字符串要加上‘’号
insert into table_name (column1, column2, ...) values (value1, value2, ...); -- 插入指定列
insert into tbl(102,'ds','ss');
insert into tbl(id,name,addr) values(103,'io','op');
-- 更新update
update tbl set addr='ji' where id=103;
select * from tbl where id<102;
select * from tbl where id between 102 and 105;

表数据的删除

delete from 表名 [匹配条件];
delete from table_name where id=104;
delete from table_name where id=104 and addr='cq';
select * from table_name where id in (102,103,104);
select * from table_name where addr like 'ps%'; -- ps开头的
-- like通配符百分号(%)代表零个、一个或多个数字或字符。下划线(_)代表一个单一的数字或字符
select * from table_name where addr GLOB 'ps%'; -- ps开头的
-- GLOB星号(*)代表零个、一个或多个数字或字符。问号(?)代表一个单一的数字或字符
select * from table_name where id=104 or addr='cq';
select * from tbl where id between 104 and 109;
select * from tbl where id is not 109; -- 当id!=109时
select * from tbl where id is 109; -- 当id=109时
select * from COMPANY limit 3 offset 2; -- limit限制显示的行数,offset偏移量为多少
select * from COMPANY order by NAME, SALARY desc; -- 安装NAME升序 SALARY降序排列 默认升序
-- asc 默认值,从小到大,升序排列  desc 从大到小,降序排列

复制表和修改表结构

create table tbl2 as select * from tbl; -- 复制一张表
create table tbl3 as select * from tbl where id=103; -- 复制部分
-- 修改表的结构
create table tbl4(id integer primary key,name text,addr text); -- 第一步创建新表
insert into tbl4(id,name,addr) select id,name,addr from tbl; -- 第二步导入数据
drop table tbl;
alter table tbl4 rename to tbl; -- 更该表名

事务处理

begin; -- 开始一个事务
commit; -- 使得begin后的所有命令得到确认
rollback; -- 取消begin后的所有操作
sqlite> BEGIN;
sqlite> DELETE FROM COMPANY WHERE AGE = 25;
sqlite> COMMIT;

函数操作

length() -- 返回字符串的长度
lower() -- 将字符串转换为小写
upper() -- 将字符串转换为大写
select id,upper(name),length(addr) from tbl;
avg() -- 返回某列的平均值
count() -- 返回某列的函数
max() -- 返回某列的最大值
min() -- 返回某列的最小值
sum() -- 求某列的总和
select id,name,addr,max(scores),avg(scores) from tbl;

数据分组group by

select class,count(*) from tbl group by class; -- group分组
-- where语句必须要在group之前
select class,avg(scores) from tbl where class='class_a' group by class;
-- having语句对结果进行过滤,在group后面
select class,avg(scores) from tbl group by class having avg(scores)>=60;
-- order by 对结果进行排序 放在having后面
select class,avg(scores) from tbl group by class 
	having avg(scores)>=60 order by avg(scores) desc; -- 使用平均成绩降序排序

约束

  • NOT NULL 约束:确保某列不能有 NULL 值。
  • DEFAULT 约束:当某列没有指定值时,为该列提供默认值。
  • UNIQUE 约束:确保某列中的所有值是不同的。是唯一的。
  • PRIMARY Key 约束:唯一标识数据库表中的各行/记录。
  • CHECK 约束:CHECK 约束确保某列中的所有值满足一定条件。使得输入的数据是合法的。
create table tbln(
	id integer primary key not null autoincrement, -- 主键 非空 自增长
    name text not null unique, -- 唯一
    age integer not null, -- 非空
    address text,
    salary real default 5000.0 check(salary>0) -- 默认5000.0 检查大于0
);

联结表

联结表就是从多个表中查询数据

select 列名1,列名2,.... from 表1,表2,.... where 判断语句;
select perosns.name, persons.addr, grade.score, grade.years from persons, grade where
	persons.id = grade.id and perosns.name = 'lucy';

视图view

通过相关的名称存储在数据库中的一个 SQLite 语句。

-- 创建视图
create view result as select perosns.name, persons.addr, grade.score, grade.years 
from persons, grade where persons.id = grade.id and perosns.name = 'lucy';
-- 删除视图
drop view result;

触发器trigger

SQLite的触发器是数据库的回调函数,他会在指定的数据库事件发生的时候自动的执行调用。SQLite 的触发器(Trigger)可以指定在特定的数据库表发生 delete、insert或 update 时触发,或在一个或多个指定表的列发生更新时触发。

create trigger trigger_name  [before | after] 
[insert | update| delete] on table_name
begin
 -- 触发器逻辑....
end;

create trigger trigger_name  [before | after] 
update on table_name of column_name -- 发生某个列上面
begin
 -- 触发器逻辑....
end;
-- 创建触发器
create trigger tg_delete after delete on persons 
begin 
	delete from grade where id=old.id; -- 回调函数
end;
-- 查看触发器
select name from sqlite_master where type = 'trigger';
select name from sqlite_master where type = 'trigger' and tbl_name = 'COMPANY';
-- 删除触发器
drop trigger trigger_name;

日志操作

create table log(time text, date text, data text); -- 创建日志表
insert into log values(time('now'),date('now'), '日志信息'); -- 添加信息
-- 创建触发器
create trigger log_trigger after update on persons
begin
	insert into log values(time('now'),date('now'), '执行了update');
end;

索引 index

-- 索引创建建议
-- 在作为主键的列上 在经常需要排列的列上创建索引
-- 在经常使用where子句中的列上面创建索引,加快条件的判断速度
create index index_name on table_name;
create index index_name on table_name(column_name); -- 单列索引
.indices 或者 .indexes -- 查看索引
select * from sqlite_master where type = 'index'; -- 列出数据库的所有索引
drop index 索引名; -- 删除索引
create unique index index_name on table_name (column_name); -- 唯一索引
create index index_name on table_name (column1, column2); -- 组合索引
-- 索引避免使用情况 索引是为了在大数据库中实现收索、查找、条件查找
-- 表的数据量不大,表的大部分操作不是查询,大量出现NULL的不建议使用索引。

SQLite c/c++编程

注意点:sqlite使用了两个动态库 pthread 和 dl。在网站: https://www.sqlite.org/cintro.html 中查看库中的各个函数的具体情况。学习网址:https://www.jb51.net/list/list_215_1.htm 。

在这里插入图片描述

sqlite3_open

int sqlite3_open(  // 打开数据库
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
filename: 数据库文件路径
ppDb: 指向sqlite3的句柄指针
返回值: 0 SQLITE_OK 成功 其他错误码(非零值)失败

sqlite3_close

int sqlite3_close(sqlite3* pdb); // 关闭数据库文件
pdb: 关闭的sqlite数据库
返回值: 0 SQLITE_OK 成功 其他错误码失败

sqlite3_exec

int sqlite3_exec( // 执行SQL操作
  sqlite3* pdb,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *arg,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);
pdb: 数据库句柄
sql: SQL语句
callback: 回调函数,在使用select语句的时候使用,其他忽略
arg: 传递给回调函数的第一个参数
errmsg: 错误信息指针的地址
返回值: 0 SQLITE_OK 成功 其他错误码
// 回调函数 每找到一条记录,自动执行一次回调函数
typedef int (*sqlite3_callback)(void* arg, int f_num, char** f_value, char** f_name); 
arg: 传递给回调函数的参数
f_num: 记录中包含的字段数目
f_value: 包含每个字段值的指针数组
f_name: 包含每个字段名称的指针数组
返回值:0 成功 -1 失败

sqlite3_get_table

// 执行zsql指向的sql语句,将结果集相关数据的地址保存在函数的参数中
int sqlite3_get_table( 
  sqlite3 *db,          /* An open database */
  const char *zSql,     /* SQL to be evaluated */
  char ***pazResult,    /* Results of the query */
  int *pnRow,           /* Number of result rows written here */
  int *pnColumn,        /* Number of result columns written here */
  char **pzErrmsg       /* Error msg written here */
);
db: 数据库的标识
zsql: SQL语句,以分号结尾
pazResult: 指针数组的地址,记录结果集数据。
    内存布局:先依次存放各列的列名,然后是每一行各列的值。
pnRow:行数的指针地址
pnColumn: 列数的指针地址
pzErrmsg: 错误信息指针的地址

void sqlite3_free_table(char **result);
// 释放动态分配的收集结果的sqlite3_get_table参数pazResult

实现数据库操作example1.c

使用上面的函数,实现学生成绩的数据库函数

#include "sqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

/**
 * @details 实现数据库的打开和创建表的功能
 * @param sqlite3_filename 打开的数据库的路径名称
 * @return 返回打开数据库的句柄指针 NULL 失败 非空 成功
*/
sqlite3* sql_open(const char* sqlite3_filename)
{
    sqlite3 *sqlite3_db = NULL;
    int sqlite3_ret = sqlite3_open(sqlite3_filename, &sqlite3_db);
    if(sqlite3_ret != SQLITE_OK)
    {
        perror("sqlite3_open error");
        return NULL;
    }
    printf("sqlite3_open ok!\r\n");
    return sqlite3_db;
}

/**
 * @details 创建一个表
 * @param sqlite3_db 打开的数据库句柄
 * @param tbname 创建的表的名字
 * @return -1失败 0成功
*/
int create_table(sqlite3 *sqlite3_db, const char* tbname)
{
    char *sql = (char*)sqlite3_malloc(100);
    if(sql == NULL)
        return -1;
    memset(sql, '\0', 100); /*初始化申请的内存都为'\0'*/
    sprintf(sql, "create table %s (id int primary key not null,name text,score float);", tbname);

    char *mesg_error = NULL;
    int ret = sqlite3_exec(sqlite3_db, sql, NULL, NULL, &mesg_error);
    if(ret != SQLITE_OK)
    {
        if(strcmp(mesg_error, "table stu already exists") != 0)
        {
            printf("%s\n", mesg_error);
            sqlite3_free(mesg_error);
            sqlite3_free(sql);
            return -1;
        }
    }
    printf("create ok\n");
    if(sql != NULL)
        sqlite3_free(sql);
    sqlite3_free(mesg_error);

    return 0;
}

/**
 * @details 给数据库中插入数据
 * @param sqlite3_db 数据库句柄
 * @param tbname 表名
 * @return 0 成功 -1 失败
*/
int insert_data(sqlite3 *sqlite3_db, const char* tbname)
{
    char *sql = (char*)sqlite3_malloc(100);
    int id;
    char name[10] = {'\0'};
    float score;
    if(sql == NULL)
        return -1;
    memset(sql, '\0', 100); /*初始化申请的内存都为'\0'*/
    printf("请分别输入你的id name score\n");
    scanf("%d%s%f",&id, name, &score);
    sprintf(sql, "insert into %s values(%d,'%s',%.1f);", tbname, id, name, score);
    printf("%s\n",sql);

    char *mesg_error = NULL;
    int ret = sqlite3_exec(sqlite3_db, sql, NULL, NULL, &mesg_error);
    if(ret != SQLITE_OK)
    {
        printf("%s\n", mesg_error);
        sqlite3_free(mesg_error);
        sqlite3_free(sql);
        return -1;
    }
    printf("insert ok\n");
    if(sql != NULL)
        sqlite3_free(sql);
    sqlite3_free(mesg_error);

    return 0;
}

/**
 * @details select查询的回调函数,每查询到一个执行一次回调函数
 * @param data 传递给回调函数的参数
 * @param column_num 列数
 * @param column_value 存放列值的数组
 * @param column_name 存放列名的数组
 * @return 0 成功 其他 失败
*/
int callback(void* data, int column_num, char* column_value[], char* column_name[])
{

    printf("%d, %s, %.1f\n", atoi(column_value[0]), column_value[1], atof(column_value[2]));    
    return 0;
}

/**
 * @details 查询显示表的数据
 * @param sqlite3_db 数据库句柄
 * @param tbname 表的名称
 * @return 0 成功 -1 失败
*/
int select_data(sqlite3 *sqlite3_db, const char* tbname)
{
    char *sql = (char*)sqlite3_malloc(100);
    if(sql == NULL)
        return -1;
    memset(sql, '\0', 100); /*初始化申请的内存都为'\0'*/

    sprintf(sql, "select * from %s;", tbname);
    printf("%s\n",sql);

    char *mesg_error = NULL;
    int ret = sqlite3_exec(sqlite3_db, sql, callback, NULL, &mesg_error);
    if(ret != SQLITE_OK)
    {
        printf("%s\n", mesg_error);
        sqlite3_free(mesg_error);
        sqlite3_free(sql);
        return -1;
    }
    printf("select ok\n");
    if(sql != NULL)
        sqlite3_free(sql);
    sqlite3_free(mesg_error);

    return 0;
}

/**
 * @details 查询显示表的数据
 * @param sqlite3_db 数据库句柄
 * @param tbname 表的名称
 * @return 0 成功 -1 失败
*/
int select_data_by_get_table(sqlite3 *sqlite3_db, const char* tbname)
{
    char *sql = (char*)sqlite3_malloc(100);
    if(sql == NULL)
        return -1;
    memset(sql, '\0', 100); /*初始化申请的内存都为'\0'*/

    sprintf(sql, "select * from %s;", tbname);
    printf("%s\n",sql);

    char *mesg_error = NULL;
    char **dbResult;
    int nRow, nColumn, i, j, index;

    int ret = sqlite3_get_table(sqlite3_db, sql, &dbResult, &nRow, &nColumn, &mesg_error);
    if(ret != SQLITE_OK)
    {
        printf("%s\n", mesg_error);
        sqlite3_free_table( dbResult );
        sqlite3_free(mesg_error);
        sqlite3_free(sql);
        return -1;
    }
    printf("select ok\n");
    printf("nRow = %d, nColumn = %d \n", nRow, nColumn);
    index = nColumn;

    for(i = 0; i < nRow; i++)
    {
        printf("第%d条记录\n", i + 1);
        for(j = 0; j < nColumn; j++)
        {
            printf("字段名:%s 字段值:%s\n", dbResult[j], dbResult[index]);
            ++index;
        }
        printf("\n");
    }

    if(sql != NULL)
        sqlite3_free(sql);
    sqlite3_free(mesg_error);

    return 0;
}

/**
 * @details 更新表的数据,成绩
 * @param sqlite3_db 数据库句柄
 * @param tbname 表的名称
 * @param score 成绩
 * @param name 谁的成绩
 * @return 0 成功 -1 失败
*/
int update_data(sqlite3 *sqlite3_db, const char* tbname, float score, char *name)
{
    char *sql = (char*)sqlite3_malloc(100);
    if(sql == NULL)
        return -1;
    memset(sql, '\0', 100); /*初始化申请的内存都为'\0'*/

    sprintf(sql, "update %s set score = %.1f where name = '%s'", tbname, score, name);
    printf("%s\n",sql);

    char *mesg_error = NULL;
    int ret = sqlite3_exec(sqlite3_db, sql, NULL, NULL, &mesg_error);
    if(ret != SQLITE_OK)
    {
        printf("%s\n", mesg_error);
        sqlite3_free(mesg_error);
        sqlite3_free(sql);
        return -1;
    }
    printf("update ok\n");
    if(sql != NULL)
        sqlite3_free(sql);
    sqlite3_free(mesg_error);

    return 0;
}

/**
 * @details 删除数据
 * @param sqlite3_db 数据库句柄
 * @param tbname 表的名称
 * @param id 删除谁的数据
 * @return 0 成功 -1 失败
*/
int delete_data(sqlite3 *sqlite3_db, const char* tbname, int id)
{
    char *sql = (char*)sqlite3_malloc(100);
    if(sql == NULL)
        return -1;
    memset(sql, '\0', 100); /*初始化申请的内存都为'\0'*/

    sprintf(sql, "delete from %s where id = %d", tbname, id);
    printf("%s\n",sql);

    char *mesg_error = NULL;
    int ret = sqlite3_exec(sqlite3_db, sql, NULL, NULL, &mesg_error);
    if(ret != SQLITE_OK)
    {
        printf("%s\n", mesg_error);
        sqlite3_free(mesg_error);
        sqlite3_free(sql);
        return -1;
    }
    printf("delete ok\n");
    if(sql != NULL)
        sqlite3_free(sql);
    sqlite3_free(mesg_error);

    return 0;
}

void print_menu()
{
    printf("\t\t\t 输入你的操作: \t\t\t\n");
    printf("\t\t\t 1.insert \t\t\t\n");
    printf("\t\t\t 2.delete \t\t\t\n");
    printf("\t\t\t 3.update \t\t\t\n");
    printf("\t\t\t 4.select_by_exec \t\t\t\n");
    printf("\t\t\t 5.select_by_table \t\t\t\n");
    printf("\t\t\t -1.exit \t\t\t\n");
}

int main(int argc, char* argv[])
{

    sqlite3 *db;
    char tbname[20] = "stu";
    char name[10] = {'\0'};
    int id;
    float score;

    db = sql_open("test.db");
    create_table(db, tbname);

    int option;

    while(1)
    {
        print_menu();
        scanf("%d",&option);
        switch(option)
        {
            case -1:
            {
                exit(-1);
                break;
            }
            case 1:
            {
                insert_data(db, tbname);
                break;
            }
            case 2:
            {
                printf("请输入你的id\n");
                scanf("%d", &id);
                delete_data(db, tbname, id);
                break;
            }
            case 3:
            {
                printf("请输入你的姓名以及成绩");
                scanf("%s%f", name, &score);
                update_data(db, tbname, score, name);
                break;
            }
            case 4:
            {
                select_data(db, tbname);
                break;
            }
            case 5:
            {
                select_data_by_get_table(db,tbname);
                break;
            }
            default:
                break;
        }
        sleep(1);
    }

    return 0;
}

sqlite3_prepare_v2

int sqlite3_prepare_v2(
  sqlite3 *db,              // 数据库连接对象
  const char *zSql,         // SQL 查询语句
  int nByte,                // SQL 查询语句的字节数 -1 自动计算
  sqlite3_stmt **ppStmt,    // 编译后的语句对象指针
  const char **pzTail       // 剩余未编译部分的指针 一般填0
);
// 将准备的sql语句解析到ppStmt结构体中去
int sqlite3_finalize(sqlite3_stmt *pStmt);
// 释放已经准备好的sqlite3_stmt sql解析好的结构体数据

sqlite3_prepare_v2(db, “insert into tbl(ID,file_content) values( 10, ?), -1, &stat, 0);
// 上面的?号表示不确定 需要使用sqlite3_bind_xxx类函数来确定,
// 该类型的函数其中的第二个参数就是表示第几个?号
// sqlite3_reset(pStmt) 重新初始化绑定的数据
sqlite3_bind_double(pStmt, 1, 10.9); // 绑定数据10.9

int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
                        void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
// 一般最后一个参数填写 SQLITE_TRANSIENT 自动管理释放内存
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
                         void(*)(void*), unsigned char encoding);
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);

sqlite3_step

int sqlite3_step(sqlite3_stmt* pStmt); // 执行结构体pStmt中解析的sql语句
// 执行完一般需要执行 sqlite3_finalize 释放pStmt内存

sqlite3_colmun_xxx

// 获取sqlite3_stmt的当前结果行中的列的各种结果。
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 获取二进制数据
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
int sqlite3_column_count(sqlite3_stmt*) // 获取列的数量

实现数据库操作example2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"

sqlite3* do_test_open(const char * datebase)
{
    sqlite3* db = NULL;
    int result = sqlite3_open(datebase, &db);
    if(result != SQLITE_OK)
    {
        sqlite3_close(db);
        return NULL;
    }
    return db;
}

int do_test_create(sqlite3* db)
{
    const char* create_table_sql = 
                "create table testtable(int_col int,float_col real,string_col text);";
    sqlite3_stmt* stmt = NULL;
    // int len = strlen(create_table_sql);

    if(sqlite3_prepare_v2(db, create_table_sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }

    if(sqlite3_step(stmt) != SQLITE_DONE)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }
    if(stmt)
        sqlite3_finalize(stmt);
    printf("create\r\n");
    return 0;
}

int do_test_begin(sqlite3* db)
{
    const char* create_table_sql = 
                "begin;";
    sqlite3_stmt* stmt = NULL;
    // int len = strlen(create_table_sql);

    if(sqlite3_prepare_v2(db, create_table_sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }

    if(sqlite3_step(stmt) != SQLITE_DONE)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }
    if(stmt)
        sqlite3_finalize(stmt);
    printf("begin\r\n");
    
    return 0;
}

int do_test_insert(sqlite3* db)
{
    const char* create_table_sql = 
                "insert into testtable values(?,?,?);";
    sqlite3_stmt* stmt = NULL;
    // int len = strlen(create_table_sql);

    if(sqlite3_prepare_v2(db, create_table_sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }

    int insertCount = 10, i = 0;
    const char* strData = "This is a test.";
    printf("start insert \r\n");
    for(i = 0; i < insertCount; i++)
    {
        sqlite3_bind_int(stmt, 1, i);
        sqlite3_bind_double(stmt, 2, i * 1.0);
        sqlite3_bind_text(stmt, 3, strData, strlen(strData), SQLITE_TRANSIENT);
        // printf("%s\n", sqlite3_sql(stmt));

        if(sqlite3_step(stmt) != SQLITE_DONE)
        {
            if(stmt)
                sqlite3_finalize(stmt);
            return -1;
        }
        // printf("%s\n", sqlite3_sql(stmt));

        sqlite3_reset(stmt); // 重新初始化 sqlite3_stmt 对象绑定的变量
        printf("insert ok!\r\n");
    }

    if(stmt)
    sqlite3_finalize(stmt);

    return 0;
}

int do_test_commit(sqlite3* db)
{
    const char* create_table_sql = 
                "commit";
    sqlite3_stmt* stmt = NULL;
    // int len = strlen(create_table_sql);

    if(sqlite3_prepare_v2(db, create_table_sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }

    if(sqlite3_step(stmt) != SQLITE_DONE)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }
    if(stmt)
        sqlite3_finalize(stmt);

    printf("commit\r\n");
    
    return 0;
}

int do_test_select(sqlite3* db)
{
    const char* create_table_sql = 
                "select * from testtable;";
    sqlite3_stmt* stmt = NULL;
    // int len = strlen(create_table_sql);

    if(sqlite3_prepare_v2(db, create_table_sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }

    int fieldCount = sqlite3_column_count(stmt); // 获取列数
    int i = 0;

    while(1)
    {
        int r = sqlite3_step(stmt);
        if(r == SQLITE_ROW) // 执行成功,返回一条结果
        {
            for (i = 0; i < fieldCount; ++i) 
            {
                int vtype = sqlite3_column_type(stmt, i);
                if(vtype == SQLITE_INTEGER)
                {
                    printf("the interger value is %d\n", sqlite3_column_int(stmt, i));
                }
                else if(vtype == SQLITE_FLOAT)
                {
                    printf("the float value is %.2f\n", sqlite3_column_double(stmt, i));
                }else if(vtype == SQLITE_TEXT)
                {
                    printf("the text value is %s\n", sqlite3_column_text(stmt, i));
                }else if(vtype == SQLITE_NULL)
                {
                    printf("the value is null\n");
                }
            }
        }
        else if(r == SQLITE_DONE) // 执行成功,没有返回结果
        {
            printf("Select Finished.\n");
            break;
        }
        else 
        {
            if(stmt)
                sqlite3_finalize(stmt);
            break;
        }
    }

    if(stmt)
        sqlite3_finalize(stmt);
    
    return 0;
}

int do_test_drop(sqlite3* db)
{
    const char* create_table_sql = 
                "drop table testtable;";
    sqlite3_stmt* stmt = NULL;
    // int len = strlen(create_table_sql);

    if(sqlite3_prepare_v2(db, create_table_sql, -1, &stmt, NULL) != SQLITE_OK)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }

    if(sqlite3_step(stmt) != SQLITE_DONE)
    {
        if(stmt)
            sqlite3_finalize(stmt);
        return -1;
    }
    if(stmt)
        sqlite3_finalize(stmt);

    printf("dropped table testtable!!!\r\n");
    
    return 0;
}

int do_test_close(sqlite3* db)
{
    int result = sqlite3_close(db);
    if(result != SQLITE_OK)
    {
        return -1;
    }
    return 0;
}


int main(int argc, char **argv)
{
    sqlite3* db = do_test_open("test.db"); // 打开数据库,无则创建

    do_test_create(db); // 创建表

    do_test_select(db); // 查询表

    /*使用begin commit来实现高效的多条语句的插入,避免多次的写入内存,减少写入的操作*/
    do_test_begin(db); // 开始执行begin

    do_test_insert(db); // 插入表

    do_test_commit(db); // commit

    do_test_select(db); // 查询表

    // do_test_drop(db); // 删除testtable表

    do_test_close(db); // 关闭数据库
    
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1000644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为云云服务器云耀L实例评测 | 华为云耀L实例:中小企业的最佳选择?

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

地震反演基础知识2(代码演示)

文章目录 数据集代码演示1. SEG盐真实数据2. SEG盐速度模型3. SEG盐模拟地震数据4. SEG盐模拟速度模型5. openfwi地震数据6. openfwi速度模型 数据集代码演示 1. SEG盐真实数据 # 绘制SEG盐层数据的地震图像 def pain_seg_seismic_data(para_seismic_data):Plotting seismic …

第69步 时间序列建模实战:ARIMA建模(R)

基于WIN10的64位系统演示 一、写在前面 这一期&#xff0c;我们使用R进行SARIMA模型的构建。 同样&#xff0c;这里使用这个数据&#xff1a; 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Re…

Material Design的基本使用方法、Tollbar、菜单等

一、Toolbar 1、基本用法 <androidx.appcompat.widget.Toolbarandroid:id"id/toolbar"android:layout_width"match_parent"android:layout_height"?attr/actionBarSize"android:background"color/cardview_dark_background"andr…

Linux:keepalived 双热备份(基础备份web)

简介 Keepalived是一个用于Linux环境的路由软件&#xff0c;具有健康检查功能以及可用于实现高可用性(High Availability, HA)的功能。它主要支持两种协议&#xff1a;VRRP (Virtual Router Redundancy Protocol) 和 LVS (Linux Virtual Server)。Keepalived的项目源代码托管在…

一文读懂 QUIC 协议:更快、更稳、更高效的网络通信

作者 | 李龙彦 来源&#xff1a;infoQ 你是否也有这样的困扰&#xff1a;打开 APP 巨耗时、刷剧一直在缓冲、追热搜打不开页面、信号稍微差点就直接加载失败…… 如果有一个协议能让你的上网速度&#xff0c;在不需要任何修改的情况下就能提升 20%&#xff0c;特别是网络差的…

一篇文章讲清楚 Mendix 与 SAP 集成开发流程

一、引言 在今日瞬息万变的商业环境中&#xff0c;大量企业依赖SAP&#xff0c;这款全球领先的企业资源规划&#xff08;ERP&#xff09;系统&#xff0c;来优化其业务流程。想象一下&#xff0c;在一家大型制造公司&#xff0c;SAP系统负责从供应链管理到财务报告的一切重要业…

day44:C++ day4,拷贝赋值、友元、常成员、运算符重载

一、仿照string类&#xff0c;完成myString 类 mystring.h #ifndef MYSTRING_H #define MYSTRING_H#include <iostream> #include <cstring>using namespace std;class myString { private:char *str; //记录c风格的字符串int size; //记录字…

计算一串输出数字的累加和

计算一个文件内数字的累加和 awk {sum$1}END{print sum} 直接抽取数据以后的打印是这样的 cat step-iostat.1125.log |grep sda |cut -c "49-56" |awk {sum$1}END{print sum}

使用Arthas诊断线上问题的常见命令(热更新,监听耗时,方法出入参,jvm信息)

Arthas 启动&#xff08;windows&#xff09; jar包丢到项目任意目录&#xff0c;启动jar&#xff0c;选择java进程&#xff0c;项目上一般选择tomcat对应的pid java -jar arthas-boot.jar * [1]: 35542[2]: 71560 math-game.jar监听方法入参及返回 参数 返回对象 调用深度…

DC/DC开关电源学习笔记(五)开关电源的主要技术指标

(五)开关电源的主要技术指标 1.输入参数2.输出参数3.效率4.电压调整率和负载调整率5.动态特性:负载突变时输出电压的变化6.电源启动时间(Set-Up Time)与保持时间(Hold-Up Time)1.输入参数 输入电压大小,交流还是直流,相数,频率等。 2.输出参数 输出功率,输出电压,输出…

java自定义注解(Annotation)

概念 注解 (Annotation)是以“注解名称”的形式存在于代码中的&#xff0c;相信用过spring的小伙伴们都会使用大量的注解。注解是JDK1.5之后引入的&#xff0c;它可以写在类、方法、属性上面&#xff0c;用于说明或标记某些含义&#xff0c;这些说明或标记可用于生成文档、程序…

golang面试题:reflect(反射包)如何获取字段tag​?为什么json包不能导出私有变量的tag?

问题 json包里使用的时候&#xff0c;会结构体里的字段边上加tag&#xff0c;有没有什么办法可以获取到这个tag的内容呢&#xff1f; 举例 tag信息可以通过反射&#xff08;reflect包&#xff09;内的方法获取&#xff0c;通过一个例子加深理解。 package mainimport (&quo…

DevSecOps 中的漏洞管理(下)

建立漏洞管理程序以支持DevSecOps 在讨论DevSecOps及DevOps模型中包含安全性的重要性时&#xff0c;建立有效的漏洞管理实践是非常重要的。这可以通过将漏洞管理设置为程序来实现。 我们可以开始对IT组织进行漏洞管理评估。人们经常问的问题可能是&#xff0c;既然已经建立了…

第一章 计算机系统概述 四、操作系统的运行机制

注:很多人习惯把Linux、Windows、MacOS的“小黑框”中使用的命令也称为“指令”&#xff0c;其实这是“交互式命令接口”&#xff0c;注意与本节的“指令”区别开。本节中的“指令”指二进制机器指令。 一、CPU的两种状态 状态的切换&#xff1a; 内核态转用户态&#xff0c;是…

【个人博客系统 × Redis】“最后的升级“ · 连接Redis · Redis的基本使用

【JavaEE】进阶 个人博客系统&#xff08;7&#xff09; 文章目录 【JavaEE】进阶 个人博客系统&#xff08;7&#xff09;1. linux安装Redis1.1 通过yum商店下载Redis1.2 启动Redis1.3 操作Redis 2. Redis的基本使用&#xff08;关键字大小写不区分&#xff09;2.1 set2.2 g…

SUMPRODUCT函数

SUMPRODUCT函数返回相应范围或数组的个数之和。 默认操作是乘法&#xff0c;但也可以执行加减除运算。 本示例使用 SUMPRODUCT 返回给定项和大小的总销售额&#xff1a; SUMPRODUCT 匹配项 Y/大小 M 的所有实例并求和&#xff0c;因此对于此示例&#xff0c;21 加 41 等于 62。…

UML-用例图

目录 一、UML 什么是UML&#xff1f; 为什么要用UML&#xff1f; UML图有哪些&#xff1f; 二、用例图 用例图摘要 用例图主要元素 1. 参与者&#xff08;Actor&#xff09; 2. 用例(Use Case) 3. 关系 4. 边界 用例图之间的关系 &#xff08;1&#xff09;参与者…

Figma实用插件速收藏!精选19个干货插件大公开!

Figma 如今有着大量的插件&#xff0c;在 UI/UX 设计领域&#xff0c;很多工作已经不用真的从零开始做了。用好 Figma 插件&#xff0c;往往能让设计工作事半功倍。不过其中的插件素质差别很大&#xff0c;需要仔细筛选。不过如果你选择了对的插件&#xff0c;合理的设置&#…

SpringCloud(17~21章):Alibaba入门简介、Nacos服务注册和配置中心、Sentinel实现熔断与限流、Seata处理分布式事务

17 SpringCloud Alibaba入门简介 17.1 why会出现SpringCloud alibaba Spring Cloud Netflix项目进入维护模式 https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now 说明 Spring Cloud Netflix Projects Entering Maintenance Mode 什么是维护模…