MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

POSIX系统上SQLite的安装与编译指南

2021-04-185.9k 阅读

SQLite简介

SQLite是一款轻型的数据库,它是遵守ACID的关系型数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持 Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。

POSIX系统概述

POSIX(Portable Operating System Interface for Unix)是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称。常见的符合POSIX标准的系统有Linux、FreeBSD、macOS(基于UNIX内核)等。这些系统在系统调用、文件操作、进程管理等方面遵循POSIX规范,为SQLite的安装与编译提供了相对统一的环境基础。

安装依赖工具

在编译SQLite之前,需要确保系统中安装了一些必要的工具,这些工具主要用于编译、链接以及管理软件包。

编译器(GCC)

GCC(GNU Compiler Collection)是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++、Objective - C、Fortran、Ada等语言编写的程序。在基于POSIX的系统中,如大多数Linux发行版,通常可以使用系统的包管理器来安装GCC。

  1. 在Debian或Ubuntu系统上 在终端中执行以下命令安装GCC:
sudo apt update
sudo apt install build - essential

这里的build - essential软件包元数据会自动安装GCC以及其他构建软件所需的基本工具,如make、libc6 - dev等。 2. 在Red Hat或CentOS系统上 使用以下命令安装:

sudo yum groupinstall "Development Tools"
  1. 在macOS上 可以通过Homebrew来安装GCC。首先确保已安装Homebrew,如果未安装,可在终端执行以下命令安装:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装好Homebrew后,执行以下命令安装GCC:

brew install gcc

其他依赖库

  1. zlib库:SQLite支持使用zlib库进行压缩,在编译时如果系统中有zlib库,SQLite会自动检测并使用它。在Debian或Ubuntu系统上安装zlib开发库的命令如下:
sudo apt install zlib1g - dev

在Red Hat或CentOS系统上:

sudo yum install zlib - devel

在macOS上,使用Homebrew安装:

brew install zlib
  1. readline库:该库为SQLite的命令行工具提供了命令行编辑和历史记录功能。在Debian或Ubuntu系统上安装:
sudo apt install libreadline - dev

在Red Hat或CentOS系统上:

sudo yum install readline - devel

在macOS上,使用Homebrew安装:

brew install readline

下载SQLite源码

SQLite的官方网站(https://www.sqlite.org/download.html)提供了源码下载。有两种主要的下载选项:预编译的 amalgamation 源码和完整的开发源码包。

下载Amalgamation源码

Amalgamation源码是将整个SQLite库合并为几个C和头文件,这种形式方便嵌入到其他项目中。通常包含sqlite3.csqlite3.h两个主要文件。可以通过以下方式下载:

wget https://www.sqlite.org/src/tarball/sqlite - amalgamation - 3.38.5.tar.gz
tar - xvf sqlite - amalgamation - 3.38.5.tar.gz
cd sqlite - amalgamation - 3.38.5

这里下载的是3.38.5版本,实际使用中可根据官网最新版本进行替换。

下载完整开发源码包

完整开发源码包包含了更多的文件,如测试脚本、工具等,对于想要深入了解SQLite内部实现以及进行定制开发的用户更有帮助。同样在官网下载对应的tar.gz包,例如:

wget https://www.sqlite.org/src/tarball/sqlite - 3.38.5.tar.gz
tar - xvf sqlite - 3.38.5.tar.gz
cd sqlite - 3.38.5

编译SQLite

配置编译选项

进入下载并解压后的SQLite源码目录,运行configure脚本进行编译配置。configure脚本会检测系统环境,设置合适的编译参数。

  1. 基本配置 运行以下命令:
./configure

这会使用默认的配置选项进行编译,生成的SQLite库将适用于大多数场景。 2. 自定义配置选项

  • 启用调试信息:如果希望在编译后的SQLite库中包含调试信息,方便后续调试,可以使用--enable - debug选项:
./configure --enable - debug
  • 指定安装目录:默认情况下,编译后的SQLite库和工具会安装到/usr/local目录。如果希望安装到其他目录,例如/opt/sqlite,可以使用--prefix选项:
./configure --prefix=/opt/sqlite
  • 禁用某些特性:比如如果不想在SQLite中支持运行时加载扩展,可以使用--disable - load - ext选项:
./configure --disable - load - ext

执行编译

完成配置后,执行make命令进行编译:

make

make工具会根据configure生成的Makefile文件,调用编译器(如GCC)对SQLite源码进行编译。编译过程中会输出一系列的编译信息,显示正在编译的源文件以及链接过程。如果编译过程中出现错误,通常会提示错误信息,例如缺少某个头文件或者某个函数未定义等。常见错误及解决方法如下:

  1. 缺少头文件错误:例如提示zlib.h: No such file or directory,这表明系统中没有安装zlib开发库,按照前面介绍的方法安装zlib开发库即可。
  2. 函数未定义错误:如果出现类似undefined reference to 'inflate'等错误,同样可能是zlib库相关问题,检查zlib库是否正确安装以及链接参数是否正确。在某些情况下,可能需要手动指定zlib库的路径,例如在configure时添加LDFLAGS=-L/path/to/zlib/lib CFLAGS=-I/path/to/zlib/include,其中/path/to/zlib是zlib库的实际安装路径。

测试编译结果

编译完成后,可以使用make test命令来运行SQLite自带的测试套件,以验证编译后的SQLite库和工具是否正常工作。

make test

测试过程会执行一系列的SQL语句和操作,检查SQLite的功能是否符合预期。如果测试通过,会显示类似All tests passed的信息;如果有测试失败,会详细列出失败的测试用例及错误信息。例如,如果在测试过程中出现testcase1 failed: SQL error,就需要根据具体的错误信息来排查问题,可能是编译配置问题,也可能是系统环境相关问题。

安装SQLite

执行安装

如果编译和测试都顺利通过,就可以执行安装操作。在编译目录下执行以下命令:

sudo make install

如果在configure时指定了--prefix选项,例如--prefix=/opt/sqlite,那么SQLite库、头文件以及工具会安装到/opt/sqlite目录下。具体来说,库文件会安装到/opt/sqlite/lib,头文件会安装到/opt/sqlite/include,可执行工具(如sqlite3命令行工具)会安装到/opt/sqlite/bin。如果没有指定--prefix,默认会安装到/usr/local/lib/usr/local/include/usr/local/bin

配置环境变量(可选)

如果将SQLite安装到了非默认路径(如/opt/sqlite),为了方便在系统任何位置使用sqlite3命令,需要配置环境变量。在POSIX系统中,可以编辑用户的~/.bashrc(对于Bash shell)或~/.zshrc(对于Zsh shell)文件,添加以下内容:

export PATH=/opt/sqlite/bin:$PATH

保存文件后,在终端执行以下命令使配置生效:

source ~/.bashrc

或者对于Zsh shell:

source ~/.zshrc

在应用中使用SQLite

C语言示例

下面是一个简单的C语言程序示例,展示如何在应用中使用SQLite。首先确保已经安装好SQLite开发头文件(通常在安装SQLite时会一并安装到/usr/local/include或指定的--prefix/include目录)。

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

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

int main() {
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    const char *sql;
    const char *data = "Callback function called";

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

    // 创建表
    sql = "CREATE TABLE 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);
    } else {
        fprintf(stdout, "Table created successfully\n");
    }

    // 插入数据
    sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
          "VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
          "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
          "VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); " \
          "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
          "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 ); " \
          "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
          "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";

    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } else {
        fprintf(stdout, "Records created successfully\n");
    }

    // 查询数据
    sql = "SELECT * from COMPANY";
    rc = sqlite3_exec(db, sql, callback, (void *)data, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } else {
        fprintf(stdout, "Operation done successfully\n");
    }

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

编译这个C程序时,需要链接SQLite库,假设程序保存为test_sqlite.c,可以使用以下命令编译:

gcc -o test_sqlite test_sqlite.c -lsqlite3

运行编译后的程序:

./test_sqlite

Python示例

Python通过sqlite3模块提供了对SQLite的支持,Python标准库中自带该模块,无需额外安装(前提是系统中安装了SQLite库)。以下是一个简单的Python示例:

import sqlite3

# 连接到SQLite数据库
conn = sqlite3.connect('test.db')
print("Opened database successfully")

# 创建表
conn.execute('''CREATE TABLE COMPANY
       (ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL);''')
print("Table created successfully")

# 插入数据
conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (1, 'Paul', 32, 'California', 20000.00 )")
conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (2, 'Allen', 25, 'Texas', 15000.00 )")
conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (3, 'Teddy', 23, 'Norway', 20000.00 )")
conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
      VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 )")
conn.commit()
print("Records created successfully")

# 查询数据
cursor = conn.execute("SELECT id, name, age, address, salary from COMPANY")
for row in cursor:
    print("ID = ", row[0])
    print("NAME = ", row[1])
    print("AGE = ", row[2])
    print("ADDRESS = ", row[3])
    print("SALARY = ", row[4], "\n")
print("Operation done successfully")

# 关闭连接
conn.close()

保存为test_sqlite.py,运行该脚本:

python3 test_sqlite.py

常见问题及解决方法

编译错误:缺少依赖库

  1. 症状:编译时出现类似fatal error: zlib.h: No such file or directoryundefined reference to 'inflate'等错误。
  2. 原因:缺少zlib库或zlib库未正确安装和链接。
  3. 解决方法:按照前面介绍的方法,使用系统包管理器或Homebrew安装zlib开发库。如果已经安装,检查configure时是否正确指定了zlib库的路径,例如通过LDFLAGSCFLAGS变量指定库路径和头文件路径。

运行时错误:无法找到SQLite库

  1. 症状:在运行使用SQLite的应用程序时,出现类似error while loading shared libraries: libsqlite3.so.0: cannot open shared object file: No such file or directory的错误。
  2. 原因:系统无法找到SQLite库文件。这可能是因为库文件安装在非标准路径,且系统的动态链接器没有配置该路径。
  3. 解决方法:如果SQLite库安装在自定义路径(如/opt/sqlite/lib),可以通过以下两种方法解决。
    • 临时方法:在运行应用程序前,设置LD_LIBRARY_PATH环境变量,例如:
export LD_LIBRARY_PATH=/opt/sqlite/lib:$LD_LIBRARY_PATH

然后再运行应用程序。

  • 永久方法:编辑/etc/ld.so.conf文件,添加SQLite库所在路径(如/opt/sqlite/lib),然后执行sudo ldconfig命令使更改生效。

数据库操作错误:SQL语法错误

  1. 症状:在使用SQLite进行数据库操作时,程序返回错误提示SQL语法错误,例如SQL error: near "(": syntax error
  2. 原因:编写的SQL语句存在语法错误,可能是拼写错误、缺少关键字、标点符号错误等。
  3. 解决方法:仔细检查SQL语句,可参考SQLite的官方文档来确认语法是否正确。例如,在创建表时,确保列定义和约束的语法准确无误,在查询时,检查SELECT语句的各个子句是否完整且正确。同时,注意SQL语句中的标点符号,特别是逗号、分号等,在不同的SQL操作中有特定的使用规则。

通过以上详细的步骤和说明,你应该能够在POSIX系统上顺利完成SQLite的安装与编译,并在自己的应用程序中使用SQLite进行数据库相关操作。在实际操作过程中,遇到问题可以根据常见问题及解决方法进行排查,也可以参考SQLite的官方文档获取更深入的技术支持。