1. 程式人生 > >YII2.0 查詢構建器 的使用

YII2.0 查詢構建器 的使用

    // DAO(Data Access Object) 資料訪問對
    // 查詢構建器 的使用

    // 主要的好處是:
    //
    // 1, 允許以面向物件方式建立一個複雜的SQL表示式
    // 2,自動引用表明和列名來 防止跟SQL保留關鍵字以及特殊字元的衝突
    // 3,引用引數值,使用引數繫結,從而降低了SQL 注入攻擊的風險。

    $status = isset($_POST['status'])?$_POST['status']:null;


    // 聯合方式 UNION / UNION ALL
    $subQuery_1 = (new Query())->select("id")->from("order");
    $subQuery_2 = (new Query())->select("id")->from("order");

    $subQuery_1->union($subQuery_2,true);// 第二個引數設定 true 則使用 UNION ALL

    $subQuerySql    = $subQuery_1->createCommand()->getRawSql();// 輸出SQL
    $rawSql         = $subQuery_1->createCommand()->rawSql;// SQL語句  已繫結查詢引數 與getRawSql()一樣
    $sql            = $subQuery_1->createCommand()->sql;// SQL語句  引數使用佔位符代替
    $params         = $subQuery_1->createCommand()->params;// 獲取繫結的引數

    $results        = $subQuery_1->all();// 執行查詢

    // 使用子查詢(必須是Query查詢物件) 其結果是: SELECT id FROM ($subQuerySql) AS tmp_table;
    $subSql1 = (new Query())->select('id')->from(['tmp_table' => $subQuery_1]);// tmp_table 是別名
    $subSql2 = (new Query())->select('id')->from('user')->where(['=','username','張三'])->one();

    $query = (new Query())->select('id,username')
        ->from('tableName')
        ->where('1=1');
    $query->addSelect('age');// 追加查詢欄位 SELECT id,username,age
    $query->addSelect(['address,phone']);// SELECT id,username,address,phone



    // JOIN => LEFT / RIGHT / INNER
    $query->join('LEFT JOIN','order','order.user_id = tableName.id');
    $query->leftJoin('order', 'order.user_id = tableName.id');
    $query->leftJoin(['orderList' => $subQuery_2], 'orderList.user_id = tableName.id');// LEFT JOIN ($subQuery_2) AS orderList ON orderList.user_id = tableName.id


    // AND
    $query->andWhere(['in','sub_id',$subSql1]);// AND sub_id IN ($subSql1)
    $query->andWhere(['sub_id',$subSql1]);// AND sub_id IN ($subSql1)
    $query->andWhere(['=','user_id',$subSql2]);// AND user_id = $subSql2

    // AND OR
    $query->andWhere(['and','id=1','id=3']);// AND (id=1 AND id=3)
    $query->andWhere(['or','id=1','id=3']);// AND (id=1 or id=3)
    $query->andWhere(['and','id=1',['or','id=2','id=3']]);// AND id=1 AND (id=2 OR id=3)

    // OR AND
    $query->orWhere(['id' => 1,'username' => 'abc']);// OR ( id=1 AND username='abc' )
    $query->orWhere(['and', ['>','id',10],['username' => 'abc']]);// OR ( id>10 AND username='abc' )


    // 判斷記錄是否存在  EXISTS / NOT EXISTS
    $subQuery_3 = (new Query())->select("id")
        ->from("tableNameSub")
        ->where("tableNameSub.id=tableName.sub_id");
    $query->andWhere(['exists',$subQuery_3]);// EXISTS 第二個引數必須是 Query查詢例項


    // LIKE / AND LIKE / OR LIKE
    $query->andWhere(['like','tableName.name','abc']);// AND tableName.name LIKE '%abc%'
    $query->andWhere(['like','tableName.name','abc%',false]);// AND tableName.name LIKE 'abc%'
    $query->andWhere(['like','tableName.name',['abc','def']]);// AND (tableName.name LIKE '%abc%' AND tableName.name LIKE '%def%')
    $query->andWhere(['like','tableName.name',['abc','def%'],false]);// AND (tableName.name LIKE 'abc' AND tableName.name LIKE 'def%')
    $query->andWhere(['or like','tableName.name',['abc','def']]);// AND (tableName.name LIKE '%abc%' OR tableName.name LIKE '%def%')



    // 繫結查詢引數(過濾使用者輸入,防止SQL 注入的攻擊)
    $query->andWhere('status=:status',[':status' => $status]);
    $query->andWhere('status=:status')->addParams([':status' => $status]);

    // BETWEEN / NOT BETWEEN
    $query->andWhere(['between','id',2,5]);// AND id BETWEEN 2 AND 5


    // andFilterWhere() :會過濾為空的查詢
    $query->andWhere(['username' => '','age' => '22']);// AND username='’AND age=22
    $query->andFilterWhere(['username' => '','age' => '22']);// AND age=22   其中 username=''被過濾

    // ORDER BY
    $query->orderBy(['id' => SORT_ASC, 'username' => SORT_DESC]);
    $query->orderBy('id ASC, username DESC');
    $query->orderBy('id ASC')->addOrderBy('username DESC');// 追加排序方式
    // GROUP BY
    $query->groupBy(['id', 'status']);
    $query->groupBy('id, status');
    $query->groupBy(['id', 'status'])->addGroupBy('age');// 追加分組方式
    // HAVING
    $query->having(['status' => 1]);
    $query->having(['status' => 1])->andHaving(['>', 'age', 30]);// 追加 HAVING 條件
    // LIMIT
    $query->limit(10)->offset(20);// LIMIT 20,10


    // indexBy 查詢結果集的索引
    $query->indexBy('username');// 將把 username 欄位的值作為陣列的鍵名
    $query->indexBy(function($row){ return $row['id'].'-'.$row['username'];});// 將把 id-username 連在一起作為 鍵名


    // 查詢方法
    $query->all();// 所有記錄
    $query->one();// 結果集第一條記錄
    $query->column();// 返回第一列的值
    $query->scalar();// 結果集的第一行第一列的標量值
    $query->exists();// 結果是否存在
    $query->count();// 記錄條數



    // 其他拓展
    // 獲取大量資料時 使用 batch 或 each 方法代替 all 方法
    //(前兩者可以節省時間和記憶體,以前一直認為一次查詢所有資料肯定比分批查詢快,看來我錯了,查詢方式不一樣處理的機制可能不一樣)
    $query = (new Query())->from('user');
    foreach($query->batch() as $user){
        echo $user['username'];
        echo "<br/>";
    }
    foreach($query->each() as $user){
        echo $user['username'];
        echo "<br/>";
    }


    // batchInsert 批量插入資料
    $result = Yii::$app->db->createCommand()
        ->batchInsert('tableName',['username','age'],[
                ['張三','21'],
                ['李四','22'],
                ['王五','25']
            ]
        )->execute();

    // insert 插入單條記錄
    $result = Yii::$app->db->createCommand()
        ->insert("user", ['username' => '將軍','age' => '36'])
        ->execute();