सीलिंग के लिए यूनियन कास्टिंग पूर्णांक के साथ समस्या (दशमलव)


10

मेरे पास यह परिदृश्य है, ऐसा लगता है कि 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 का उपयोग कर रहा हूं , बैचों में परिवर्तन को बचाने के लिए, विशेष रूप से विधि संदर्भ। BulkSaveChanges ();; ।


1
20 किसी तरह 9.9 हो जाता है ?! यह सही नहीं लगता।
dbdemon

2
DBFiddle पर MySQL 8.0 एक ही बकवास दिखाता है: dbfiddle.uk/…
dezso

और भी भ्रामक ... SELECT 20 UNION SELECT null UNION SELECT 40 UNION SELECT 4.3;ठीक काम करता है
इवान कैरोल

Pls उस पोस्ट को आउटपुट करें जिसकी आपको आवश्यकता है। साथ ही, आपके द्वारा उत्पन्न कोड पर कितना नियंत्रण है: उदाहरण के लिए क्या आप 20 से 20.0 का प्रकार, या 2.2 से 2 के प्रकार को बदल सकते हैं?
Qsigma

मैंने अब और संदर्भ जोड़ा, मेरे मामले में एक संभावित समाधान कोड में मूल्य को 20.0 करने के लिए मजबूर करना है, मैंने समस्या का परीक्षण किया और ठीक किया, लेकिन यह एक बग जैसा दिखता है क्योंकि केवल उस विशिष्ट परिदृश्य में होता है जहां नल शामिल है और में वह आदेश।
ngcbassman

जवाबों:


9

मेरे लिए एक बग की तरह दिखता है और मैं इस अजीब व्यवहार की पुष्टि कर सकता हूं:

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;

@ इवान कैरोल के जवाब में टिप्पणियों को पढ़ने के बाद आगे की टिप्पणियों

select 20 union select null union select 2;
+------+
| 20   |
+------+
|   20 |
| NULL |
|    2 |
+------+

ठीक है, इंट वैल्यू का उपयोग करने से त्रुटि उत्पन्न नहीं होती है।

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'),)

अजीब तरह से पर्याप्त त्रुटि गायब हो जाती है अगर नल पहले या आखिरी में ले जाया जाता है:

select null union select 20 union select 9.0;
select 20 union select 9.0 union select null;

+------+
| NULL |
+------+
| NULL |
| 20.0 |
| 9.0  |
+------+

यदि नल को पहले रखा गया है, तो परिणामी प्रकार दशमलव (20,1) है। यदि शून्य को अंतिम परिणाम के रूप में रखा गया है तो दशमलव (3,1) है

यदि दूसरा पैर यूनियन में जोड़ा जाता है, तो त्रुटि भी गायब हो जाती है:

select 20 union select 6 union select null union select 9.0;
+------+
| 20   |
+------+
| 20.0 |
| 6.0  |
| NULL |
| 9.0  |
+------+

परिणामी प्रकार दशमलव (20,1)

बीच में एक और अशक्त जोड़ना त्रुटि को बरकरार रखता है:

select 20 union select null union select null union select 9.0;
+------+
| 20   |
+------+
| 9.9  |
| NULL |
| 9.0  |
+------+

लेकिन शुरुआत में एक अशक्त जोड़ना इसे ठीक करता है:

select null union select 20 union select null union select null union select 9.0;
+------+
| NULL |
+------+
| NULL |
| 20.0 |
| 9.0  |
+------+

जैसा कि उम्मीद है कि पहले मूल्य दशमलव (3,1) काम करता है।

अंत में, दशमलव (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)

1
CAST to DOUBLE MySQL में एक सिंटैक्स त्रुटि है। इसके बजाय एक दशमलव काम करता है:SELECT CAST(20 AS DECIMAL) AS x UNION SELECT NULL UNION SELECT 2.2;
Qsigma


1
यह प्रतीत होता है कि यह मुद्दा मारियाडीबी 10.3 में तय किया गया है। (मैंने अभी 10.3.6 के साथ परीक्षण किया है, और 10.3.1 को भी काम करना है।)
dbdemon

2
यदि आप 20जैसा निर्दिष्ट करते हैं तो उत्सुकता से कोई समस्या नहीं है 020। व्यवहार MariaDB 10.2 और MySQL 8.0 में समान है । बहुत अधिक लगता है जैसे कि शाब्दिक की लंबाई संयुक्त स्तंभ के प्रकार को प्रभावित करती है। किसी भी घटना में, यह निश्चित रूप से मेरी किताब में एक बग है।
एंड्री एम

1
मैं इस मुद्दे को MySQL 8.0 में बिना नल के भी देख रहा हूं (हालांकि यह MariaDB 10.2 में ठीक काम करता है)। यदि आप एक अग्रणी शून्य या एक गणना
मिक ओ'एचई

5

बग MDEV-15999

Dbdemon द्वारा दायर बग एमडीईवी -15999 ने इसकी सूचना दी। यह 10.3.1 में तय किया गया है।

अजीब MySQL / MariaDB प्रकृति

डॉक्स से,

पहले SELECTकथन के कॉलम नामों का उपयोग लौटाए गए परिणामों के कॉलम नामों के रूप में किया जाता है। प्रत्येक SELECTविवरण के संबंधित पदों में सूचीबद्ध चयनित कॉलम में समान डेटा प्रकार होना चाहिए। (उदाहरण के लिए, पहले स्टेटमेंट द्वारा चुने गए पहले कॉलम में उसी प्रकार का होना चाहिए जैसे कि दूसरे स्टेटमेंट द्वारा चुने गए पहले कॉलम में।)

यदि संबंधित SELECTकॉलम के डेटा प्रकार मेल नहीं खाते हैं, तो UNIONपरिणाम के कॉलम के प्रकार और लंबाई सभी SELECTकथनों द्वारा प्राप्त मूल्यों को ध्यान में रखते हैं ।

इस मामले में, वे सामंजस्य स्थापित करते हैं decimalऔर integerपूर्णांक को बढ़ावा देने के लिए decimalइसे शामिल नहीं कर सकते। मुझे पता है कि यह बहुत ही भयावह है, लेकिन यह उतना ही भयावह है कि यह मूर्खतापूर्ण व्यवहार करता है।

SELECT CAST(20 AS decimal(2,1));
+--------------------------+
| CAST(20 AS decimal(2,1)) |
+--------------------------+
|                      9.9 |
+--------------------------+

जो इस समस्या का मार्ग प्रशस्त करता प्रतीत होता है।


SELECT cast(20 as signed) UNION SELECT null UNION SELECT 2.2 ;एक ही (9.9) गलत परिणाम पैदा करता है। लेकिन अगर हम "अनजाइन" का उपयोग करते हैं तो यह सब ठीक हो जाता है। जाओ आंकड़ा ...
ypercubeᵀᴹ

SELECT -20 UNION SELECT null UNION SELECT 2.2 ;सही ढंग से भी काम करता है, जैसा किSELECT 20. UNION SELECT null UNION SELECT 2.2 ;
एंड्री एम

3
यहाँ मुख्य अंतर्दृष्टि यह है कि MySQL ने एक डेटा प्रकार का चयन किया है जो होल्ड कर सकता है 2.2लेकिन होल्ड करने के लिए बहुत संकीर्ण है 20। आप इसे अंतिम चयन खंड को बदलकर देख सकते हैं CAST(2.2 AS DECIMAL(10,2)), जो 20.0पहली पंक्ति के रूप में देता है (संक्षेप में चल रहा है CAST(20 AS DECIMAL(10,2)))।
IMSoP

1
अजीब बात यह है कि यह सिर्फ डेटा प्रकार पर आधारित नहीं है 2.2। यदि आप कोशिश select 20000 union select null union select 2.22करते हैं 9999.99, तो आप एक में decimal(6,2)। यह मान रखने के लिए हमेशा एक अंक बहुत छोटा होता है
मिक ओ'हिया

1
@ ठीक है हाँ। यदि आप NULLबीच में मूल्य में फेंकते हैं तो यह सटीक 1 लघु की गणना करता है।
सलमान ए
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.