Mysql

聯合將整數轉換為天花板的問題(十進制)

  • May 16, 2018

我有這種情況,看起來 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)

引用自:https://dba.stackexchange.com/questions/204757