みんなだいすき
8.0.12とそれ以前はリテラルのみが指定可能、例外として
DEFAULT
がついに関数を指定できるようになった。8.0.12とそれ以前はリテラルのみが指定可能、例外として
TIMESTAMP
, DATETIME
型の CURRENT_TIMESTAMP
のみだった。
記法は
The MySQL 8.0.13 Maintenance Release is Generally Available | MySQL Server Blog に書いてある↓をそのまま試そうとしても、括弧が抜けているので通らない。。
.. DEFAULT ( expression )
で、 DEFAULT
のあとに括弧を入れてから関数なり表現なりを書く。The MySQL 8.0.13 Maintenance Release is Generally Available | MySQL Server Blog に書いてある↓をそのまま試そうとしても、括弧が抜けているので通らない。。
mysql80 40> CREATE TABLE t2 (a BINARY(16) DEFAULT uuid_to_bin(uuid()));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'uuid_to_bin(uuid()))' at line 1
mysql80 40> CREATE TABLE t2 (a BINARY(16) DEFAULT (uuid_to_bin(uuid())));
Query OK, 0 rows affected (0.11 sec)
( ´-`).oO(MySQL Server Teamのブログではまれにだがよくあること
mysql80 40> CREATE TABLE t1 (num serial, val varchar(32), val_len int NOT NULL DEFAULT (CHARACTER_LENGTH(val)));
Query OK, 0 rows affected (0.10 sec)
mysql80 40> INSERT INTO t1 (num, val) VALUES (1, 'one');
Query OK, 1 row affected (0.07 sec)
mysql80 40> SELECT * FROM t1;
+-----+------+---------+
| num | val | val_len |
+-----+------+---------+
| 1 | one | 3 |
+-----+------+---------+
1 row in set (0.00 sec)
しかしこれ迂闊にNOT NULLなカラムのデフォルトにNULLアンセーフな関数とNULLABLEなカラムの値を組み合わせるとおかしなことになった。
mysql80 40> INSERT INTO t1 (num, val) VALUES (2, NULL);
Query OK, 1 row affected, 1 warning (0.06 sec)
mysql80 40> SHOW WARNINGS;
+-------+------+---------------------------------+
| Level | Code | Message |
+-------+------+---------------------------------+
| Error | 1048 | Column 'val_len' cannot be null |
+-------+------+---------------------------------+
1 row in set (0.00 sec)
mysql80 40> SELECT * FROM t1;
+-----+------+---------+
| num | val | val_len |
+-----+------+---------+
| 1 | one | 3 |
| 2 | NULL | 0 |
+-----+------+---------+
2 rows in set (0.00 sec)
CHARACTER_LENGTH(NULL)
は NULL
なので、NOT NULLな val_len
のデフォルト値が NULL
になるというなんか地獄のように矛盾した結果、INT型のフォールバック先である0に落ち着いた様子。
ただこれ
STRICT_TRANS_TABLES
の状態でこの動作になっちゃうのでちょっとあんまり嬉しくない(同じことをデフォルト値を使わずにやるとちゃんとエラーになるのに…)mysql80 40> SELECT @@sql_mode;
+-----------------------------------------------------------------------------------------------------------------------+
| @@sql_mode |
+-----------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql80 40> INSERT INTO t1 (num, val, val_len) VALUES (3, NULL, CHARACTER_LENGTH(NULL));
ERROR 1048 (23000): Column 'val_len' cannot be null
使い道があんまり思いつかない(generated columnでもいいケースがほとんど?)けれど、ブログのサンプルにもあった
uuid_to_bin(uuid())
を使って時間経過順に並ぶ形式にしたUUIDをサロゲートキーにする、とかとても上手く使えそう。
0 件のコメント :
コメントを投稿