版本: v2.3.0
select
從資料表中查詢資料。
select($table, $columns)
table [string]
要查詢的資料表名稱。
columns [array/string]
要回傳的欄位。
select($table, $columns, $where)
table [string]
要查詢的資料表名稱。
columns [array/string]
要回傳的欄位。
where [array] (可選)
用於篩選結果集的 WHERE 條件。
select($table, $join, $columns, $where)
table [string]
要查詢的資料表名稱。
join [array]
用於關聯相關資料表的 JOIN 定義;如果不需要 JOIN,可省略此參數。
columns [array/string]
要回傳的欄位。
where [array] (可選)
用於篩選結果集的 WHERE 條件。
回傳值
[array] 回傳查詢結果陣列。
可以在 columns 參數中使用
* 查詢所有欄位,但為了效能與可讀性,建議明確指定實際需要的欄位。$data = $database->select("account", [
"user_name",
"email"
], [
"user_id[>]" => 100
]);
// 範例結果:
// array(
// [0] => array(
// "user_name" => "foo",
// "email" => "foo@bar.com"
// ),
// [1] => array(
// "user_name" => "cat",
// "email" => "cat@dog.com"
// )
// )
foreach ($data as $item) {
echo "使用者:" . $item["user_name"] . " - 電子郵件:" . $item["email"] . "<br/>";
}
// 選取所有欄位。
$data = $database->select("account", "*");
// 選取單一欄位。
$data = $database->select("account", "user_name");
// 範例結果:
// array(
// [0] => "foo",
// [1] => "cat"
// )
使用回呼逐行處理結果
預設情況下,
select() 會先將完整結果集載入記憶體,再以陣列形式回傳。當結果行數較多時,這會顯著增加記憶體占用。如果把
function ($data) {} 這類回呼函式作為 select() 的最後一個參數傳入,Medoo 會在取得每一行後立刻處理,而不是先把整份結果集全部放進記憶體。在處理大型資料集時,這種方法的記憶體效率更高。
$database->select("account", ["name"], function ($data) {
echo $data["name"];
});
$database->select("account", [
"name"
], function ($data) {
echo $data["name"];
});
記憶體占用對比
以下範例比較從 MySQL 資料庫取得和輸出 1,000、5,000 和 20,000 行時的記憶體使用情況。記憶體使用情況透過
memory_get_usage() 來測量。// 方法 1
$database->select("account", ["name"], function ($data) {
echo $data["name"];
});
// 對照方式:
// 方法 2
$data = $database->select("account", ["name"]);
foreach ($data as $item) {
echo $item["name"];
}
| 方法 1 | 方法 2 | |
| 1,000 筆記錄 | 789 KB | 1.2 MB |
| 5,000 筆記錄 | 1.1 MB | 3.3 MB |
| 20,000 筆記錄 | 2.26 MB | 11.1 MB |
表關聯(JOIN)
SQL 的 JOIN 子句用於將多個資料表中的記錄關聯起來。Medoo 提供了更直觀的 JOIN 語法。
- [>] ==> LEFT JOIN
- [<] ==> RIGHT JOIN
- [<>] ==> FULL JOIN
- [><] ==> INNER JOIN
$database->select("post", [
// 定義主資料表與關聯資料表之間的關係。
"[>]account" => ["author_id" => "user_id"]
], [
"post.title",
"account.city"
]);
post 資料表中的 author_id 欄位會對應到 account 資料表中的 user_id 欄位。"[>]account" => ["author_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
如果兩個資料表使用相同的欄位名稱,則可以使用簡寫形式。
"[>]album" => "user_id"
LEFT JOIN "album" USING ("user_id")
如果兩個資料表中有多個欄位名稱相同,也可以將它們作為陣列傳遞。
"[>]photo" => ["user_id", "avatar_id"]
LEFT JOIN "photo" USING ("user_id", "avatar_id")
如果需要多次連接同一個資料表,請為該資料表指定別名。
"[>]account (replier)" => ["replier_id" => "user_id"]
LEFT JOIN "account" AS "replier" ON "post"."replier_id" = "replier"."user_id"
您也可以透過在欄位前加上資料表名稱,來引用先前連接的資料表。
"[>]account" => ["author_id" => "user_id"], "[>]album" => ["account.user_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id" LEFT JOIN "album" ON "account"."user_id" = "album"."user_id"
多個 JOIN 條件
"[>]account" => [ "author_id" => "user_id", "album.user_id" => "user_id" ]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id" AND "album"."user_id" = "account"."user_id"
附加 JOIN 條件
您也可以為連接子句新增邏輯條件。
"[>]comment" => [ "author_id" => "user_id", "AND" => [ "rate[>]" => 50 ] ]
LEFT JOIN "comment" ON "post"."author_id" = "comment"."user_id" AND "rate" > 50
使用 Raw 物件自訂 JOIN 條件
"[>]account" => Medoo::raw("ON <post.author_id> = <account.user_id>")
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
結果對映
您可以自訂回傳資料的結構。對映鍵不必與原始欄位名稱一致,也支援巢狀輸出。
$data = $database->select("post", [
"[>]account" => ["user_id"]
], [
"post.content",
"userData" => [
"account.user_id",
"account.email",
"meta" => [
"account.location",
"account.gender"
]
]
], [
"LIMIT" => [0, 2]
]);
echo json_encode($data);
[
{
"content": "Hello world!",
"userData": {
"user_id": "1",
"email": "foo@example.com",
"meta": {
"location": "New York",
"gender": "male"
}
}
},
{
"content": "Hey everyone",
"userData": {
"user_id": "2",
"email": "bar@example.com",
"meta": {
"location": "London",
"gender": "female"
}
}
}
]
索引對映
如果您在欄位定義中將欄位名稱作為第一個鍵,結果就會依該欄位建立索引。
$data = $database->select("post", [
"user_id" => [
"nickname",
"location",
"email"
]
]);
{
"10": {
"nickname": "foo",
"location": "New York",
"email": "foo@example.com"
},
"12": {
"nickname": "bar",
"location": "New York",
"email": "bar@medoo.in"
}
}
資料型別聲明
您可以明確聲明所選欄位的輸出類型。
// 支援的資料型別:[String | Bool | Int | Number | Object | JSON]
// [String] 是所有輸出值的預設型別。
// [Object] 表示使用 serialize() 序列化並以 unserialize() 還原的 PHP 資料。
// [JSON] 表示有效的 JSON 資料,並會使用 json_decode() 解碼。
$data = $database->select("post", [
"[>]account" => ["user_id"]
], [
"post.post_id",
"profile" => [
"account.age [Int]",
"account.is_locked [Bool]",
"account.userData [JSON]"
]
]);
echo json_encode($data);
[
{
"post_id": "1",
"profile": {
"age": 20,
"is_locked": true,
"userData": ["foo", "bar", "tim"]
}
},
{
"post_id": "2",
"profile": {
"age": 25,
"is_locked": false,
"userData": ["mydata1", "mydata2"]
}
}
]
// 先將物件存入資料庫,之後再取出。
class Foo {
var $bar = "cat";
public function __wakeup()
{
$this->bar = "dog";
}
}
$object_data = new Foo();
$database->insert("account", [
"data" => $object_data
]);
$data = $database->select("account", [
"data [Object]"
]);
echo $data[0]["data"]->bar;
// 在 unserialize() 期間會呼叫物件的 __wakeup() 方法。
// 因此,輸出為「dog」。
別名
您可以為欄位名稱或資料表名稱指定別名。這在 JOIN 查詢中特別有用,可避免名稱衝突並讓輸出更清楚。
$data = $database->select("account", [
"user_id",
"nickname (my_nickname)"
]);
// 範例結果:
// array(
// [0] => array(
// "user_id" => "1",
// "my_nickname" => "foo"
// ),
// [1] => array(
// "user_id" => "2",
// "my_nickname" => "bar"
// )
// )
$data = $database->select("post (content)", [
"[>]account (user)" => "user_id",
], [
"content.user_id (author_id)",
"user.user_id"
]);
// 範例結果:
// array(
// [0] => array(
// "author_id" => "1",
// "user_id" => "321"
// ),
// [1] => array(
// "author_id" => "2",
// "user_id" => "322"
// )
// )
SELECT
"content"."user_id" AS "author_id",
"user"."user_id"
FROM
"post" AS "content"
LEFT JOIN "account" AS "user" USING ("user_id")
DISTINCT
若要將
DISTINCT 關鍵字套用到選取欄位,請在欄位名前加上 @ 前綴。$data = $database->select("account", [
// DISTINCT 會套用到這一欄。
"@location",
"id",
"name",
]);
SELECT DISTINCT "location", "id", "name" FROM "account"
若要對不同值進行計數,請使用原始表達式。
$data = $database->select("account", [
"unique_locations" => Medoo::raw("COUNT(DISTINCT <location>)")
]);
SELECT COUNT(DISTINCT "location") AS "unique_locations" FROM "account"