查询
查询基础
注意
CodeIgniter 不支持数据库、表和列名称中的点 (.
)。
常规查询
$db->query()
要提交查询,请使用 query()
方法
<?php
$db = db_connect();
$db->query('YOUR QUERY HERE');
当执行“读取”类型的查询时,query()
方法返回一个数据库结果对象,您可以使用它来显示您的结果。当执行“写入”类型的查询时,它只返回 true 或 false,具体取决于成功或失败。在检索数据时,您通常会将查询分配给您自己的变量,如下所示
<?php
$query = $db->query('YOUR QUERY HERE');
注意
如果您使用的是 OCI8 驱动程序,SQL 语句不应以分号 (;
) 结尾。PL/SQL 语句应以分号 (;
) 结尾。
简化查询
$db->simpleQuery()
simpleQuery()
方法是 $db->query()
方法的简化版本。它不返回数据库结果集,也不设置查询计时器,也不编译绑定数据,也不存储您的查询以供调试。它只是让您提交查询。大多数用户很少使用此函数。
它返回数据库驱动程序的“执行”函数返回的任何内容。对于写入类型的查询(如 INSERT、DELETE 或 UPDATE 语句),这通常是成功或失败时的 true/false(这正是它应该使用的目的),对于具有可获取结果的查询,则在成功时返回资源/对象。
<?php
if ($db->simpleQuery('YOUR QUERY')) {
echo 'Success!';
} else {
echo 'Query failed!';
}
注意
PostgreSQL 的 pg_exec()
函数(例如)始终在成功时返回资源,即使对于写入类型的查询也是如此。因此,如果您正在寻找布尔值,请记住这一点。
手动处理数据库前缀
$db->prefixTable()
如果您已配置数据库前缀,并且希望将其附加到表名中以在原生 SQL 查询中使用,例如,您可以使用以下方法
<?php
$db->prefixTable('tablename'); // outputs prefix_tablename
$db->setPrefix()
如果出于任何原因,您希望以编程方式更改前缀,而无需创建新的连接,您可以使用此方法
<?php
$db->setPrefix('newprefix_');
$db->prefixTable('tablename'); // outputs newprefix_tablename
$db->getPrefix()
您可以随时使用此方法获取当前前缀
<?php
$DBPrefix = $db->getPrefix();
保护标识符
$db->protectIdentifiers()
在许多数据库中,建议保护表名和字段名 - 例如在 MySQL 中使用反引号。查询构建器查询会自动受到保护,但如果您需要手动保护标识符,可以使用
<?php
$db->protectIdentifiers('table_name');
重要
虽然查询构建器会尽力正确地引用您提供的所有字段和表名,但请注意,它**并非**设计用于处理任意用户输入。**不要**将未经清理的用户数据提供给它。
此函数还会在您的表名前添加**表前缀**,假设您在数据库配置文件中指定了前缀。要启用前缀,请通过第二个参数设置true
(布尔值)。
<?php
$db->protectIdentifiers('table_name', true);
转义值
在将数据提交到数据库之前对其进行转义是一个非常好的安全实践。CodeIgniter 有三种方法可以帮助您做到这一点。
1. $db->escape()
此函数会确定数据类型,以便它只转义字符串数据。它还会自动在数据周围添加单引号,因此您不必这样做。
<?php
$sql = 'INSERT INTO table (title) VALUES(' . $db->escape($title) . ')';
2. $db->escapeString()
此函数会转义传递给它的数据,无论类型如何。大多数情况下,您会使用上面的函数而不是这个函数。像这样使用该函数:
<?php
$sql = "INSERT INTO table (title) VALUES('" . $db->escapeString($title) . "')";
3. $db->escapeLikeString()
当字符串要在 LIKE 条件中使用时,应该使用此方法,以便 LIKE 通配符(%
,_
)在字符串中也能被正确地转义。
<?php
$search = '20% raise';
$sql = "SELECT id FROM table WHERE column LIKE '%" . $db->escapeLikeString($search) . "%' ESCAPE '!'";
重要
escapeLikeString()
方法使用 '!'
(感叹号)来转义 LIKE
条件的特殊字符。因为此方法转义的是您自己用引号括起来的字符串的一部分,所以它无法自动为您添加 ESCAPE '!'
条件,因此您必须手动执行此操作。
查询绑定
绑定使您能够通过让系统为您组合查询来简化查询语法。请考虑以下示例:
<?php
$sql = 'SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?';
$db->query($sql, [3, 'live', 'Rick']);
查询中的问号会自动替换为查询函数第二个参数中数组中的值。
绑定也适用于数组,这些数组将被转换为 IN 集合。
<?php
$sql = 'SELECT * FROM some_table WHERE id IN ? AND status = ? AND author = ?';
$db->query($sql, [[3, 6], 'live', 'Rick']);
生成的查询将是:
SELECT * FROM some_table WHERE id IN (3,6) AND status = 'live' AND author = 'Rick'
使用绑定带来的次要好处是,值会自动转义,从而生成更安全的查询。您无需记住手动转义数据 - 引擎会自动为您完成。
命名绑定
您可以使用名称来标记绑定值的位置,而不是使用问号,这样就可以让传入的值的键与查询中的占位符匹配。
<?php
$sql = 'SELECT * FROM some_table WHERE id = :id: AND status = :status: AND author = :name:';
$db->query($sql, [
'id' => 3,
'status' => 'live',
'name' => 'Rick',
]);
注意
查询中的每个名称都必须用冒号括起来。
处理错误
$db->error()
如果您需要获取发生的最后一个错误,error()
方法将返回一个包含其代码和消息的数组。以下是一个简单的示例
<?php
if (! $db->simpleQuery('SELECT `example_field` FROM `example_table`')) {
$error = $db->error(); // Has keys 'code' and 'message'
}
预备查询
大多数数据库引擎都支持某种形式的预备语句,允许您准备一次查询,然后使用新的数据集多次运行该查询。这消除了 SQL 注入的可能性,因为数据以与查询本身不同的格式传递到数据库。当您需要多次运行相同的查询时,它也会快很多。但是,对每个查询都使用它可能会导致性能下降,因为您要调用数据库的次数是原来的两倍。由于查询构建器和数据库连接已经为您处理了数据转义,因此安全性方面已经为您处理好了。但是,有时您需要通过运行预备语句或预备查询来优化查询。
准备查询
这可以通过 prepare()
方法轻松完成。它接受一个参数,该参数是一个返回查询对象的闭包。查询对象由任何“最终”类型的查询自动生成,包括 **insert**、**update**、**delete**、**replace** 和 **get**。这可以通过使用查询构建器来运行查询来最轻松地处理。查询实际上并没有运行,并且值并不重要,因为它们永远不会被应用,而是充当占位符。这将返回一个 PreparedQuery 对象
<?php
$pQuery = $db->prepare(static function ($db) {
return $db->table('user')->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US',
]);
});
如果您不想使用查询构建器,您可以使用问号作为值占位符手动创建查询对象
<?php
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(static function ($db) {
$sql = 'INSERT INTO user (name, email, country) VALUES (?, ?, ?)';
return (new Query($db))->setQuery($sql);
});
如果数据库在准备语句阶段需要传递给它的选项数组,您可以在第二个参数中传递该数组
<?php
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(static function ($db) {
$sql = 'INSERT INTO user (name, email, country) VALUES (?, ?, ?)';
return (new Query($db))->setQuery($sql);
}, $options);
执行查询
准备好查询后,可以使用 execute()
方法实际运行查询。您可以在查询参数中传递任意数量的变量。传递的参数数量必须与查询中的占位符数量匹配。它们还必须按照占位符在原始查询中出现的顺序传递。
<?php
// Prepare the Query
$pQuery = $db->prepare(static function ($db) {
return $db->table('user')->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US',
]);
});
// Collect the Data
$name = 'John Doe';
$email = '[email protected]';
$country = 'US';
// Run the Query
$results = $pQuery->execute($name, $email, $country);
对于“写入”类型的查询,它返回 true 或 false,表示查询的成功或失败。对于“读取”类型的查询,它返回一个标准的 结果集.
其他方法
除了这两个主要方法之外,准备好的查询对象还具有以下方法。
close()
虽然 PHP 在关闭与数据库的所有打开语句方面做得很好,但始终建议在完成准备好的语句后将其关闭。
<?php
if ($pQuery->close()) {
echo 'Success!';
} else {
echo 'Deallocation of prepared statements failed!';
}
注意
从 v4.3.0 开始,close()
方法在所有 DBMS 中释放准备好的语句。以前,它们在 Postgre、SQLSRV 和 OCI8 中没有被释放。
getQueryString()
这将准备好的查询作为字符串返回。
hasError()
如果最后一次 execute()
调用创建了任何错误,则返回布尔值 true/false。
getErrorCode()
getErrorMessage()
如果遇到任何错误,可以使用这些方法检索错误代码和字符串。
使用查询对象
在内部,所有查询都以 CodeIgniter\Database\Query
实例的形式进行处理和存储。此类负责绑定参数,否则准备查询,并存储有关其查询的性能数据。
$db->getLastQuery()
当您只需要检索最后一个查询对象时,请使用 getLastQuery()
方法。
<?php
$query = $db->getLastQuery();
echo (string) $query;
查询类
每个查询对象都存储有关查询本身的几个信息。这在一定程度上由时间线功能使用,但也可以供您使用。
getQuery()
返回所有处理完成后最终的查询。这是发送到数据库的精确查询
<?php
$sql = $query->getQuery();
可以通过将 Query 对象转换为字符串来检索相同的值
<?php
$sql = (string) $query;
getOriginalQuery()
返回传递到对象的原始 SQL。它不会包含任何绑定,也不会交换前缀等
<?php
$sql = $query->getOriginalQuery();
hasError()
如果在执行此查询期间遇到错误,此方法将返回 true
<?php
if ($query->hasError()) {
echo 'Code: ' . $query->getErrorCode();
echo 'Error: ' . $query->getErrorMessage();
}
isWriteType()
如果确定查询为写入类型查询(即 INSERT、UPDATE、DELETE 等),则返回 true
<?php
if ($query->isWriteType()) {
// ... do something
}
swapPrefix()
用另一个值替换 SQL 中的一个表前缀。第一个参数是要替换的原始前缀,第二个参数是要替换的值
<?php
$sql = $query->swapPrefix('ci3_', 'ci4_');
getStartTime()
获取查询执行时间的秒数和微秒数
<?php
$microtime = $query->getStartTime();
getDuration()
返回一个浮点数,表示查询的持续时间,以秒和微秒为单位
<?php
$microtime = $query->getDuration();