Chinook 資料庫:查詢 EmployeeId=4 負責的所有客戶聯繫資訊。
對應 SQL:
SELECT c.FirstName, c.LastName, c.Address, c.Email
FROM Customer c
INNER JOIN Employee e ON c.SupportRepId = e.EmployeeId
WHERE e.EmployeeId = 4
public function actionIndex() {
$model = [];
$connection = Yii::app()->db;
// 流式介面構建查詢
$command = $connection->createCommand()
->select('c.FirstName, c.LastName, c.Address, c.Email')
->from('Customer c')
->join('Employee e', 'c.SupportRepId = e.EmployeeId')
->where('e.EmployeeId = :eid', [':eid' => 4]);
// 執行查詢
$dataReader = $command->query();
// 映射至模型
foreach ($dataReader as $row) {
$customer = new DataModel();
$customer->firstName = $row['FirstName'];
$customer->lastName = $row['LastName'];
$customer->address = $row['Address'];
$customer->email = $row['Email'];
$model[] = $customer;
}
$this->render('index', ['model' => $model]);
}
| 方法 | 說明 | 範例 |
|---|---|---|
| select($columns) | SELECT 欄位,支援陣列、字串、別名 | select(['id', 'name AS n']) |
| selectDistinct($columns) | SELECT DISTINCT | selectDistinct('category') |
| from($tables) | FROM 表,支援別名、子查詢 | from('User u') |
| where($conditions, $params) | WHERE 條件,支援字串、陣列、運算子 | where(['status'=>1, 'type'=>'post']) |
| andWhere / orWhere | 追加 AND/OR 條件 | andWhere('age>18') |
| join($table, $condition, $params) | INNER JOIN | join('Profile p', 'p.user_id=user.id') |
| leftJoin / rightJoin / crossJoin / naturalJoin | 其他 JOIN 類型 | leftJoin('Post p', 'p.author_id=user.id') |
| group($columns) | GROUP BY | group('category_id') |
| having($conditions, $params) | HAVING | having('COUNT(*) > 5') |
| order($columns) | ORDER BY | order('create_time DESC') |
| limit($limit) | LIMIT | limit(10) |
| offset($offset) | OFFSET | offset(20) |
| union($sql) | UNION 合併查詢 | union($otherCommand) |
$command = $connection->createCommand()->from('Post');
if ($keyword) $command->andWhere(['like', 'title', $keyword]);
if ($category) $command->andWhere(['category_id' => $category]);
if ($dateFrom) $command->andWhere(['>=', 'create_time', $dateFrom]);
if ($dateTo) $command->andWhere(['<=', 'create_time', $dateTo]);
$posts = $command->queryAll();
$subQuery = $connection->createCommand()
->select('author_id')
->from('Post')
->where('status=1')
->group('author_id')
->having('COUNT(*) > 5');
$command = $connection->createCommand()
->select('*')
->from('User')
->where(['in', 'id', $subQuery]);
// 批次 INSERT
$command = $connection->createCommand();
$command->batchInsert('Log', ['level', 'message', 'time'], [
['error', 'Disk full', time()],
['warning', 'High memory', time()],
['info', 'Backup done', time()],
])->execute();
// 批次 UPDATE (Yii 1.1 需自行迴圈或用 DAO)
$sql = $command->getText(); // 含參數佔位符
$params = $command->params; // 參數陣列
// 實際執行 SQL 可用 CDbConnection::getLastQuery() 或啟用 profiling
| 場景 | 推薦 | 理由 |
|---|---|---|
| 簡單 CRUD、關聯導航 | ActiveRecord | 程式碼最少、可讀性最高、內建驗證 |
| 動態查詢條件、部分欄位、無模型 | Query Builder | 程式化構建、自動引用、防注入 |
| 複雜報表、批次操作、存儲過程、鎖表 | DAO | 完全控制 SQL、效能最高 |
`column`。:name 需與 bindValues 鍵名一致 (含冒號)。join() 第二參數若為字串不自動參數化,建議用陣列 ['c.SupportRepId = e.EmployeeId'] 或確保可信來源。createCommand() 只建構,必須呼叫 queryAll()/queryRow()/query()/execute() 才會發送 SQL。