database_zh
基础配置
当你需要使用数据库增删改查功能时,可直接使用CORE_DB
(/std/database.c
),这个文件提供了一系列的方法链式操作数据库。
void test()
{
/**
* @brief 初始化数据库连接
*
*/
object DB = new(CORE_DB, host, db, user);
// ...
}
或者使用 setConnection()
方法配置数据库:
void test()
{
object DB = new(CORE_DB);
mapping db = ([
"host":"127.0.0.1",
"database":"mud",
"user":"root",
]);
DB->setConnection(db);
}
上以配置使用以的是系统默认数据库类型__DEFAULT_DB__
,如果要指定数据库类型可以使用以下方式:
void test()
{
// 初始化时指定type
object DB = new(CORE_DB, host, db, user, type);
// 通过配置指定type(使用SQLITE3)
mapping db = ([
"host":"",
"database":"/data/mudlite.db",
"user":"",
"type":__USE_SQLITE3__
]);
DB->setConnection(db);
}
数据库类型可以使用宏定义:__USE_MYSQL__
、__USE_SQLITE3__
、__USE_POSTGRE__
或__DEFAULT_DB__
。
查询
从数据表中查询所有行
使用DB
对象的table
方法指定要查询的数据表并返回一个查询对象,使用get
方法获取所有结果,返回值为结果二维数组,示例代码:
inherit CORE_DB;
void test()
{
mixed res;
// 获取 users 表的所有结果
res = DB->table("users")->get();
printf("%O\n", res);
}
从数据表中获取单行或单列
使用first
方法可以获取查询结果的第一行,返回值为一维数组结果,如果指定数组做为参数,只查询指定的列,另外你可以使用where
方法限制查询条件,核心代码:
// 查询用户表中的第一条数据
res = DB->table("users")->first();
// 查询用户表中的第一条数据的name和email
res = DB->table("users")->first("name", "email");
// 查询用户表中用户名为 ivy 的数据
res = DB->table("users")->where("name", "ivy")->first();
如果不需要整行数据,则可以使用value
方法从记录中获取单个值。该方法将直接返回该字段的值:
// 获得用户 ivy 的 email
email = DB->table("users")->where("name", "ivy")->value("email");
// 获取随机用户的 email
email = DB->table("users")->inRandomOrder()->value("email");
如果是通过 id 字段值获取一行数据,可以使用 find 方法:
// 获取 ID 为 1 的用户数据
res = DB->table("users")->find(1);
获取一列的值
如果你想获取单列数据的集合,则可以使用 pluck 方法。在下面的例子中,我们将获取角色表中所有邮箱:
// 返回所有用户的邮箱数组
res = DB->table("users")->pluck("email");
聚合
查询构造器还提供了各种聚合方法,比如 count
,max
,min
,avg
,还有 sum
。你可以在构造查询后调用任何方法:
// 获取用户总数
users = DB->table("users")->count();
// 获取等级最高的用户
level = DB->table("users")->max("level");
同样,你可以通过条件查询限制聚合查询:
// 返回ID为9的用户发贴的访问量之和
res = DB->table("topics")->where("user_id", 9)->sum("view_count");
// 判断用户mudren是否存在
count = DB->table("users")->where("name", "mudren")->count();
Where Clauses
where 语句
在构造 where
查询实例中,你可以使用 where
方法。调用 where
最基本的方式是需要传递三个参数:第一个参数是列名,第二个参数是任意一个数据库系统支持的运算符,第三个是该列要比较的值。如:
user = DB->table("users")->where("name", "=", "mudren")->get();
为了方便,如果你只是简单比较列值和给定数值是否相等,可以将数值直接作为 where 方法的第二个参数:
user = DB->table("users")->where("name", "mudren")->get();
当然,你也可以使用其他的运算符来编写 where
子句:
users = DB->table("users")
->where("id", ">=", 100)
->get();
users = DB->table("users")
->where("id", "<>", 100)
->get();
users = DB->table("users")
->where("email", "like", "%@mud.ren")
->get();
你还可以传递条件数组到 where 函数中实现 AND
查询:
// 相当于 WHERE user_id>7 AND category_id=4
res = DB->table("topics")->where(({ ({"user_id", ">", 7}), ({"category_id", 4}) }))->get();
你也可以对 where
函数链式调用,以上查询可以使用以下方式:
// 相当于 WHERE user_id>7 AND category_id=4
res = DB->table("topics")->where("user_id", ">", 7)->where("category_id", 4)->get();
orWhere 语句
你可以一起链式调用 where
约束,也可以在查询中添加 or 字句。 orWhere
方法和 where
方法接收的参数一样:
// 相当于 WHERE user_id>7 OR category_id=4
res = DB->table("topics")->where("user_id", ">", 7)->orWhere("category_id", 4)->get();
请注意:orWhere
方法之前必须至少有一次where
调用,否则报错。
附加 Where 语句
除了基础的 where
和 orWhere
,还有以下语句可用:
whereBetween / orWhereBetween / whereNotBetween / orWhereNotBetween
验证字段值是否在给定的两个值之间或之外:
users = DB->table("users")
->whereBetween("votes", ({1, 100}))
->get();
whereNull / orWhereNull / whereNotNull / orWhereNotNull
验证指定的字段是否是 NULL
:
users = DB->table("users")
->whereNull("updated_at")
->get();
Ordering, Grouping, Limit & Offset
orderBy
orderBy
方法允许你通过给定字段对结果集进行排序。 orderBy
的第一个参数应该是你希望排序的字段,第二个参数控制排序的方向,可以是 asc
或 desc
:
users = DB->table("users")
->orderBy("name", "desc")
->get();
如果你需要使用多个字段进行排序,你可以多次引用 orderBy
:
users = DB->table("users")
->orderBy("name", "desc")
->orderBy("email", "asc")
->get();
inRandomOrder
inRandomOrder
方法被用来将结果进行随机排序。例如,你可以使用此方法随机找到一个用户:
randomUser = DB->table("users")
->inRandomOrder()
->first();
limit / offset
要限制结果的返回数量,或跳过指定数量的结果,你可以使用 limit
和 offset
方法:
users = DB->table("users")
->offset(10)
->limit(5)
->get();
插入
查询构造器还提供了 insert
方法用于插入记录到数据库中。 insert
方法接收映射形式的字段名和字段值进行插入操作:
DB->table("users")->insert((["name":"test", "email":"test@mud.ren"]));
更新
查询构造器也可以通过 update
方法更新已有的记录。 update
方法和 insert
方法一样,接受包含要更新的字段及值的映射。你可以通过 where
子句对 update
查询进行约束:
DB->table("users")->where("id", ">", 120)->limit(5)->update((["level":777]));
删除
查询构造器也可以使用 delete
方法从表中删除记录。 在使用 delete
前,可以添加 where
子句来约束 delete
语法:
DB->table("migrations")->where("id",">", 55)->limit(5)->delete();
原生语句
除了使用封装好的方法外,查询构造器还提供了原生SQL语句的使用,通过使用 sql
方法执行,注意对 SELECT
语句可以使用 get
、first
、pluck
、value
方法获取查询结果,而 INSERT
、UPDATE
、DELETE
语句使用 exec
执行。
// 查询
res = DB->sql("select * from users")->get();
res = DB->sql("select * from users")->pluck("name");
res = DB->sql("select * from users where name='mudren'")->value("email");
// 删除
res = DB->sql("delete from users where id>130 limit 5")->exec();
长连接
需要注意的是,CORE_DB
默认使用的是短连接,所有数据库操作完成后自动释放 db_handle ,如果需要大量或高频次查询,最好改为长连接,并自己在必要时操作释放 db_handle 。
如需长连接,请使用 setAutoClose(0)
方法禁用自动释放,并在执行结束时调用 close(1)
方法释放 db_handle。
void test()
{
// 初始化数据库连接
object DB = new(CORE_DB, host, db, user);
// 禁用自动关闭连接
DB->setAutoClose(0);
// ...数据库操作
// 关闭数据库连接
DB->close(1);
}
调试
您可以使用 dump
方法来输出最近一次查询SQL:
printf(DB->dump());
调试输出结果类似以下:
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
db_host = 127.0.0.1
db_db = mud
db_user = root
db_handle = 1
db_error = 0
db_table = topics
db_table_column = ({ /* sizeof() == 2 */
"user_id",
"title"
})
db_sql = SELECT user_id,title FROM topics WHERE user_id > '7' AND category_id='4'
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
如果你只是简单查询,可以通过继承CORE_DB
的方式,而不需要用 new()
方法生成数据库连接对象,示例如下:
inherit CORE_DB;
void test()
{
mixed res;
/**
* @brief 配置数据库连接
*
*/
mapping db = ([
"host":"127.0.0.1",
"database":"mud",
"user":"root"
]);
DB::setConnection(db);
// 获取 users 表的所有结果
res = DB::table("users")->get();
printf("%O", res);
}