Last active
August 11, 2020 08:41
-
-
Save jrunning/4535434 to your computer and use it in GitHub Desktop.
MySQL COALESCE() silently casts its return to the type of subsequent non-NULL arguments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- The MySQL docs say COALESCE() "returns the first non-NULL value in the list, | |
-- or NULL if there are no non-NULL values." This turns out not to be true. | |
-- If the value to be returned is an integer, COALESCE() first casts it to | |
-- the type of a subsequent non-NULL argument. ಠ_ಠ | |
mysql> SELECT 0 = '', | |
-> COALESCE(0, '') = '', | |
-> COALESCE(0, ''), | |
-> COALESCE(0, NULL), | |
-> COALESCE(0, 98.6, NULL), | |
-> COALESCE(0, 50) = '' | |
-> ; | |
+--------+----------------------+-----------------+-------------------+-------------------------+----------------------+ | |
| 0 = '' | COALESCE(0, '') = '' | COALESCE(0, '') | COALESCE(0, NULL) | COALESCE(0, 98.6, NULL) | COALESCE(0, 50) = '' | | |
+--------+----------------------+-----------------+-------------------+-------------------------+----------------------+ | |
| 1 | 0 | 0 | 0 | 0.0 | 1 | | |
+--------+----------------------+-----------------+-------------------+-------------------------+----------------------+ | |
-- ^---(string) (integer) ---^ | |
mysql> SELECT COALESCE('99', 0), | |
-> COALESCE(99, '0') | |
-> ; | |
+-------------------+-------------------+ | |
| COALESCE('99', 0) | COALESCE(99, '0') | | |
+-------------------+-------------------+ | |
| 99 | 99 | | |
+-------------------+-------------------+ | |
-- ^---(string) ^---(string) | |
mysql> SELECT COALESCE(1, 99), | |
-> COALESCE(1, 99.0), | |
-> COALESCE(1, 99.0, 99), | |
-> COALESCE(1, 99, '99'), | |
-> COALESCE(1, '99', 99) | |
-> ; | |
+-----------------+-------------------+-----------------------+-----------------------+-----------------------+ | |
| COALESCE(1, 99) | COALESCE(1, 99.0) | COALESCE(1, 99.0, 99) | COALESCE(1, 99, '99') | COALESCE(1, '99', 99) | | |
+-----------------+-------------------+-----------------------+-----------------------+-----------------------+ | |
| 1 | 1.0 | 1.0 | 1 | 1 | | |
+-----------------+-------------------+-----------------------+-----------------------+-----------------------+ | |
-- (integer)---^ ^---(string) ^---(string) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
COALESCE() turns out to be syntactic sugar for a CASE expression, for which the docs say, "The return type of a CASE expression is the compatible aggregated type of all return values." Good luck finding a definition for that, but it more or less means that it looks at all of the possible return values and picks whatever type they can all be represented in. Other RDBMSes document their "type precedence" but I can't find any such documentation for MySQL.