成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP 批量更新

tunny / 2082人閱讀

摘要:高效方案那么能不能一條語句實(shí)現(xiàn)批量更新呢并沒有提供直接的方法來實(shí)現(xiàn)批量更新,但是可以用點(diǎn)小技巧來實(shí)現(xiàn)。這里使用了這個小技巧來實(shí)現(xiàn)批量更新。不過因?yàn)橛邢薅藯l件,所以只有為這幾條記錄被更新。

mysql更新語句很簡單,更新一條數(shù)據(jù)的某個字段,一般這樣寫:

UPDATE mytable SET myfield = "value" WHERE other_field = "other_value";

如果更新同一字段為同一個值,mysql也很簡單,修改下where即可:

UPDATE mytable SET myfield = "value" WHERE other_field in ("other_values");

這里注意,other_values是一個逗號,分隔的字符串,如:1,2,3

1 常規(guī)方案
那如果更新多條數(shù)據(jù)為不同的值,可能很多人會這樣寫:

foreach ($display_order as $id => $ordinal) {
    $sql = "UPDATE categories SET display_order = $ordinal WHERE id = $id";
    mysql_query($sql);
}

即是循環(huán)一條一條的更新記錄。

一條記錄update一次,這樣性能很差,也很容易造成阻塞。

2 高效方案
那么能不能一條sql語句實(shí)現(xiàn)批量更新呢?

2.1 CASE WHEN
mysql并沒有提供直接的方法來實(shí)現(xiàn)批量更新,但是可以用點(diǎn)小技巧來實(shí)現(xiàn)。

UPDATE mytable SET
    myfield = CASE id
        WHEN 1 THEN "value"
        WHEN 2 THEN "value"
        WHEN 3 THEN "value"
    END
WHERE id IN (1,2,3)

這里使用了case when 這個小技巧來實(shí)現(xiàn)批量更新。

舉個例子:

UPDATE categories SET
    display_order = CASE id
        WHEN 1 THEN 3
        WHEN 2 THEN 4
        WHEN 3 THEN 5
    END
WHERE id IN (1,2,3)

這句sql的意思是,更新display_order 字段:

如果id=1 則display_order 的值為3,
如果id=2 則 display_order 的值為4,
如果id=3 則 display_order 的值為5。
即是將條件語句寫在了一起。

這里的where部分不影響代碼的執(zhí)行,但是會提高sql執(zhí)行的效率。

確保sql語句僅執(zhí)行需要修改的行數(shù),這里只有3條數(shù)據(jù)進(jìn)行更新,而where子句確保只有3行數(shù)據(jù)執(zhí)行。

3.2 更新多值
如果更新多個值的話,只需要稍加修改:

UPDATE categories SET
    display_order = CASE id
        WHEN 1 THEN 3
        WHEN 2 THEN 4
        WHEN 3 THEN 5
    END,
    title = CASE id
        WHEN 1 THEN "New Title 1"
        WHEN 2 THEN "New Title 2"
        WHEN 3 THEN "New Title 3"
    END
WHERE id IN (1,2,3)

到這里,已經(jīng)完成一條mysql語句更新多條記錄了。

但是要在業(yè)務(wù)中運(yùn)用,需要結(jié)合服務(wù)端語言。

3.3 封裝成PHP函數(shù)
在PHP中,我們把這個功能封裝成函數(shù),以后直接調(diào)用。

為提高可用性,我們考慮處理更全面的情況。

如下時需要更新的數(shù)據(jù),我們要根據(jù)idparent_id字段更新post表的內(nèi)容。

其中,id的值會變,parent_id的值一樣。

$data = [
    ["id" => 1, "parent_id" => 100, "title" => "A", "sort" => 1],
    ["id" => 2, "parent_id" => 100, "title" => "A", "sort" => 3],
    ["id" => 3, "parent_id" => 100, "title" => "A", "sort" => 5],
    ["id" => 4, "parent_id" => 100, "title" => "B", "sort" => 7],
    ["id" => 5, "parent_id" => 101, "title" => "A", "sort" => 9],
];

例如,我們想讓parent_id為100、title為A的記錄依據(jù)不同id批量更新:

echo batchUpdate($data, "id", ["parent_id" => 100, "title" => "A"]);

其中,batchUpdate()實(shí)現(xiàn)的PHP代碼如下:

/**
 * 批量更新函數(shù)
 * @param $data array 待更新的數(shù)據(jù),二維數(shù)組格式
 * @param array $params array 值相同的條件,鍵值對應(yīng)的一維數(shù)組
 * @param string $field string 值不同的條件,默認(rèn)為id
 * @return bool|string
 */
function batchUpdate($data, $field, $params = [])
{
   if (!is_array($data) || !$field || !is_array($params)) {
      return false;
   }

    $updates = parseUpdate($data, $field);
    $where = parseParams($params);

    // 獲取所有鍵名為$field列的值,值兩邊加上單引號,保存在$fields數(shù)組中
    // array_column()函數(shù)需要PHP5.5.0+,如果小于這個版本,可以自己實(shí)現(xiàn),
    // 參考地址:http://php.net/manual/zh/function.array-column.php#118831
    $fields = array_column($data, $field);
    $fields = implode(",", array_map(function($value) {
        return """.$value.""";
    }, $fields));

    $sql = sprintf("UPDATE `%s` SET %s WHERE `%s` IN (%s) %s", "post", $updates, $field, $fields, $where);

   return $sql;
}

/**
 * 將二維數(shù)組轉(zhuǎn)換成CASE WHEN THEN的批量更新條件
 * @param $data array 二維數(shù)組
 * @param $field string 列名
 * @return string sql語句
 */
function parseUpdate($data, $field)
{
    $sql = "";
    $keys = array_keys(current($data));
    foreach ($keys as $column) {

        $sql .= sprintf("`%s` = CASE `%s` 
", $column, $field);
        foreach ($data as $line) {
            $sql .= sprintf("WHEN "%s" THEN "%s" 
", $line[$field], $line[$column]);
        }
        $sql .= "END,";
    }

    return rtrim($sql, ",");
}

/**
 * 解析where條件
 * @param $params
 * @return array|string
 */
function parseParams($params)
{
   $where = [];
   foreach ($params as $key => $value) {
      $where[] = sprintf("`%s` = "%s"", $key, $value);
   }
   
   return $where ? " AND " . implode(" AND ", $where) : "";
}

得到這樣一個批量更新的SQL語句:

UPDATE `post` SET `id` = CASE `id` 
WHEN "1" THEN "1" 
WHEN "2" THEN "2" 
WHEN "3" THEN "3" 
WHEN "4" THEN "4" 
WHEN "5" THEN "5" 
END,`parent_id` = CASE `id` 
WHEN "1" THEN "100" 
WHEN "2" THEN "100" 
WHEN "3" THEN "100" 
WHEN "4" THEN "100" 
WHEN "5" THEN "101" 
END,`title` = CASE `id` 
WHEN "1" THEN "A" 
WHEN "2" THEN "A" 
WHEN "3" THEN "A" 
WHEN "4" THEN "B" 
WHEN "5" THEN "A" 
END,`sort` = CASE `id` 
WHEN "1" THEN "1" 
WHEN "2" THEN "3" 
WHEN "3" THEN "5" 
WHEN "4" THEN "7" 
WHEN "5" THEN "9" 
END WHERE `id` IN ("1","2","3","4","5")  AND `parent_id` = "100" AND `title` = "A"

生成的SQL把所有的情況都列了出來。

不過因?yàn)橛蠾HERE限定了條件,所以只有id為1、2、3這幾條記錄被更新。

如果只需要更新某一列,其他條件不限,那么傳入的$data可以更簡單:

$data = [
    ["id" => 1, "sort" => 1],
    ["id" => 2, "sort" => 3],
    ["id" => 3, "sort" => 5],
];
echo batchUpdate($data, "id");

這樣的數(shù)據(jù)格式傳入,就可以修改id從1~3的記錄,將sort分別改為1、3、5。

得到SQL語句:

UPDATE `post` SET `id` = CASE `id` 
WHEN "1" THEN "1" 
WHEN "2" THEN "2" 
WHEN "3" THEN "3" 
END,`sort` = CASE `id` 
WHEN "1" THEN "1" 
WHEN "2" THEN "3" 
WHEN "3" THEN "5" 
END WHERE `id` IN ("1","2","3")

這種情況更加簡單高效。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/28896.html

相關(guān)文章

  • [PDO綁定參數(shù)]使用PHP的PDO擴(kuò)展進(jìn)行批量更新操作

    摘要:方案選擇筆者已知的做批量更新有以下幾種方案逐條更新這種是最簡單的方案,但無疑也是效率最低的方案。類似如下的語句綁定參數(shù)為了防止注入,使用了擴(kuò)展綁定參數(shù)。 最近有一個批量更新數(shù)據(jù)庫表中某幾個字段的需求,在做這個需求的時候,使用了PDO做參數(shù)綁定,其中遇到了一個坑。 方案選擇 筆者已知的做批量更新有以下幾種方案: 1、逐條更新 這種是最簡單的方案,但無疑也是效率最低的方案。 2、CASE ...

    yearsj 評論0 收藏0
  • PHP配上MySQL實(shí)現(xiàn)批量更新插入

    摘要:單數(shù)據(jù)小量數(shù)據(jù)的更新于插入,操作起來簡單,不用太考慮語句怎么書寫。正常來說,按照條件判斷數(shù)據(jù)是否已經(jīng)在表中存在,存在更新,不存在插入。 單數(shù)據(jù)小量數(shù)據(jù)的更新于插入,操作起來簡單,不用太考慮SQL語句怎么書寫。正常來說,按照條件判斷數(shù)據(jù)是否已經(jīng)在表中存在,存在更新,不存在插入。如果是N條數(shù)據(jù)的話,執(zhí)行的SQL語句最大值為2N條。當(dāng)N數(shù)值不大的時候,可以用這種簡單的方式去更新插入。但是當(dāng)N...

    Jiavan 評論0 收藏0
  • 持續(xù)更新,微信公眾號文章批量采集系統(tǒng)的構(gòu)建

    摘要:我從年就開始做微信公眾號內(nèi)容的批量采集,最開始的目的是為了做一個的垃圾內(nèi)容網(wǎng)站。經(jīng)過實(shí)測的微信客戶端在批量采集過程中崩潰率高于安卓系統(tǒng)。在年年初的時候微信公眾號和微信文章開始使用鏈接。 我從2014年就開始做微信公眾號內(nèi)容的批量采集,最開始的目的是為了做一個html5的垃圾內(nèi)容網(wǎng)站。當(dāng)時垃圾站采集到的微信公眾號的內(nèi)容很容易在公眾號里面?zhèn)鞑ァ.?dāng)時批量采集特別好做,采集入口是公眾號的歷史消...

    marek 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<