<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 背景描述 之前我們遇到一個咨詢,客戶說: 1\. 同一個表,col1=a,col2=b,做 update,set col1=col2,col2=col1,這時候兩個都是b 2\. 不同表,A表 col1=a,B表 col2=b,做 update,就能進行交換 為什么不同表就能交換呢? ## 問題實驗 ### 一張表的測試 ~~~ root@localhost : test 12:36:09> select * from upt; +------+------+ | c1 | c2 | +------+------+ | a | b | +------+------+ 1 row in set (0.03 sec) root@localhost : test 12:36:20> update upt set c1=c2,c2=c1; Query OK, 1 row affected (2 hours 47 min 59.80 sec) Rows matched: 1 Changed: 1 Warnings: 0 root@localhost : test 03:24:32> select * from upt; +------+------+ | c1 | c2 | +------+------+ | b | b | +------+------+ 1 row in set (0.00 sec) ~~~ ### 兩張表的測試 ~~~ root@localhost : test 02:45:13> select * from upt1; +------+------+------+ | c1 | c2 | id | +------+------+------+ | a | b | 1 | | c | d | 2 | +------+------+------+ 2 rows in set (0.00 sec) root@localhost : test 02:45:18> select * from upt2; +------+------+------+ | c1 | c2 | id | +------+------+------+ | e | f | 1 | | g | h | 2 | +------+------+------+ 2 rows in set (0.00 sec) root@localhost : test 02:47:50> update upt1, upt2 set upt1.c1=upt2.c1, upt2.c1=upt1.c1 where upt1.id=upt2.id; Query OK, 4 rows affected (0.04 sec) Rows matched: 4 Changed: 4 Warnings: 0 root@localhost : test 02:48:25> select * from upt1; +------+------+------+ | c1 | c2 | id | +------+------+------+ | e | b | 1 | | g | d | 2 | +------+------+------+ 2 rows in set (0.00 sec) root@localhost : test 02:48:35> select * from upt2; +------+------+------+ | c1 | c2 | id | +------+------+------+ | a | f | 1 | | c | h | 2 | +------+------+------+ 2 rows in set (0.01 sec) ~~~ ## 問題分析 ### 一張表的情況 UPDATE并沒有把c1和c2列的值做交換,而是用c2列的值覆蓋了c1列的值。而如果c1和c2來自不同的表,則會交換值,原因何在呢? 單張表的UPDATE函數入口為?`mysql_uptate()`,函數有兩個參數?`List<Item> &fields,List<Item> &values`分別表示要修改的列,和它們的目標值。 在上面例子中SET子句等號的左邊,依次出現的是c1和c2,所以在fields數組中,順序是field(c1)->field(c2),在SET子句等號的右邊,依次出現的是c2和c1,所以在values數組中,順序是value(c2)->value(c1)。 對于單表UPDATE,MySQL調用了read_record()來讀取values,所以會得到 value(c2).str_value=’b’->value(c1).str_value=’a’。然后在fill_record()中,根據fields的順序依次調用value->save_in_field()來把values填入fields。 因此value(c2)會被首先賦值給field(c1),因此field(c1).str_value=’b’,然后value(c1).str_value此時已經成為了’b’,因此value(c1)復制給filed(c2)依然還是’b’。 我們用三個列來驗證我們的分析 ~~~ root@localhost : test 03:54:55> select * from upt; +------+------+------+ | c1 | c2 | c3 | +------+------+------+ | a | b | c | +------+------+------+ 1 row in set (0.01 sec) root@localhost : test 03:55:05> update upt set c1=c2, c2=c3, c3=c1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 root@localhost : test 03:55:45> select * from upt; +------+------+------+ | c1 | c2 | c3 | +------+------+------+ | b | c | b | +------+------+------+ 1 row in set (0.00 sec) ~~~ 可見,c1被賦值為c2的時候,c2還是’b’,c2被賦值為c3的時候,c3還是’c’。但是當c3被賦值為c1的時候,c1之前已經被賦值為’b’,所以c3也就成了’b’。 ## 兩張表的分析 對于不同表的UPDATE,MySQL調用的是mysql_multi_update(),定義一個multi_update類來處理,最終在?`multi_update::do_updates()`?中進行修改。 這里有什么不同的呢? 通過調研?`multi_update::do_updates()`?函數發現,multi_update類中的copy_field數組暫存了要更新的列值 ~~~ for ( ; *field ; field++) { Item_field *item= (Item_field* ) field_it++; (copy_field_ptr++)->set(item->field, *field, 0); } ~~~ 然后從原表中讀取一行記錄,并存到table->record[1], ~~~ tbl->file->ha_rnd_pos(tbl->record[0], (uchar *) tmp_table->field[field_num]->ptr))) ... store_record(table,record[1]); ~~~ 接著再把暫存的列值拷貝回table->record[0], ~~~ for (copy_field_ptr=copy_field; copy_field_ptr != copy_field_end; copy_field_ptr++) (*copy_field_ptr->do_copy)(copy_field_ptr); ~~~ 最后調用ha_update_row這個API更新這行數據, ~~~ local_error= table->file->ha_update_row(table->record[1], table->record[0]); ~~~ 這樣就不會因為列值被修改,而導致后續利用列值更新其他列的時候值變化了,這就是UPDATE多表和單表邏輯中區別的關鍵。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看