织梦数据库SQL条件查询语句如何高效编写?

99ANYc3cd6
预计阅读时长 25 分钟
位置: 首页 织梦建站 正文

织梦CMS的数据库查询主要通过两个核心函数实现:dsql(旧版)和 pudsql(新版V5.7后推荐使用)。pudsql 是基于 PDO 的,更安全、更灵活,是当前的主流方式。

织梦数据库sql条件查询语句
(图片来源网络,侵删)

核心查询对象:$dsql$pudsql

在进行任何查询之前,你都需要获取数据库连接对象。

获取 $dsql 对象(适用于旧版或兼容模式)

// 在织梦的文件中,通常可以直接全局使用 $dsql 对象
// 如果在非标准环境中,需要手动初始化
$dsql = new DedeSql(false);
// 或者使用全局对象(在织梦文件中更常见)
global $dsql;

获取 $pudsql 对象(推荐,新版织梦)

// 在织梦文件中,可以直接使用全局 $pudsql 对象
global $pudsql;
// 如果需要手动初始化(例如在独立PHP脚本中)
require_once(DEDEINC.'/dedesql.class.php'); // 引入核心类文件
$pudsql = new DedeSql(FALSE); // 初始化

注意:在本文的后续示例中,我们将主要使用 $pudsql,因为它代表了未来的方向,并且语法更清晰,但大部分 $dsql 的方法与 $pudsql 是相通的。


基本查询结构

一个完整的SQL查询通常包含以下几个部分:

  1. SetQuery($sql): 设置你想要执行的SQL语句。
  2. Execute(): 执行查询。
  3. 获取结果: 使用 GetOne(), GetArray(), GetList() 等方法获取数据。
// 1. 设置SQL查询语句
$sql = "SELECT id, title, pubdate FROM dede_archives WHERE typeid = 1 ORDER BY pubdate DESC LIMIT 10";
// 2. 执行查询
$pudsql->SetQuery($sql);
$pudsql->Execute();
// 3. 获取结果 (这里以循环获取多行为例)
while ($row = $pudsql->GetArray()) {
    // $row 是一个关联数组,键名为字段名
    echo $row['id'] . ' - ' . $pudsql->GetField('title') . '<br>';
    // 注意:在循环中,GetArray() 会将指针下移,而 GetField() 是获取当前行指定字段的值
    // 更推荐使用 $row['title'] 的方式
    echo $row['id'] . ' - ' . $row['title'] . '<br>';
}

WHERE 条件查询详解

WHERE 子句是查询的核心,用于筛选记录,以下是常见的条件查询方式。

织梦数据库sql条件查询语句
(图片来源网络,侵删)

基本条件 (, , >, <, >=, <=)

// 查询ID为10的单篇文章
$sql = "SELECT id, title FROM dede_archives WHERE id = 10";
$pudsql->SetQuery($sql);
$row = $pudsql->GetOne(); // GetOne() 用于获取单条记录
if(is_array($row)) {
    echo "文章标题: " . $row['title'];
}

ANDOR 逻辑组合

// 查询栏目ID为1,并且状态为'已审核'的文章
$sql = "SELECT id, title FROM dede_archives WHERE typeid = 1 AND arcrank = 0";
$pudsql->SetQuery($sql);
$pudsql->Execute();
while($row = $pudsql->GetArray()) {
    // ...
}
// 查询栏目ID为1或2的文章
$sql = "SELECT id, title FROM dede_archives WHERE typeid = 1 OR typeid = 2";
// ...

INNOT IN

// 查询栏目ID在1, 3, 5中的文章
$sql = "SELECT id, title FROM dede_archives WHERE typeid IN (1, 3, 5)";
// ...
// 查询栏目ID不在1, 2, 3中的文章
$sql = "SELECT id, title FROM dede_archives WHERE typeid NOT IN (1, 2, 3)";
// ...

BETWEEN ... AND (范围查询)

// 查询发布日期在 '2025-01-01' 和 '2025-12-31' 之间的文章
$sql = "SELECT id, title, pubdate FROM dede_archives WHERE pubdate BETWEEN '2025-01-01' AND '2025-12-31'";
// ...

LIKE 模糊查询

LIKE 通常与通配符一起使用:

  • 代表任意数量的任意字符(包括0个)
  • _: 代表单个任意字符
$sql = "SELECT id, title FROM dede_archives WHERE title LIKE '%织梦%'";
// ...
以“DedeCMS”开头的文章
$sql = "SELECT id, title FROM dede_archives WHERE title LIKE 'DedeCMS%'";
// ...
第二个字符是“e”,最后一个字符是“s”的文章 (如: DedeCMS)
$sql = "SELECT id, title FROM dede_archives WHERE title LIKE '_e%s'";
// ...

高级查询技巧

排序 (ORDER BY)

// 按发布日期降序排列(最新的在前)
$sql = "SELECT id, title, pubdate FROM dede_archives ORDER BY pubdate DESC";
// 按点击量升序排列(点击量少的在前)
$sql = "SELECT id, title, click FROM dede_archives ORDER BY click ASC";

分页 (LIMIT)

LIMIT 用于限制返回的记录数量,是实现分页的关键。

// 获取第1页,每页10条记录
$sql = "SELECT id, title FROM dede_archives LIMIT 0, 10"; // (偏移量, 记录数)
// 获取第2页,每页10条记录
$sql = "SELECT id, title FROM dede_archives LIMIT 10, 10";
// 织梦自带分页函数 `GetPageList()`,但直接用SQL LIMIT更灵活

聚合函数 (COUNT, SUM, AVG, MAX, MIN)

聚合函数通常与 GROUP BY 一起使用。

// 统计每个栏目下的文章数量
$sql = "SELECT typeid, COUNT(id) as article_count FROM dede_archives GROUP BY typeid";
$pudsql->SetQuery($sql);
while($row = $pudsql->GetArray()) {
    echo "栏目ID: " . $row['typeid'] . ", 文章数: " . $row['article_count'] . "<br>";
}
// 获取全站文章总数
$sql = "SELECT COUNT(id) as total FROM dede_archives";
$pudsql->SetQuery($sql);
$row = $pudsql->GetOne();
echo "全站文章总数: " . $row['total'];

JOIN 多表查询

织梦的数据表是分离的,如文章内容在 dede_archives,栏目在 dede_arctype,查询时常常需要关联它们。

织梦数据库sql条件查询语句
(图片来源网络,侵删)
  • archives: 文章主表
  • arctype: 栏目表
  • addonarticle: 文章附加表(存放文章内容)
// 查询“织梦技术”栏目下的所有文章标题和内容
// 注意:这里需要关联 dede_archives 和 dede_addonarticle
$sql = "
    SELECT a.title, b.body
    FROM dede_archives AS a
    LEFT JOIN dede_addonarticle AS b ON a.id = b.aid
    WHERE a.typeid = (SELECT id FROM dede_arctype WHERE typename = '织梦技术')
";
$pudsql->SetQuery($sql);
while($row = $pudsql->GetArray()) {
    echo "<h2>" . $row['title'] . "</h2>";
    echo "<p>" . $row['body'] . "</p>";
}

安全查询:防止SQL注入

极其重要! 直接拼接SQL字符串是极其危险的,会导致SQL注入攻击,织梦的 $pudsql 对象提供了预处理语句来解决这个问题。

错误且危险的做法:

// 危险!不要这样做!
$id = $_GET['id'];
$sql = "SELECT * FROM dede_archives WHERE id = " . $id; // id是 '1 OR 1=1',就会泄露所有数据

安全的做法:使用 SelectOne()SelectSql() 的参数化查询

这些方法内部会自动处理SQL注入问题。

// 安全方法1:使用 $pudsql->SelectOne() 专门查询单条记录
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0; // 强制转为整数,增加安全性
$row = $pudsql->GetOne("SELECT id, title FROM dede_archives WHERE id = {$id}");
if($row){
    echo $row['title'];
}
// 安全方法2:使用 $pudsql->SelectSql() 查询多条记录(带参数绑定)
// 这是更强大的方式,可以处理复杂类型的数据
$sql = "SELECT id, title FROM dede_archives WHERE typeid = ? AND arcrank = ?";
$typeid = 1;
$arcrank = 0;
// 执行查询,参数以数组形式传入
$pudsql->Execute($sql, array($typeid, $arcrank));
while($row = $pudsql->GetArray()){
    echo $row['title'] . "<br>";
}

常用查询函数速查表

函数 功能 返回值 适用场景
$dsql->SetQuery($sql) 设置要执行的SQL语句 所有查询的第一步
$dsql->Execute() 执行 SetQuery 设置的SQL GetArray/GetOne 之前调用
$dsql->GetOne() 获取下一条记录(单条) 关联数组false 获取唯一匹配的记录
$dsql->GetArray() 获取下一条记录(循环用) 关联数组false while 循环中遍历多条记录
$dsql->GetAll() 获取所有记录 二维关联数组false 一次性获取所有结果
$dsql->GetTotalRow() 获取查询结果的总行数 整数 统计查询到的记录数
$dsql->GetField('field') 获取当前记录指定字段的值 字符串 GetArray 循环中使用,但不如 $row['field'] 直观
$dsql->SelectOne($sql) 执行SQL并直接返回单条结果 关联数组false 简化查询单条记录的写法
$dsql->SelectSql($sql, $arr) 执行带参数绑定的SQL 结果集对象 安全地执行复杂查询

总结与最佳实践

  1. 优先使用 $pudsql:如果你使用的是织梦V5.7或更高版本,请务必使用 $pudsql
  2. 永远不要相信外部输入:对来自 $_GET, $_POST, $_REQUEST 的数据进行严格过滤和类型转换,如 (int)htmlspecialchars()
  3. 优先使用参数化查询:对于包含变量的SQL语句,尽量使用 $pudsql->Execute($sql, $params) 的方式,这是防止SQL注入的黄金标准。
  4. 结果为空时要判断:使用 GetOne()GetArray() 后,务必用 if(is_array($row))if($row !== false) 来判断是否查询到数据,避免后续操作出错。
  5. 关闭不必要的查询:查询结束后,如果不再需要数据库连接,可以调用 $dsql->Close() 来释放资源,虽然PHP脚本结束时会自动关闭,但这是一个好习惯。
  6. 熟悉织梦表结构:在进行多表查询前,最好先了解 dede_archives, dede_arctype, dede_addonarticle 等核心表的结构,知道字段名和数据类型。
-- 展开阅读全文 --
头像
dede addonarticle是什么?
« 上一篇 2025-12-19
C11中noreturn关键字有何作用?
下一篇 » 2025-12-19

相关文章

取消
微信二维码
支付宝二维码

目录[+]