A case where MySQL’s implicit conversion causes strange phenomena

A colleague asked a MySQL question, and the phenomenon is indeed strange. It roughly means that the data in the select table, the where condition is "a=0", where the a field is of varchar type, and there are NULL and records containing characters in this field, but there is no " 0" records, and then execute SQL, the returned records are exactly all records containing characters. There are obviously no 0 value records, but they can be returned, and they are regular. What is this phenomenon?

select * from test where a = 0;

For comparison and illustration, we used MySQL, Oracle and SQL Server for simulation respectively.

(1) MySQL statements for creating tables and inserting data,

create table test (id int, a varchar(3000), b varchar(2000));
insert into test values(1, '测试a', '测试b'),(2, NULL, '测试');

(2) Oracle statements for creating tables and inserting data,

create table test (id NUMBER(1), a varchar2(3000), b varchar2(2000));
insert into test values(1, '测试a', '测试b');
insert into test values(2, NULL, '测试');

(3) SQL Server statements to create tables and insert data,

create table test (id numeric(1,0), a varchar(3000), b varchar(2000));
insert into test values(1, '测试a', '测试b');
insert into test values(2, NULL, '测试');

The records returned by the test table should all be,

11ca699953fdc868a18e323b1a90ae0e.png

Let’s take a look at what we get when we execute the following statements in all three databases:

select * from test where a = 0;

(1) MySQL execution returns the following records with characters, but in actual logic, it must be wrong.

45c21377a4e0559d0b7344f63db24005.png

When executed, a warning will also be thrown.

Truncated incorrect DOUBLE value: '测试a'

(2) Oracle directly reports an error, prompting "invalid number", because a is varchar2 and 0 is a number, so the error is for field a. A needs to be converted into a number, but characters cannot be converted into numbers, so the prompt " invalid digit" is reasonable,

ORA-01722: 无效数字

(3) SQL Server will directly report an error when executing, but the prompt information will be clearer. What it means is that the value of field a "test a" cannot be converted into an int value type.

SQL 错误 [245] [S0001]: 在将 varchar 值 '测试a' 转换成数据类型 int 时失败。

Through the above comparison, we can know that Oracle and SQL Server will automatically convert the character type into a numeric type for the "character type = numeric type" condition. If it cannot be converted into a numeric type due to value problems, an error will be prompted, and SQL The prompts given by Server are more specific than Oracle.

In contrast, MySQL not only can execute the "character type = numeric type" condition, but the execution is wrong, which is very frustrating. After all, for a product, avoiding errors may be more important than appearing to perform, but on this issue, Oracle and SQL Server can be said to be superior.

Why does MySQL give wrong results here?

From these paragraphs of official documents, we can get some clues,

https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html

2c35856abdfbcf7e514669503ad51d7e.png

Converting varchar to int in MySQL will automatically truncate the string. For example, "1 test" will be truncated into "1". Through the following judgment, it can be proved that,

bisal@mysqldb 23:26:  [test]> select 1="1测试a";
+--------------+
| 1="1测试a"   |
+--------------+
|            1 |
+--------------+
1 row in set, 1 warning (0.00 sec)

In the above example, "test a" will be cut into "", and "" and 0 are equal, so records with all fields that are not empty will be returned.

bisal@mysqldb 23:27:  [test]> select 0="测试a";
+-------------+
| 0="测试a"   |
+-------------+
|           1 |
+-------------+
1 row in set, 1 warning (0.00 sec)

This problem can be further proved by comparing 0 and "",

bisal@mysqldb 23:29:  [test]> select 0="";
+------+
| 0="" |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

Therefore, it is precisely because MySQL truncates and then converts strings when implicitly converting them, instead of databases like Oracle and SQL Server directly reporting errors for this problem, that this weird problem occurs.

I don't know what the considerations are for this design, but this kind of "fault tolerance" is not desirable, after all, the wrong result set is returned.

Of course, this problem is also related to the use of data types. "a=0" in the SQL condition is actually "varchar=int", and the types on both sides are inconsistent, which leads to implicit conversion of the database. It may be a problem with the database design (field It should be int, but it is defined as varchar), and it may also be a problem of the developer (the SQL condition rvalue should use character type, such as "0", but in fact 0 of int numerical type is used), if according to the database design The requirements of the development specifications strictly ensure that the data types on both sides of the "=" sign are consistent, which will not trigger implicit conversion of the database.

If you think this article is helpful, please feel free to click "Like" and "Reading" at the end of the article, or forward it directly to pyq,

5b5138e21016454efb5e37cdd0e4c1c8.png

Recently updated articles:

" A SQL scenario where indexing is still very slow in MySQL "

" What is "BRICS"?

" Some Problems Encountered Recently "

" Exploration of MySQL Client Instructions Usage "

" MySQL Runtime Observability "

Recent hot articles:

" Recommend a classic paper on Oracle RAC Cache Fusion "

" The shock that the open source code of the "Red Alert" game brings to us "

Article classification and indexing:

" Classification and Indexing of 1,200 Public Account Articles "

Guess you like

Origin blog.csdn.net/bisal/article/details/132613658