私はこのシナリオを持っています。MySQLが最大の10進数値を取り、他の値をそれにキャストしようとしているようです。
問題は、このクエリが外部ライブラリによって生成されるため、少なくともこのレベルでは、このコードを制御できません。これを修正する方法を知っていますか?
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/ を使用してEntity Framework 6を使用して、変更をバッチで保存します。具体的には、メソッドcontext.BulkSaveChanges();、このライブラリです。 「select union」を使用してクエリを作成します。
私にはバグのように見え、この不可解な動作は以下で確認できます:
10.2.14-MariaDB
可能であれば、整数値をdoubleにキャストできます。
SELECT cast(20 as double) UNION SELECT null UNION SELECT 2.2;
または、最初にdouble値があることを確認します。
SELECT 2.2 UNION SELECT null UNION SELECT 22;
@Evan Carrollの回答のコメントを読んだ後のさらなる観察
select 20 union select null union select 2;
+------+
| 20 |
+------+
| 20 |
| NULL |
| 2 |
+------+
OK、int値を使用してもエラーは発生しないようです。
select 20 union select null union select 9.0;
+------+
| 20 |
+------+
| 9.9 |
| NULL |
| 9.0 |
+------+
エラー:出力はdecimal(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が最初に配置された場合、結果の型はdecimal(20,1)になります。 nullが最後に配置された場合、結果の型はdecimal(3,1)です。
ユニオンに別のレッグが追加された場合も、エラーは消えます。
select 20 union select 6 union select null union select 9.0;
+------+
| 20 |
+------+
| 20.0 |
| 6.0 |
| NULL |
| 9.0 |
+------+
結果の型decimal(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)
バグ MDEV-15999 提出者 dbdemon がこれを報告しました。 10.3.1で修正されました。
最初の
SELECT
ステートメントの列名は、返される結果の列名として使用されます。 各SELECT
ステートメントの対応する位置にリストされている選択された列は、同じデータ型である必要があります。(たとえば、最初のステートメントは、他のステートメントによって選択された最初の列と同じタイプでなければなりません。)対応する
SELECT
列のデータ型が一致しない場合、UNION
結果の列の型と長さは、すべてのSELECT
ステートメントによって取得された値を考慮に入れます。
この場合、整数をdecimal
に昇格させることで、integer
とdecimal
を調整できます。私はそれが恐ろしいことを知っていますが、同様に恐ろしいのは、このように静かに振る舞うことです。
SELECT CAST(20 AS decimal(2,1));
+--------------------------+
| CAST(20 AS decimal(2,1)) |
+--------------------------+
| 9.9 |
+--------------------------+
これはこの問題への道を開くようです。