简体中文
版本: v2.3.0

WHERE 条件语法

某些 Medoo 方法支持传入 $where 参数来筛选记录,其作用类似 SQL 的 WHERE 子句。手写 SQL 条件往往既复杂又容易引入 SQL 注入风险,而 Medoo 提供了结构化、可读性更高的写法来安全构建 WHERE 条件。

基本条件

基本条件易于使用。您还可以将运算符附加到列名以创建更高级的比较,尤其是对于数值。
$database->select("account", "user_name", [
	"email" => "foo@bar.com"
]);
// WHERE email = 'foo@bar.com'

$database->select("account", "user_name", [
	"user_id" => 200
]);
// WHERE user_id = 200

$database->select("account", "user_name", [
	"user_id[>]" => 200
]);
// WHERE user_id > 200

$database->select("account", "user_name", [
	"user_id[>=]" => 200
]);
// WHERE user_id >= 200

$database->select("account", "user_name", [
	"user_id[!]" => 200
]);
// WHERE user_id != 200

$database->select("account", "user_name", [
	"age[<>]" => [200, 500]
]);
// WHERE age BETWEEN 200 AND 500

$database->select("account", "user_name", [
	"age[><]" => [200, 500]
]);
// WHERE age NOT BETWEEN 200 AND 500
[<>][><] 运算符也可以与日期时间值一起使用。
$database->select("account", "user_name", [
	"birthday[<>]" => [date("Y-m-d", mktime(0, 0, 0, 1, 1, 2015)), date("Y-m-d")]
]);

$database->select("account", "user_name", [
	"birthday[><]" => [date("Y-m-d", mktime(0, 0, 0, 1, 1, 2015)), date("Y-m-d")]
]);
WHERE ("birthday" BETWEEN '2015-01-01' AND '2017-01-01')
WHERE ("birthday" NOT BETWEEN '2015-01-01' AND '2017-01-01')
您不仅可以传递单个字符串或数值,还可以传递一个数组。在这种情况下,Medoo 会生成 IN 条件。
$database->select("account", "user_name", [
	"OR" => [
		"user_id" => [2, 123, 234, 54],
		"email" => ["foo@bar.com", "cat@dog.com", "admin@medoo.in"]
	]
]);
WHERE
user_id IN (2,123,234,54) OR
email IN ('foo@bar.com','cat@dog.com','admin@medoo.in')

否定条件

使用 [!] 运算符构建否定比较,例如 !=、NOT IN 和 IS NOT NULL。
$database->select("account", "user_name", [
	"AND" => [
		"user_name[!]" => "foo",
		"user_id[!]" => 1024,
		"email[!]" => ["foo@bar.com", "cat@dog.com", "admin@medoo.in"],
		"city[!]" => null,
		"promoted[!]" => true
	]
]);
WHERE
"user_name" != 'foo' AND
"user_id" != 1024 AND
"email" NOT IN ('foo@bar.com','cat@dog.com','admin@medoo.in') AND
"city" IS NOT NULL AND
"promoted" != 1
您还可以使用 select() 或 get() 的结果作为条件的值。
$database->select("account", "user_name", [
	"user_id" => $database->select("post", "user_id", ["comments[>]" => 40])
]);
WHERE user_id IN (2, 51, 321, 3431)

逻辑条件

逻辑条件描述多个表达式之间的关系。使用 AND 和 OR 构建更复杂的查询。
基本用法
$database->select("account", "user_name", [
	"AND" => [
		"user_id[>]" => 200,
		"age[<>]" => [18, 25],
		"gender" => "female"
	]
]);

// Medoo 默认使用 AND 组合条件。下面的查询与之等价。
$database->select("account", "user_name", [
	"user_id[>]" => 200,
	"age[<>]" => [18, 25],
	"gender" => "female"
]);
WHERE user_id > 200 AND age BETWEEN 18 AND 25 AND gender = 'female'
$database->select("account", "user_name", [
	"OR" => [
		"user_id[>]" => 200,
		"age[<>]" => [18, 25],
		"gender" => "female"
	]
]);
WHERE user_id > 200 OR age BETWEEN 18 AND 25 OR gender = 'female'
嵌套条件
$database->has("account", [
	"AND" => [
		"OR" => [
			"user_name" => "foo",
			"email" => "foo@bar.com"
		],
		"password" => "12345"
	]
]);
WHERE (user_name = 'foo' OR email = 'foo@bar.com') AND password = '12345'

因为 Medoo 使用数组来描述逻辑条件,所以同一个数组中的重复键会互相覆盖。

// 这不会按预期工作。
$database->select("account", '*', [
	"AND" => [
		"OR" => [
			"user_name" => "foo",
			"email" => "foo@bar.com"
		],
		"OR" => [
			"user_name" => "bar",
			"email" => "bar@foo.com"
		]
	]
]);
// [X] SELECT * FROM "account" WHERE ("user_name" = 'bar' OR "email" = 'bar@foo.com')
为了避免键冲突,请在逻辑键名称后附加注释。注释以 # 开头,可以包含任何文本。
$database->select("account", '*', [
	"AND #注释可用于任意 AND 或 OR 逻辑条件" => [
		"OR #第一组条件" => [
			"user_name" => "foo",
			"email" => "foo@bar.com"
		],
		"OR #第二组条件" => [
			"user_name" => "bar",
			"email" => "bar@foo.com"
		]
	]
]);
WHERE (
	("user_name" = 'foo' OR "email" = 'foo@bar.com')
	AND
	("user_name" = 'bar' OR "email" = 'bar@foo.com')
)
列间比较
$database->select("post", [
	"[>]account" => "user_id",
], [
	"post.content"
], [
	// 在完全限定列名上使用运算符比较列,例如 [=]、[>]、[<] 和 [!=]。
	"post.restrict[<]account.age"
]);
WHERE "post"."restrict" < "account"."age"

LIKE 条件

使用 [~] 运算符构建 LIKE 条件。它可以在基本条件和逻辑条件下使用。
// 默认会在关键字两侧自动加上 %,从而执行包含匹配。
$database->select("person", "id", [
	"city[~]" => "lon"
]);
WHERE "city" LIKE '%lon%'
分组匹配
$database->select("person", "id", [
	"city[~]" => ["lon", "foo", "bar"]
]);
WHERE "city" LIKE '%lon%' OR "city" LIKE '%foo%' OR "city" LIKE '%bar%'
否定 LIKE 条件
$database->select("person", "id", [
	"city[!~]" => "lon"
]);
WHERE "city" NOT LIKE '%lon%'
组合 LIKE 条件
$database->select("person", "id", [
	"content[~]" => ["AND" => ["lon", "on"]]
]);
WHERE ("content" LIKE '%lon%' AND "content" LIKE '%on%')
$database->select("person", "id", [
	"content[~]" => ["OR" => ["lon", "on"]]
]);
WHERE ("content" LIKE '%lon%' OR "content" LIKE '%on%')
SQL 通配符
您可以使用 SQL 通配符模式进行更高级的匹配。
$database->select("person", "id", [
	"city[~]" => "%stan" // Kazakhstan, Uzbekistan, Turkmenistan
]);

$database->select("person", "id", [
	"city[~]" => "Londo_" // London, Londox, Londos, ...
]);

$database->select("person", "id", [
	"name[~]" => "[BCR]at" // Bat, Cat, Rat
]);

$database->select("person", "id", [
	"name[~]" => "[!BCR]at" // Eat, Fat, Hat, ...
]);

排序条件

使用 ORDER 对结果集进行排序。
// 按单个列排序。
$database->select("account", "user_id", [
	"ORDER" => "user_id"
]);

// 按多个列排序。
$database->select("account", "user_id", [
	"ORDER" => [
		// 按自定义顺序对某一列排序。
		"user_id" => [43, 12, 57, 98, 144, 1],

		// 使用默认方向按某一列排序。
		"register_date",

		// 按降序排序。
		"profile_id" => "DESC",

		// 按升序排序。
		"date" => "ASC"
	]
]);

全文搜索

MySQL 支持全文搜索,以实现更高级的搜索查询。
搜索模式
natural 自然语言模式
natural+query 在带有查询扩展的自然语言模式
boolean 布尔模式
query 带有查询扩展
// MATCH 条件。
$database->select("post_table", "post_id", [
	"MATCH" => [
		"columns" => ["content", "title"],
		"keyword" => "foo",

		// 可选:搜索模式。
		"mode" => "natural"
	]
]);
WHERE MATCH (content, title) AGAINST ('foo' IN NATURAL LANGUAGE MODE)

正则表达式

使用 [REGEXP] 运算符将值与正则表达式进行匹配。
$data = $database->select('account', [
	'user_id',
	'user_name'
], [
	'user_name[REGEXP]' => '[a-z0-9]*'
]);
WHERE "user_name" REGEXP '[a-z0-9]*'

SQL 函数

在更高级的用法中,您可以通过 raw() 对象使用 SQL 函数。更多说明请参阅 raw 页面。
$data = $database->select('account', [
	'user_id',
	'user_name'
], [
	'datetime' => Medoo::raw('NOW()')
]);
WHERE "datetime" = NOW()

LIMIT 与 OFFSET

使用 LIMIT 限制返回的行数。您还可以指定偏移量。
// 返回前 100 行。
$database->select("account", "user_id", [
	"LIMIT" => 100
]);

// 跳过前 20 行,然后返回接下来的 100 行。
$database->select("account", "user_id", [
	"LIMIT" => [20, 100]
]);

// 对于 Oracle 和 MSSQL,还需要 ORDER BY。
$database->select("account", "user_id", [
	"LIMIT" => [20, 100],
	"ORDER" => "location"
]);

GROUP BY 与 HAVING

使用 GROUP 对行进行分组,并使用 HAVING 过滤分组结果。
// 按单个列分组。
$database->select("account", "user_id", [
	"GROUP" => "type"
]);

// 按多个列分组。
$database->select("account", "user_id", [
	"GROUP" => [
		"type",
		"age",
		"gender"
	]
]);

// 对行进行分组,并过滤分组后的结果。
$database->select("account", "user_id", [
	"GROUP" => "type",
	"HAVING" => [
		"user_id[>]" => 500
	]
]);