使用 mysql 就不太強,並且寫的複雜SQL可能是 select 查詢語句,最怕複雜的 update 語句了。mysql
因此在這裏總結一下sql
有一張訂單明細表,我須要 更新 明細表裏面的 金額和重量, 這個 更新的依據是 根據 訂單明細表裏面的 某些數據的 來進行 算出來 重量或者金額 來進行更新的。函數
固然 這個訂單明細表 須要根據 訂單主表 來進行查詢出來。spa
首先 第一步 我寫出來的SQL ,看起來也不算複雜.net
UPDATE gwqmshop_process_order_item set total_weight=1*count * ( SELECT units.unitWeight from ( SELECT isrc.total_weight/isrc.count as unitWeight from gwqmshop_process_order_item as isrc where src_order_item_id=isrc.id ) as units ), total_amount=total_weight*price where id in ( SELECT item.id from ( SELECT it.id from gwqmshop_process_order_item as it where it.disabled=0 and it.order_id in ( SELECT o.id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) ) item );
更新的時候 where 語句必須 這樣的寫法, 調試
不然 mysql 就會報錯,由於 mysql 是不能 經過 查詢 自身而後來進行 更新的。code
報錯內容:server
參考地址: https://blog.csdn.net/z_youarethebest/article/details/53785487blog
上面的剛纔我寫的SQL語句, 是沒有報錯, 但是 執行更新以後, 更新的結果都 是 被更新爲 null 了。ci
我這裏是 mysql 5.6 不知道是否是 mysql的bug , 即沒有報錯,又被更新爲 null 了。。。
緣由是 由於 where src_order_item_id=isrc.id 這個語句, 在 mysql 中 是 獲取 不到
訂單明細表 裏面的 src_order_item_id 這個字段內容的。
若是咱們改成 :
where isrc.id=gwqmshop_process_order_item.src_order_item_id
mysql 就會報錯了, 報錯是由於 找不到 gwqmshop_process_order_item 表。
其實無論是 update 語句,仍是 select 語句, 字段 經過 查詢其餘表,可是又須要更加當前查詢的表的內容取管理的話,都是會報錯的。
由於 最外層的表的內容傳不去裏面的 臨時表的。
例子 :
SELECT i.id ,i.src_order_item_id,i.total_amount,i.total_weight,i.count * ( SELECT isrc.total_weight/isrc.count from gwqmshop_process_order_item isrc where isrc.id =i.src_order_item_id ) from gwqmshop_process_order_item i where i.disabled=0 and i.order_id in ( SELECT o.id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) ; 上面的語句確定是沒有問題的,若是改動一下就有問題了 SELECT i.id ,i.src_order_item_id,i.total_amount,i.total_weight,i.count * ( SELECT units.unitWeight from (SELECT isrc.total_weight/isrc.count as unitWeight from gwqmshop_process_order_item isrc where isrc.id =i.src_order_item_id ) as units ) from gwqmshop_process_order_item i where i.disabled=0 and i.order_id in ( SELECT o.id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) ; 而後就會報錯 : Unknown column 'i.src_order_item_id' in 'where clause' 那爲何更新的時候不能使用第一種的方式呢? UPDATE gwqmshop_process_order_item set gwqmshop_process_order_item.total_weight=1*gwqmshop_process_order_item.count * ( SELECT isrc.total_weight/isrc.count as unitWeight from gwqmshop_process_order_item as isrc where isrc.id=gwqmshop_process_order_item.src_order_item_id ), gwqmshop_process_order_item.total_amount=gwqmshop_process_order_item.total_weight*gwqmshop_process_order_item.price where gwqmshop_process_order_item.id in ( SELECT item.id from ( SELECT it.id from gwqmshop_process_order_item as it where it.disabled=0 and it.order_id in ( SELECT o.id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) ) item ); 上面的更新語句就會爆錯,仍是以前的錯誤,不能經過查詢 自身來更新 報錯: You can't specify target table 'gwqmshop_process_order_item' for update in FROM clause
上面的辦法都不能成功,而後我也亂寫了一通,都搞不定,,,都本身的錯,寫代碼寫出BUG了,必須執行更新語句,,,本身的坑,本身填。。。
網上亂看,而後 本身亂寫,亂調試:
最終解決update SQL語句:
UPDATE gwqmshop_process_order_item,gwqmshop_process_order_item units set gwqmshop_process_order_item.total_weight=1*gwqmshop_process_order_item.count * (units.total_weight/units.count), gwqmshop_process_order_item.total_amount=gwqmshop_process_order_item.total_weight*gwqmshop_process_order_item.price where gwqmshop_process_order_item.id in ( SELECT item.id from ( SELECT it.id from gwqmshop_process_order_item as it where it.disabled=0 and it.order_id in ( SELECT o.id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) ) item ) and units.id = gwqmshop_process_order_item.src_order_item_id;
原來只須要 update 的是, 再 來一個自身表 便可。
由於以前 沒有這樣想是由於 感受多是 會 報錯,由於查詢了自身表又更新了。。。
- You can't specify target table 'gwqmshop_process_order_item' for update in FROM clause
由於沒有報錯,能夠成功是由於 mysql 的 底層區分開了吧。
gwqmshop_process_order_item,gwqmshop_process_order_item units 可能就是兩個 不會產生關聯的表吧。
2. update 執行,使用SUM() 函數
訂單明細表,已經更新了 重量和金額了,那麼 還須要 更新 訂單主表啊,由於訂單主表也有 總的 重量和金額。。。
看起來挺簡單,更加明細表求和,更加便可。
估計你們通常會這樣寫:
## 再更新訂單的 總理論重量和總理論價格 update gwqmshop_process_order set total_weight =( sum( SELECT it1.total_weight from gwqmshop_process_order_item as it1 where it1.order_id=id and it1.disabled=0 ) ), set total_price=( sum( SELECT it2.total_amount from gwqmshop_process_order_item as it2 where it2.order_id=id and it2.disabled=0 ) ) where id in ( SELECT mo.id from ( SELECT o.id as id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) as mo );
可是 執行以後 報錯:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT it1.total_weight from gwqmshop_process_order_item as it1
where it1.ord' at line 4
語法錯誤,什麼鬼,,,沒有錯誤啊。反正就是不行。
看不問題,我試着簡化一下SQL:
update gwqmshop_process_order , gwqmshop_process_order_item it1 set gwqmshop_process_order.total_weight =sum(it1.total_weight) where gwqmshop_process_order.id in ( SELECT mo.id from ( SELECT o.id as id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) as mo ) and it1.order_id=gwqmshop_process_order.id and it1.disabled=0 ;
就爆出來 :
Invalid use of group function
看起來 感受是 使用不了 sum 函數啊。。。
想一想也是, sum 函數也算分組函數吧,分組求和的。。。
咱們通常使用 sum 函數都是 在 select 語句中的, 沒有這樣直接使用的。。。
因此要改一下, 隨便試了一下,沒成功, 去百度看看
能夠參考: https://stackoverflow.com/questions/653826/update-with-sum-in-mysql
UPDATE Table_NAme SET PAR= summedValue FROM TAble_NAME t JOIN ( SELECT ID, SUM(S_val) as summedvalue FROM TABLE_NAME GROUP BY ID ) s on t.ID = s.ID
這樣子 感受 好像行的通, 但是怎麼使用MYSQL 寫出來?
試着用join 關聯: update gwqmshop_process_order , inner join ( SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwqmshop_process_order_item.total_weight) as sumweight from gwqmshop_process_order_item where gwqmshop_process_order_item.disabled=0 ) as itsum on itsum.order_id=gwqmshop_process_order.id set gwqmshop_process_order.total_weight =itsum.sumweight where gwqmshop_process_order.id in ( SELECT mo.id from ( SELECT o.id as id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) as mo ) ; 報錯。。。 check the manual that corresponds to your MySQL server version for the right syntax to use near 'inner join ( SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwq' at line 2 試試下面的: update gwqmshop_process_order , ( SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwqmshop_process_order_item.total_weight) as sumweight from gwqmshop_process_order_item GROUP BY gwqmshop_process_order_item.order_id ) as itsum left JOIN itsum itsum1 on itsum1.order_id=gwqmshop_process_order.id set gwqmshop_process_order.total_weight =itsum1.sumweight where gwqmshop_process_order.id in ( SELECT mo.id from ( SELECT o.id as id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) as mo ) ; Table 'yxshop.itsum' doesn't exist 報錯,仍是不行。
最終解決辦法:
因而使用下面的: update gwqmshop_process_order , ( SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwqmshop_process_order_item.total_weight) as sumweight, sum(gwqmshop_process_order_item.total_amount) as sumamount from gwqmshop_process_order_item GROUP BY gwqmshop_process_order_item.order_id ) as itsum set gwqmshop_process_order.total_weight =itsum.sumweight, gwqmshop_process_order.total_price=itsum.sumamount where gwqmshop_process_order.id in ( SELECT mo.id from ( SELECT o.id as id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00' ) as mo ) and itsum.order_id=gwqmshop_process_order.id ;
上面的SQL在 mysql 5.6 下面沒有問題,
可是在 mysql5.7 下面就報錯:
You can't specify target table 'gwqmshop_process_order' for update in FROM clause
也是奇怪,還好生產環境使用 mysql5.6
mysql 5.7 的報錯,不知道是否是BUG,否則爲何mysql5.6 沒事?
並且從報錯的角度來看,,,不知道怎麼會出現這樣錯誤??
我也不還知道怎麼辦了
由於
update gwqmshop_process_order
set total_price=total_price
where
id in
(
SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
) as mo
)
;
這樣子在 mysql 5.7 下面行不通,
有最笨的方式就是 拼出來 執行的全部的 update SQL,
先把 全部的訂單ID查詢出來,而後根據訂單id 去更新了,
也就是 不採用批量更新了,採用 單表更新了。