この問題はMySQL 5.7.25に影響しています。
そのため、移行では、レガシーフィールドをテーブルからJSON列に移動します。プロセスのこの部分は正常に機能します。しかし、ロールバックは無残に失敗しています!この時点で、JSONフィールドロジックをSQLからPHPに移動することを検討しています。
次のように問題を再現できます。
_CREATE TABLE `test_table` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`meta` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `test_table` VALUES
(null, '{"test_dt": "2019-03-28 15:43:59", "test_enum": "foo"}'),
(null, '{"test_dt": "2019-03-28 15:44:15", "test_enum": null}'),
(null, '{"test_dt": null, "test_enum": "bar"}');
ALTER TABLE `test_table`
ADD COLUMN `test_enum` ENUM('foo', 'bar') NOT NULL DEFAULT 'foo',
ADD COLUMN `test_dt` DATETIME NULL;
_
次のクエリの回避策はありますか?可能であれば、更新クエリを1つだけにすることをお勧めします...
_-- copy from meta back into legacy fields
UPDATE `test_table` SET
`test_enum` = `meta`->>"$.test_enum",
`test_dt` = CAST(`meta`->>"$.test_dt" AS DATETIME);
_
行2はエラーになります:_Data truncated for column 'test_enum'
_。これは、_meta->>"$.test_enum"
_とJSON_EXTRACT(meta, "$.test_enum")
の両方がNULL
ではなく_"null"
_を返すためと思われます。
Enumフィールドを更新せずにもう一度試してください。
_-- copy from meta back into legacy fields
UPDATE `test_table` SET
`test_dt` = CAST(`meta`->>"$.test_dt" AS DATETIME);
_
行3でエラーが発生するようになりました:_Incorrect datetime value: 'null'
_
クエリを次のように2つに分割すると、エラーを回避できます。
_UPDATE test_table
SET test_enum = `meta`->>"$.test_enum"
WHERE JSON_TYPE(JSON_EXTRACT(`meta`, "$.test_enum")) != 'NULL';
UPDATE test_table
SET test_dt = `meta`->>"$.test_dt"
WHERE JSON_TYPE(JSON_EXTRACT(`meta`, "$.test_dt")) != 'NULL';
_
_"null"
_値のためにENUM関連の列が無効であっても、CASTを介してデータをSELECTすることは正常に機能します。 JSON_EXTRACT()
がNULLを正しく返さないのはなぜですか?
_SELECT
`meta`->>"$.test_enum" AS `test_enum`,
CAST(`meta`->>"$.test_dt" AS DATETIME) AS `test_dt`
FROM test_table
_
_"id","test_enum","test_dt"
1,"foo","2019-03-28 15:43:59"
2,"null","2019-03-28 15:44:15"
3,"bar",NULL
_
現在、MySQLがJSONとCAST/CONVERTメソッドの両方でNULL処理を使用してこのように動作するのはなぜですか。私は明らかな何かを見逃しているように感じます。
string _"2019-03-28 15:43:59"
_は、DATETIME
のように見え、動作します。 CAST()
を使用しないでください。
NULL
NULL
値ではなく、_"NULL"
_は4文字の文字列ですか?つまり、あなたはヌルセルに働きすぎているのですか?