嵌入式SqLite

玩转SQLite7:基本语法与数据类型

安装sqlite3

sudo apt install sqlite3

image-20240212214735306

进入cli

sqlite3

image-20240212215121598

退出cli

.quit

image-20240212215234327

数据类型

SQLite支持多种数据类型,这些类型在存储和处理数据时具有不同的特性。以下是SQLite中的主要数据类型:

  1. NULL:

    • 表示缺失值或未知值。
  2. INTEGER:

    • 表示有符号的整数,SQLite根据值的大小自动选择1、2、3、4、6或8字节的存储方式。
  3. REAL:

    • 表示浮点数,存储为8字节的IEEE浮点数。
  4. TEXT:

    • 表示文本字符串,使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储。
  5. BLOB:

    • 表示二进制数据,如图像、音频文件等,完全按照输入的方式存储。
  6. NUMERIC:

    • 这是一个亲和类型,不是实际的存储类型。当文本数据被插入到亲和性为NUMERIC的字段时,SQLite会尝试将其转换为INTEGER或REAL类型的数据。如果转换失败,数据将以TEXT方式存储。
  7. BOOLEAN:

    • SQLite没有专门的布尔数据类型,布尔值通常以整数0(false)和1(true)的形式存储。
  8. DATE AND TIME:

    • SQLite没有专门的日期和时间存储类型,但可以存储为TEXT、REAL或INTEGER值。日期和时间可以以多种格式存储,如"YYYY-MM-DD HH:MM:SS.SSS"(TEXT格式),或者从公元前4714年11月24日格林威治时间正午开始算起的天数(INTEGER格式),或者从1970-01-01 00:00:00 UTC算起的秒数(REAL格式)。

在创建表时,你可以指定列的数据类型,但SQLite的存储类型是动态的,这意味着实际存储的数据类型可能会根据值的类型自动转换。例如,你可以声明一个列的类型为INTEGER,但实际上可以存储TEXT类型的数据,SQLite会根据需要自动转换数据类型。这种动态类型系统提供了灵活性,但也可能导致数据类型的不一致性,因此在设计数据库时应尽量保持数据类型的一致性。

基本命令

创建数据库

创建数据库: 要创建一个新的SQLite数据库文件,你可以使用sqlite3命令后跟数据库文件的名称。如果文件不存在,SQLite会创建一个新的数据库文件;如果文件已存在,SQLite会打开它。

sqlite3 database_name.db

进入数据库

进入数据库一旦你通过上述命令打开了数据库文件,你就已经在数据库环境中了。你可以执行各种SQL命令来操作数据库,如创建表、插入数据等。

如果你想要查看当前打开的数据库,可以使用以下命令:

.database

这将显示当前数据库的文件路径。

创建表

在SQLite中创建表的基本语法如下:

CREATE TABLE table_name (
    column1 datatype constraint,
    column2 datatype constraint,
    column3 datatype constraint,
    ...
);

这里,table_name 是你想要创建的表的名称,column1, column2, column3 等是表中的列名,datatype 是列的数据类型,constraint 是可选的列约束(如 PRIMARY KEY, NOT NULL, UNIQUE 等)。

以下是一个具体的例子,创建一个名为 students 的表,包含 id, name, age, 和 grade 四个列:

CREATE TABLE students (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    age INTEGER,
    grade TEXT
);

在这个例子中:

  • id 是一个整数类型,并且是表的主键(PRIMARY KEY),这意味着每个 id 的值必须是唯一的,且不能为 NULL
  • name 是文本类型(TEXT),并且不能为 NULLNOT NULL)。
  • age 是整数类型(INTEGER),没有额外的约束。
  • grade 是文本类型(TEXT),同样没有额外的约束。

在SQLite命令行界面中,你可以使用以下命令来执行这个创建表的SQL语句:

sqlite3 students.db
CREATE TABLE students (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    age INTEGER,
    grade TEXT
);

这将在名为 students.db 的数据库文件中创建一个名为 students 的表。如果你已经打开了数据库,只需执行 CREATE TABLE 语句即可。

修改数据库

在SQLite中,ALTER TABLE命令主要用于修改表的结构,但SQLite对ALTER TABLE的支持相对有限。SQLite允许你使用ALTER TABLE来重命名表或在现有表中添加新列。以下是ALTER TABLE的基本用法:

  1. 重命名表:
    使用RENAME TO子句来重命名表。例如,如果你想要将名为old_table的表重命名为new_table,你可以执行以下命令:

    ALTER TABLE old_table RENAME TO new_table;
    

    请注意,这个操作不会影响表中的数据,只是改变了表的名称。

  2. 添加新列:
    使用ADD COLUMN子句来在表中添加新列。例如,如果你想要向名为students的表中添加一个名为new_column的列,你可以这样做:

    ALTER TABLE students ADD COLUMN new_column datatype;
    

    这里datatype是你想要为新列指定的数据类型。

SQLite不支持直接删除列或修改列的数据类型。如果你需要进行这些操作,你需要创建一个新的表,将旧表的数据导入新表,然后删除旧表,并将新表重命名为旧表的名称。这个过程可以通过以下步骤实现:

  1. 创建新表,使用你想要的结构(不包括你想要删除的列)。
  2. 将旧表的数据插入到新表中。
  3. 删除旧表。
  4. 将新表重命名为旧表的名称。

例如,如果你想要删除students表中的old_column列,你可以这样做:

-- 创建新表,不包括old_column列
CREATE TABLE new_students AS SELECT * EXCEPT (old_column) FROM students;

-- 删除旧表
DROP TABLE students;

-- 将新表重命名为旧表的名称
ALTER TABLE new_students RENAME TO students;

请注意,这些操作可能会影响数据库的性能,特别是当你处理大量数据时。在进行这些更改之前,建议备份你的数据库。

删除表

在SQLite中删除表的命令是 DROP TABLE。这个命令会移除整个表及其所有数据。以下是基本的语法:

DROP TABLE table_name;

这里,table_name 是你想要删除的表的名称。

在SQLite命令行界面中,你可以使用以下命令来删除一个表:

sqlite3 database_name.db
DROP TABLE table_name;

请确保在执行 DROP TABLE 命令之前,你已经打开了包含该表的数据库文件。这个操作是不可逆的,一旦执行,表及其所有数据都将被永久删除。如果你只是想删除表中的所有数据,但保留表结构,你可以使用 DELETE FROM 语句:

DELETE FROM table_name;

这将删除 table_name 表中的所有记录,但表本身仍然存在。

插入数据

在SQLite中,插入数据到表中通常使用INSERT INTO语句。以下是基本的语法:

INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);

这里,table_name是你要插入数据的表名,column1, column2, column3等是表中的列名,value1, value2, value3等是你想要插入的数据值。

如果你想要插入所有列的数据,并且列的顺序与表中列的顺序相同,你可以省略列名,直接插入值:

INSERT INTO table_name VALUES (value1, value2, value3, ...);

以下是一个具体的例子,假设我们有一个名为students的表,包含id, name, age, 和 grade四个列,我们想要插入一条新的学生记录:

INSERT INTO students (id, name, age, grade)
VALUES (1, 'Alice', 20, 'A');

在这个例子中,我们为students表插入了一条新记录,其中id为1,name为’Alice’,age为20,grade为’A’。

如果你已经打开了SQLite命令行界面,并且连接到了相应的数据库,你可以直接执行这个INSERT语句来插入数据。如果你使用的是图形界面的SQLite管理工具,如DB Browser for SQLite,你可以在工具中找到相应的界面来执行这个操作。

删除数据

delete from students where id=2

image-20240212221351620

修改数据

 update students set name='meow' where id=1;

image-20240212221607817

查看表内容

SELECT * FROM students;

image-20240212220305370

查看表结构

.schema

image-20240212215853194

C语言sqlite编程接口

缺少库文件问题

sqlite_demo.c:3:10: fatal error: sqlite3.h: 没有那个文件或目录
    3 | #include <sqlite3.h>
      |          ^~~~~~~~~~~
compilation terminated.

解决办法:

sudo apt install libsqlite3-dev

image-20240212222854335

编译报错问题

注意编译的时候带上-lsqlite3,不然会报错

gcc -o sqlite_demo sqlite_demo.c -lsqlite3

image-20240212223125484

image-20240212223202279

sqlite3_open()打开数据库函数

sqlite3_open 是 SQLite 库中的一个函数,用于打开或创建一个新的 SQLite 数据库文件。这个函数是 C/C++ 语言中与 SQLite 数据库交互的基础,它允许你建立与数据库的连接,并获取一个数据库句柄(sqlite3 *),后续的数据库操作都将通过这个句柄进行。

函数原型如下:

int sqlite3_open(const char *filename, sqlite3 **ppDb);

参数说明:

  • filename:指向一个以 UTF-8 编码的字符串,表示数据库文件的路径。如果文件不存在,SQLite 会尝试创建它。如果传递 NULL 或者 ':memory:',则会在内存中创建一个临时数据库,这个数据库只存在于当前的进程中。
  • ppDb:这是一个指向 sqlite3 * 类型的指针的指针。函数成功时,这个指针会被设置为指向新创建的数据库句柄。如果函数失败,这个指针将保持为 NULL

返回值:

  • 成功时返回 SQLITE_OK(值为 0)。
  • 失败时返回一个非零的错误码,可以通过 sqlite3_errmsg() 函数获取错误信息。

使用示例:

#include <stdio.h>
#include <sqlite3.h>

int main() {
    sqlite3 *db;
    int rc = sqlite3_open("test.db", &db);

    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    } else {
        printf("Opened database successfully\n");
    }

    // 在这里执行数据库操作...

    sqlite3_close(db);
    return 0;
}

在这个示例中,我们尝试打开名为 test.db 的数据库文件。如果文件不存在,SQLite 会创建它。如果打开成功,我们可以通过 db 句柄执行 SQL 语句。在完成所有操作后,使用 sqlite3_close() 函数关闭数据库连接。

sqlite3_close()关闭数据库函数

sqlite3_close 函数用于关闭之前通过 sqlite3_open 打开的 SQLite 数据库连接。这个函数会释放与数据库句柄相关联的所有资源,并断开与数据库的连接。在关闭数据库之前,确保已经完成了所有必要的操作,并且所有的事务都已经提交或回滚。

函数原型如下:

int sqlite3_close(sqlite3 *db);

参数说明:

  • db:指向 sqlite3 * 类型的数据库句柄,这是之前通过 sqlite3_open 函数获取的。

返回值:

  • 成功时返回 SQLITE_OK(值为 0)。
  • 如果在关闭过程中发生错误,返回一个非零的错误码。

使用示例:

#include <stdio.h>
#include <sqlite3.h>

int main() {
    sqlite3 *db;
    int rc = sqlite3_open("test.db", &db);

    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    // 在这里执行数据库操作...

    // 关闭数据库连接
    rc = sqlite3_close(db);
    if (rc) {
        fprintf(stderr, "Can't close database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    printf("Database closed successfully\n");
    return 0;
}

在这个示例中,我们首先尝试打开一个名为 test.db 的数据库。如果成功,我们执行一些数据库操作,然后调用 sqlite3_close 来关闭数据库。如果关闭过程中出现错误,我们会打印错误信息并返回非零值。如果关闭成功,程序会打印一条成功消息。

请注意,如果你在数据库操作中使用了 sqlite3_exec 或其他需要回调的函数,确保在关闭数据库之前处理完所有回调。此外,如果你在事务中,需要在关闭数据库之前提交(sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);)或回滚(sqlite3_exec(db, "ROLLBACK;", NULL, NULL, NULL);)事务。

sqlite3_exec()执行sql语句函数

sqlite3_exec 是 SQLite 库中的一个函数,用于执行 SQL 语句。这个函数可以执行任何类型的 SQL 语句,包括创建表、插入数据、更新数据、删除数据以及执行查询等。它返回一个整数状态码,表示执行的结果。

函数原型如下:

int sqlite3_exec(
    sqlite3 *db,          /* 数据库句柄 */
    const char *sql,      /* SQL 语句 */
    sqlite3_callback callback, /* 可选的回调函数 */
    void *arg,            /* 传递给回调函数的参数 */
    char **errmsg,         /* 错误信息(如果发生错误) */
    char **tail          /* 未处理的 SQL 语句(可选) */
);

参数说明:

  • db:指向 sqlite3 类型的数据库句柄,这是通过 sqlite3_opensqlite3_open_v2 函数获取的。
  • sql:指向一个以 NULL 结尾的字符串,包含要执行的 SQL 语句。
  • callback:可选的回调函数,用于处理查询结果。如果 SQL 语句返回结果集,这个回调函数会被调用。如果不需要处理结果集,可以传递 NULL
  • arg:传递给回调函数的参数。
  • errmsg:指向一个字符指针的指针,如果执行失败,这里会存储错误信息。如果执行成功,这个指针应该设置为 NULL
  • tail:指向一个字符指针的指针,如果 SQL 语句包含多个语句(以分号分隔),这里会存储剩余未处理的 SQL 语句。如果不需要这个功能,可以传递 NULL

返回值:

  • 成功时返回 SQLITE_OK(值为 0)。
  • 失败时返回一个非零的错误码,可以通过 sqlite3_errmsg 函数获取错误信息。

使用示例:

#include <stdio.h>
#include <sqlite3.h>

// 回调函数,用于处理查询结果
int callback(void *NotUsed, int argc, char **argv, char **azColName) {
    int i;
    for (i = 0; i < argc; i++) {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

int main(int argc, char *argv[]) {
    sqlite3 *db;
    const char *sql;
    char *zErrMsg = 0;
    int rc;

    // 打开数据库
    rc = sqlite3_open("test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        return(0);
    }

    // 创建表
    sql = "CREATE TABLE IF NOT EXISTS COMPANY (ID INT PRIMARY KEY     NOT NULL, "
              "  NAME           TEXT    NOT NULL, "
              "  AGE            INT     NOT NULL, "
              "  ADDRESS        CHAR(50), "
              "  SALARY         REAL );";
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return(0);
    }

    // 插入数据
    sql = "INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY) "
          "VALUES (1, 'Paul', 32, 'California', 20000.0)";
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return(0);
    }

    // 查询数据
    sql = "SELECT * FROM COMPANY";
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return(0);
    }

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

在这个示例中,我们首先打开了一个名为 test.db 的数据库,然后创建了一个名为 COMPANY 的表。接着,我们插入了一条记录,并执行了一个查询,查询结果通过回调函数 callback 打印出来。最后,我们关闭了数据库连接。