从 MySQL 5.7.13 版开始,假设您希望得到以下结果
{"test1": "Test 1", "test2": {"test3": "Test 3"}}
在您的示例中,正在更新的 attributes 列设置为 {"test1": "Test 1"}
查看您最初的UPDATE 查询,我们可以看到$.test2.test3 不存在。
所以不能设置为
JSON_SET() 在 JSON 文档中插入或更新数据并返回
结果。如果任何参数为 NULL,则返回 NULL,或者如果给出路径,则返回 NULL
找不到对象。
意思是MySQL可以添加$.test2,但是由于$.test2不是一个对象,所以MySQL不能添加到$.test2.test3。
因此,您需要通过执行以下操作将 $.test2 定义为 json 对象。
mysql> SELECT * FROM testing;
+----+---------------------+
| id | attributes |
+----+---------------------+
| 1 | {"test1": "Test 1"} |
+----+---------------------+
1 row in set (0.00 sec)
mysql> UPDATE testing
-> SET attributes = JSON_SET(
-> attributes,
-> "$.test1", "Test 1",
-> "$.test2", JSON_OBJECT("test3", "Test 3")
-> );
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM testing;
+----+---------------------------------------------------+
| id | attributes |
+----+---------------------------------------------------+
| 1 | {"test1": "Test 1", "test2": {"test3": "Test 3"}} |
+----+---------------------------------------------------+
1 row in set (0.00 sec)
因此,您需要明确告诉 MySQL 该键作为 JSON 对象存在,而不是依赖于 MySQL 点表示法。
这类似于 PHP 如何定义不存在的对象属性值。
$a = (object) ['test1' => 'Test 1'];
$a->test2->test3 = 'Test 3';
//PHP Warning: Creating default object from empty value
要消除错误,您需要先将$a->test2 定义为对象。
$a = (object) ['test1' => 'Test 1'];
$a->test2 = (object) ['test3' => 'Test 3'];
或者,您可以在使用点符号之前测试和创建对象,以设置值。尽管对于较大的数据集,这可能是不可取的。
mysql> UPDATE testing
-> SET attributes = JSON_SET(
-> attributes, "$.test2", IFNULL(attributes->'$.test2', JSON_OBJECT())
-> ),
-> attributes = JSON_SET(
-> attributes, "$.test4", IFNULL(attributes->'$.test4', JSON_OBJECT())
-> ),
-> attributes = JSON_SET(
-> attributes, "$.test4.test5", IFNULL(attributes->'$.test4.test5', JSON_OBJECT())
-> ),
-> attributes = JSON_SET(
-> attributes, "$.test2.test3", "Test 3"
-> );
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM testing;
+----+---------------------------------------------------------------------------+
| id | attributes |
+----+---------------------------------------------------------------------------+
| 1 | {"test1": "Test 1", "test2": {"test3": "Test 3"}, "test4": {"test5": {}}} |
+----+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
尽管在任何一种情况下,如果未提供原始数据,JSON_OBJECT 函数调用都会清空嵌套对象的属性值。但是从上一个JSON_SET 查询中可以看到,$.test1 没有在attributes 的定义中提供,并且它保持不变,因此可以在查询中省略那些未修改的属性。