Mysql
聯合將整數轉換為天花板的問題(十進制)
我有這種情況,看起來 MySQL 正在採用最大的十進制值並嘗試將其他值轉換為該值。
問題是這個查詢是由一個外部庫生成的,所以我無法控制這個程式碼,至少在這個級別。你知道如何解決這個問題嗎?
SELECT 20 AS x UNION SELECT null UNION SELECT 2.2; +------+ | x | +------+ | 9.9 | -- why from 20 to 9.9 | NULL | | 2.2 | +------+
預期結果
+------+ | x | +------+ | 20 | -- or 20.0, doesn't matter really in my case | NULL | | 2.2 | +------+
添加更多上下文,我使用帶有擴展庫http://entityframework-extensions.net/的實體框架 6來批量保存更改,特別是方法 context.BulkSaveChanges();,該庫使用“選擇聯合”創建查詢.
對我來說看起來像一個錯誤,我可以確認這種令人費解的行為:
10.2.14-MariaDB
如果可能的話,您可以將整數值轉換為雙精度值:
SELECT cast(20 as double) UNION SELECT null UNION SELECT 2.2;
或者先確保你有雙精度值:
SELECT 2.2 UNION SELECT null UNION SELECT 22;
閱讀@Evan Carroll 回答中的評論後的進一步觀察
select 20 union select null union select 2; +------+ | 20 | +------+ | 20 | | NULL | | 2 | +------+
好的,使用 int 值似乎不會產生錯誤。
select 20 union select null union select 9.0; +------+ | 20 | +------+ | 9.9 | | NULL | | 9.0 | +------+
錯誤:似乎輸出是十進制(2,1)
create table tmp as select * from (select 20 as x union select null union select 9.0) as t describe tmp; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | x | decimal(2,1) | YES | | NULL | | +-------+--------------+------+-----+---------+-------+
該錯誤並非孤立於命令行界面,它也存在於 python2-mysql-1.3.12-1.fc27.x86_64 中:
>>> import MySQLdb >>> db = MySQLdb.connect(host="localhost", user="*****", passwd="*****", db="test") >>> cur = db.cursor() >>> cur.execute("SELECT 20 union select null union select 2.2") 3L >>> for row in cur.fetchall() : ... print row ... (Decimal('9.9'),) (None,) (Decimal('2.2'),)
奇怪的是,如果 null 首先或最後移動,錯誤就會消失:
select null union select 20 union select 9.0; select 20 union select 9.0 union select null; +------+ | NULL | +------+ | NULL | | 20.0 | | 9.0 | +------+
如果首先放置 null,則結果類型為小數 (20,1)。如果最後放置 null,則結果類型為小數(3,1)
如果將另一條腿添加到聯合中,該錯誤也會消失:
select 20 union select 6 union select null union select 9.0; +------+ | 20 | +------+ | 20.0 | | 6.0 | | NULL | | 9.0 | +------+
結果類型小數(20,1)
在中間添加另一個 null 會保留錯誤:
select 20 union select null union select null union select 9.0; +------+ | 20 | +------+ | 9.9 | | NULL | | 9.0 | +------+
但是在開頭添加一個 null 可以修復它:
select null union select 20 union select null union select null union select 9.0; +------+ | NULL | +------+ | NULL | | 20.0 | | 9.0 | +------+
正如預期的那樣,將第一個值轉換為 decimal(3,1) 有效。
最後,顯式轉換為 decimal(2,1) 會產生相同的錯誤,但會發出警告:
select cast(20 as decimal(2,1)); +--------------------------+ | cast(20 as decimal(2,1)) | +--------------------------+ | 9.9 | +--------------------------+ 1 row in set, 1 warning (0.00 sec)