# PHP SQLite3 教程

> 原文： [https://zetcode.com/php/sqlite3/](https://zetcode.com/php/sqlite3/)

这是针对 SQLite 版本 3 数据库的 PHP 编程教程。 它涵盖了使用 PHP 语言进行 SQLite 编程的基础。

要使用本教程，我们必须在系统上安装 PHP CLI。

为了使用 SQLite 数据库，我们可以安装`sqlite3`命令行工具或 SQLite 浏览器 GUI。

```php
$ php -v
PHP 7.2.11 (cli) (built: Oct 10 2018 02:39:52) ( ZTS MSVC15 (Visual C++ 2017) x86 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

```

在本教程中，我们使用 PHP 7.2.11。

```php
...
;extension=sockets
extension=sqlite3
;extension=tidy
...

```

SQLite 随 PHP 一起提供； 我们不需要安装它。 我们必须在`php.ini`文件中启用 sqlite3 扩展。

## SQLite

SQLite 是嵌入式关系数据库引擎。 该文档称其为自包含，无服务器，零配置和事务型 SQL 数据库引擎。 如今，它在全球使用着数亿册，非常受欢迎。 几种编程语言都内置了对 SQLite 的支持，包括 PHP 和 Python。

## 创建 SQLite 数据库

我们使用`sqlite3`命令行工具创建一个新数据库。

```php
$ sqlite3 test.db
SQLite version 3.27.2 2019-02-25 16:06:06
Enter ".help" for usage hints.
sqlite>

```

我们为`sqlite3`工具提供了一个参数； `test.db`是数据库名称。 这是我们磁盘上的文件。 如果存在，则将其打开。 如果不是，则创建它。

```php
sqlite> .tables
sqlite> .exit
$ ls
test.db

```

`.tables`命令提供`test.db`数据库中的表的列表。 当前没有表格。 `.exit`命令终止`sqlite3`命令行工具的交互式会话。 `ls`命令显示当前工作目录的内容。 我们可以看到`test.db`文件。 所有数据将存储在该单个文件中。

## PHP SQLite3 版本示例

在以下示例中，我们获得了 SQLite 数据库的版本。

`version.php`

```php
<?php

$ver = SQLite3::version();

echo $ver['versionString'] . "\n";
echo $ver['versionNumber'] . "\n";

var_dump($ver);

```

`SQLite3::version()`返回 SQLite 数据库的版本。

```php
$ php version.php
3.20.1
3020001
array(2) {
    ["versionString"]=>
    string(6) "3.20.1"
    ["versionNumber"]=>
    int(3020001)
}

```

这是输出。

`version2.php`

```php
<?php

$db = new SQLite3('test.db');

$version = $db->querySingle('SELECT SQLITE_VERSION()');

echo $version . "\n";

```

程序返回 SQLite 数据库的当前版本。 这次我们执行了`SELECT SQLITE_VERSION()`语句。

```php
$db = new SQLite3('test.db');

```

我们创建一个 SQLite3 对象并打开一个 SQLite3 数据库连接。

```php
$version = $db->querySingle('SELECT SQLITE_VERSION()');

```

`querySingle()`执行查询并返回单个结果。

```php
$ php version2.php
3.20.1

```

This is the output.

## PHP SQLite3 执行

`exec()`对给定的数据库执行无结果查询。

`create_table.php`

```php
<?php

$db = new SQLite3('test.db');

$db->exec("CREATE TABLE cars(id INTEGER PRIMARY KEY, name TEXT, price INT)");
$db->exec("INSERT INTO cars(name, price) VALUES('Audi', 52642)");
$db->exec("INSERT INTO cars(name, price) VALUES('Mercedes', 57127)");
$db->exec("INSERT INTO cars(name, price) VALUES('Skoda', 9000)");
$db->exec("INSERT INTO cars(name, price) VALUES('Volvo', 29000)");
$db->exec("INSERT INTO cars(name, price) VALUES('Bentley', 350000)");
$db->exec("INSERT INTO cars(name, price) VALUES('Citroen', 21000)");
$db->exec("INSERT INTO cars(name, price) VALUES('Hummer', 41400)");
$db->exec("INSERT INTO cars(name, price) VALUES('Volkswagen', 21600)");

```

该程序将创建一个`cars`表，并将八行插入该表中。

```php
$db->exec("CREATE TABLE cars(id INTEGER PRIMARY KEY, name TEXT, price INT)");

```

该 SQL 语句创建一个新的`cars`表。 该表有三列。 请注意，在 SQLite 数据库中，`INTEGER PRIMARY KEY`列是自动增加的。

```php
$db->exec("INSERT INTO cars(name, price) VALUES('Audi', 52642)");
$db->exec("INSERT INTO cars(name, price) VALUES('Mercedes', 57127)");

```

这两行将两辆车插入表。

```php
sqlite> .mode column
sqlite> .headers on

```

我们使用`sqlite3`工具验证写入的数据。 首先，我们修改数据在控制台中的显示方式。 我们使用列模式并打开标题。

```php
sqlite> select * from cars;
id          name        price
----------  ----------  ----------
1           Audi        52642
2           Mercedes    57127
3           Skoda       9000
4           Volvo       29000
5           Bentley     350000
6           Citroen     21000
7           Hummer      41400
8           Volkswagen  21600

```

这是我们已写入`cars`表的数据。

## PHP SQLite3 `lastInsertRowID`

有时，我们需要确定最后插入的行的 ID。 在 PHP SQLite3 中，我们使用`lastInsertRowID()`方法。

`last_rowid.php`

```php
<?php

$db = new SQLite3(':memory:');

$db->exec("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)");
$db->exec("INSERT INTO friends(name) VALUES ('Tom')");
$db->exec("INSERT INTO friends(name) VALUES ('Rebecca')");
$db->exec("INSERT INTO friends(name) VALUES ('Jim')");
$db->exec("INSERT INTO friends(name) VALUES ('Robert')");

$last_row_id = $db->lastInsertRowID();

echo "The last inserted row Id is $last_row_id";

```

我们在内存中创建一个`friends`表。 ID 会自动递增。

```php
$db->exec("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)");

```

在 SQLite3 中，`INTEGER PRIMARY KEY`列自动增加。 还有一个`AUTOINCREMENT`关键字。 在`INTEGER PRIMARY KEY AUTOINCREMENT`中使用时，会使用稍微不同的 ID 创建算法。

```php
$db->exec("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)");
$db->exec("INSERT INTO friends(name) VALUES ('Tom')");
$db->exec("INSERT INTO friends(name) VALUES ('Rebecca')");
$db->exec("INSERT INTO friends(name) VALUES ('Jim')");
$db->exec("INSERT INTO friends(name) VALUES ('Robert')");

```

使用自动增量时，我们必须明确声明列名，而忽略自动增量的列名。 这四个语句在`friends`表中插入四行。

```php
$last_row_id = $db->lastInsertRowID();

```

使用`lastInsertRowID()`获得最后插入的行 ID。

```php
$ php last_rowid.php
The last inserted row Id is 4

```

我们看到了程序的输出。

## PHP SQLite3 查询

`query()`方法执行 SQL 查询并返回结果对象。

`fetch_all.php`

```php
<?php

$db = new SQLite3('test.db');

$res = $db->query('SELECT * FROM cars');

while ($row = $res->fetchArray()) {
    echo "{$row['id']} {$row['name']} {$row['price']} \n";
}

```

该示例从`cars`表中检索所有数据。

```php
$res = $db->query('SELECT * FROM cars');

```

该 SQL 语句从`cars`表中选择所有数据。

```php
while ($row = $res->fetchArray()) {

```

`fetchall()`检索结果行作为关联数组或数字索引数组，或两者都检索（默认为两者）。 如果没有更多行，则返回`false`。

```php
$ php fetch_all.php
1 Audi 52642
2 Mercedes 57127
3 Skoda 9000
4 Volvo 29000
5 Bentley 350000
6 Citroen 21000
7 Hummer 41400
8 Volkswagen 21600

```

这是示例的输出。

## PHP SQLite3 `escapeString`

`escapeString()`返回已正确转义的字符串。

`escape_string.php`

```php
<?php

$db = new SQLite3('test.db');

$sql = "SELECT name FROM cars WHERE name = 'Audi'";

$escaped = SQLite3::escapeString($sql);

var_dump($sql);
var_dump($escaped);

```

该示例对查询中的字符串进行转义。

```php
$ php escape_string.php
string(41) "SELECT name FROM cars WHERE name = 'Audi'"
string(43) "SELECT name FROM cars WHERE name = ''Audi''"

```

This is the output of the example.

## PHP SQLite3 参数化语句

SQL 语句通常是动态构建的。 用户提供一些输入，并且此输入已内置到语句中。 每当我们处理来自用户的输入时，我们都必须谨慎。 它具有一些严重的安全隐患。 动态构建 SQL 语句的推荐方法是使用参数绑定。

使用`prepare()`创建参数化查询； 它准备要执行的 SQL 语句并返回一个语句对象。

PHP SQLite3 具有`bindParam()`和`bindValue()`方法来将值绑定到占位符。 它允许将数据绑定到问号或命名的占位符。

### 带问号的参数化语句

在第一个示例中，我们使用问号的语法。

`prepared.php`

```php
<?php

$db = new SQLite3('test.db');

$stm = $db->prepare('SELECT * FROM cars WHERE id = ?');
$stm->bindValue(1, 3, SQLITE3_INTEGER);

$res = $stm->execute();

$row = $res->fetchArray(SQLITE3_NUM);
echo "{$row[0]} {$row[1]} {$row[2]}";

```

我们选择使用问号占位符的汽车。

```php
$stm = $db->prepare('SELECT * FROM cars WHERE id = ?');

```

问号`?`是值的占位符。 稍后将这些值添加（绑定）到占位符。

```php
$stm->bindValue(1, 3, SQLITE3_INTEGER);

```

使用`bindValue()`，将值 3 绑定到问号占位符。 第一个参数是位置参数，用于标识占位符（可以有多个问号占位符）。

```php
$ php prepared.php
3 Skoda 9000

```

This is the output.

### 具有命名占位符的参数化语句

第二个示例使用带有命名占位符的参数化语句。

`prepared2.php`

```php
<?php

$db = new SQLite3('test.db');

$stm = $db->prepare('SELECT * FROM cars WHERE id = :id');
$stm->bindValue(':id', 1, SQLITE3_INTEGER);

$res = $stm->execute();

$row = $res->fetchArray(SQLITE3_NUM);
echo "{$row[0]} {$row[1]} {$row[2]}";

```

我们使用命名的占位符选择特定的汽车。

```php
$stm = $db->prepare('SELECT * FROM cars WHERE id = :id');

```

命名的占位符以冒号开头。

### PHP SQLite3 bind_param

`bind_param()`将参数绑定到语句变量。 它可以用于处理多行。

`bind_param.php`

```php
≪?php

$db = new SQLite3(':memory:');

$db->exec("CREATE TABLE friends(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT)");

$stm = $db->prepare("INSERT INTO friends(firstname, lastname) VALUES (?, ?)");
$stm->bindParam(1, $firstName);
$stm->bindParam(2, $lastName);

$firstName = 'Peter';
$lastName = 'Novak';
$stm->execute();

$firstName = 'Lucy';
$lastName = 'Brown';
$stm->execute();

$res = $db->query('SELECT * FROM friends');

while ($row = $res->fetchArray()) {
    echo "{$row[0]} {$row[1]} {$row[2]}\n";
}

```

在示例中，我们将两行插入到带有参数化语句的表中。 要绑定占位符，我们使用`bind_param()`方法。

```php
$ php bind_param.php
1 Peter Novak
2 Lucy Brown

```

This is the output.

## PHP SQLite3 元数据

元数据是有关数据库中数据的信息。 SQLite 中的元数据包含有关表和列的信息，我们在其中存储数据。 受 SQL 语句影响的行数是元数据。 结果集中返回的行数和列数也属于元数据。

可以使用特定的 PHP SQLite3 方法，`PRAGMA`命令或通过查询 SQLite 系统`sqlite_master`表来获取 SQLite 中的元数据。

`num_of_columns.php`

```php
<?php

$db = new SQLite3('test.db');

$res = $db->query("SELECT * FROM cars WHERE id = 1");
$cols = $res->numColumns();

echo "There are {$cols} columns in the result set\n";

```

`numColumns()`返回结果集中的列数。

```php
$ php num_of_columns.php
There are 3 columns in the result set

```

This is the output.

`column_names.php`

```php
<?php

$db = new SQLite3('test.db');

$res = $db->query("PRAGMA table_info(cars)");

while ($row = $res->fetchArray(SQLITE3_NUM)) {
    echo "{$row[0]} {$row[1]} {$row[2]}\n";
}

```

在此示例中，我们发出`PRAGMA table_info(tableName)`命令以获取有关`cars`表的一些元数据信息。

```php
$res = $db->query("PRAGMA table_info(cars)");

```

`PRAGMA table_info(tableName)`命令为`cars`表中的每一列返回一行。 结果集中的列包括列顺序号，列名称，数据类型，该列是否可以为`NULL`以及该列的默认值。

```php
while ($row = $res->fetchArray(SQLITE3_NUM)) {
    echo "{$row[0]} {$row[1]} {$row[2]}\n";
}

```

根据提供的信息，我们打印列顺序号，列名称和列数据类型。

```php
$ php column_names.php
0 id INTEGER
1 name TEXT
2 price INT

```

This is the output of the example.

在下面的示例中，我们打印`cars`表中的所有行及其列名。

`column_names2.php`

```php
<?php

$db = new SQLite3('test.db');

$res = $db->query("SELECT * FROM cars");

$col1 = $res->columnName(1);
$col2 = $res->columnName(2);

$header = sprintf("%-10s %s\n", $col1, $col2);
echo $header;

while ($row = $res->fetchArray()) {

    $line = sprintf("%-10s %s\n", $row[1], $row[2]);
    echo $line;
}

```

我们还将`cars`表的内容与列名一起打印到控制台。 记录与列名对齐。

```php
$col1 = $res->columnName(1);

```

`columnName()`返回第 n 列的名称。

```php
$header = sprintf("%-10s %s\n", $col1, $col2);
echo $header;

```

这些行打印`cars`表的两个列名。

```php
while ($row = $res->fetchArray()) {

    $line = sprintf("%-10s %s\n", $row[1], $row[2]);
    echo $line;
}

```

我们使用`while`循环打印行。 数据与列名对齐。

```php
$ php column_names2.php
name       price
Audi       52642
Mercedes   57127
Skoda      9000
Volvo      29000
Bentley    350000
Citroen    21000
Hummer     41400
Volkswagen 21600

```

This is the output.

在下一个示例中，我们列出`test.db`数据库中的所有表。

`list_tables.php`

```php
<?php

$db = new SQLite3('test.db');

$res = $db->query("SELECT name FROM sqlite_master WHERE type='table'");

while ($row = $res->fetchArray(SQLITE3_NUM)) {
    echo "{$row[0]}\n";
}

```

该代码示例将指定数据库中的所有可用表打印到终端。

```php
$res = $db->query("SELECT name FROM sqlite_master WHERE type='table'");

```

表名存储在系统`sqlite_master`表中。

```php
$ php list_tables.php
cars
images

```

这些是我们系统上的表。

`changes()`返回由最新 SQL 语句修改，插入或删除的数据库行数。

`changes.php`

```php
<?php

$db = new SQLite3(':memory:');

$db->exec("CREATE TABLE friends(id INTEGER PRIMARY KEY, name TEXT)");
$db->exec("INSERT INTO friends(name) VALUES ('Tom')");
$db->exec("INSERT INTO friends(name) VALUES ('Rebecca')");
$db->exec("INSERT INTO friends(name) VALUES ('Jim')");
$db->exec("INSERT INTO friends(name) VALUES ('Robert')");

$db->exec('DELETE FROM friends');

$changes = $db->changes();

echo "The DELETE statement removed $changes rows";

```

该示例返回已删除的行数。

```php
$ php changes.php
The DELETE statement removed 4 rows

```

This is the output.

## PHP SQLite3 PDO 示例

PHP 数据对象（PDO）定义了用于访问 PHP 中的数据库的轻量级接口。 它提供了一个数据访问抽象层，用于在 PHP 中使用数据库。 它定义了用于各种数据库系统的一致 API。

PHP PDO 是一个内置库； 我们不需要安装它。

`list_tables.php`

```php
<?php

$pdo = new PDO('sqlite:test.db');

$stm = $pdo->query("SELECT * FROM cars");
$rows = $stm->fetchAll(PDO::FETCH_NUM);

foreach($rows as $row) {

    printf("$row[0] $row[1] $row[2]\n");
}

```

该示例使用 PHP PDO 获取所有表行。

## Dibi 的例子

PHP Dibi 是用于 PHP 的小型智能数据库层。

```php
$ composer req dibi/dibi

```

我们安装库。

`fetch_cars.php`

```php
<?php

require('vendor/autoload.php');

$db = dibi::connect([
    'driver' => 'sqlite',
    'database' => 'test.db',
]);

$rows = $db->query('SELECT * FROM cars');

foreach ($rows as $row) {

    $id = $row->id;
    $name = $row->name;
    $price = $row->price;

    echo "$id $name $price \n";
}

```

该示例从`cars`表中提取所有行。

## Doctrine DBAL 示例

Doctrine 是一组 PHP 库，主要致力于在 PHP 中提供持久性服务。 它的主要项目是对象关系映射器（ORM）和数据库抽象层（DBAL）。

```php
$ composer req doctrine/dbal

```

我们安装 Doctrine DBAL 包。

`fetch_cars.php`

```php
<?php

require_once "vendor/autoload.php";

use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;

$attrs = ['driver' => 'pdo_sqlite', 'path' => 'test.db'];

$conn = DriverManager::getConnection($attrs);

$queryBuilder = $conn->createQueryBuilder();
$queryBuilder->select('*')->from('cars');

$stm = $queryBuilder->execute();
$rows = $stm->fetchAll(FetchMode::NUMERIC);

foreach ($rows as $row) {

    echo "{$row[0]} {$row[1]} {$row[2]}\n";
}

```

该示例使用 Doctrine DBAL `QueryBuilder`从`cars`表中检索所有行。

这是 PHP SQLite3 教程。 您可能也对以下相关教程感兴趣： [Doctrine `QueryBuilder`教程](/doctrine/querybuilder/)， [PHP PDO 教程](/php/pdo/)和 [PHP 教程](/lang/php/)，或列出[所有 PHP 教程](/all/#php)。