从 MySQL 版本 5.7.13 开始,假设您希望最终结果为
{"test1": "Test 1", "test2": {"test3": "Test 3"}}
在您的示例中attributes
,正在更新的列设置为{"test1": "Test 1"}
查看您的初始UPDATE
查询,我们可以看到$.test2.test3
不存在。所以不能设置为
JSON_SET() 在 JSON 文档中插入或更新数据并返回结果。如果任何参数为 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
,并且它保持不变,因此可以从查询中省略那些未修改的属性。