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

(图片来源网络,侵删)
核心查询对象:$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查询通常包含以下几个部分:
SetQuery($sql): 设置你想要执行的SQL语句。Execute(): 执行查询。- 获取结果: 使用
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 子句是查询的核心,用于筛选记录,以下是常见的条件查询方式。

(图片来源网络,侵删)
基本条件 (, , >, <, >=, <=)
// 查询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'];
}
AND 与 OR 逻辑组合
// 查询栏目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";
// ...
IN 和 NOT 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,查询时常常需要关联它们。

(图片来源网络,侵删)
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 | 结果集对象 | 安全地执行复杂查询 |
总结与最佳实践
- 优先使用
$pudsql:如果你使用的是织梦V5.7或更高版本,请务必使用$pudsql。 - 永远不要相信外部输入:对来自
$_GET,$_POST,$_REQUEST的数据进行严格过滤和类型转换,如(int)或htmlspecialchars()。 - 优先使用参数化查询:对于包含变量的SQL语句,尽量使用
$pudsql->Execute($sql, $params)的方式,这是防止SQL注入的黄金标准。 - 结果为空时要判断:使用
GetOne()或GetArray()后,务必用if(is_array($row))或if($row !== false)来判断是否查询到数据,避免后续操作出错。 - 关闭不必要的查询:查询结束后,如果不再需要数据库连接,可以调用
$dsql->Close()来释放资源,虽然PHP脚本结束时会自动关闭,但这是一个好习惯。 - 熟悉织梦表结构:在进行多表查询前,最好先了解
dede_archives,dede_arctype,dede_addonarticle等核心表的结构,知道字段名和数据类型。
