|
90 | 90 | "+ JSON_ARRAY() function, which creates arrays. \n",
|
91 | 91 | "+ JSON_OBJECT() function, which creates objects.\n",
|
92 | 92 | "+ JSON_QUOTE() function, which quotes a string as a JSON value.\n",
|
93 |
| - "\n", |
| 93 | + "+ or you can (CAST anyValue AS JSON). \n", |
94 | 94 | "\n",
|
95 | 95 | "For example:"
|
96 | 96 | ]
|
|
120 | 120 | "execution_count": null,
|
121 | 121 | "metadata": {},
|
122 | 122 | "outputs": [],
|
123 |
| - "source": [] |
| 123 | + "source": [ |
| 124 | + "-- returns \"[1, 2, \\\"abc\\\"]\":\n", |
| 125 | + "SELECT JSON_QUOTE('[1, 2, \"abc\"]');" |
| 126 | + ] |
| 127 | + }, |
| 128 | + { |
| 129 | + "cell_type": "markdown", |
| 130 | + "metadata": {}, |
| 131 | + "source": [ |
| 132 | + "The JSON_TYPE() function allows you to check JSON value types. It should return OBJECT, ARRAY, a scalar type (INTEGER, BOOLEAN, etc), NULL, or an error. For example:" |
| 133 | + ] |
| 134 | + }, |
| 135 | + { |
| 136 | + "cell_type": "code", |
| 137 | + "execution_count": null, |
| 138 | + "metadata": {}, |
| 139 | + "outputs": [], |
| 140 | + "source": [ |
| 141 | + "-- returns ARRAY:\n", |
| 142 | + "SELECT JSON_TYPE('[1, 2, \"abc\"]');\n", |
| 143 | + "\n", |
| 144 | + "-- returns OBJECT:\n", |
| 145 | + "SELECT JSON_TYPE('{\"a\": 1, \"b\": 2}');\n", |
| 146 | + "\n", |
| 147 | + "-- returns an error:\n", |
| 148 | + "SELECT JSON_TYPE('{\"a\": 1, \"b\": 2');" |
| 149 | + ] |
| 150 | + }, |
| 151 | + { |
| 152 | + "cell_type": "markdown", |
| 153 | + "metadata": {}, |
| 154 | + "source": [ |
| 155 | + "The JSON_VALID() function returns 1 if the JSON is valid or 0 otherwise:" |
| 156 | + ] |
| 157 | + }, |
| 158 | + { |
| 159 | + "cell_type": "code", |
| 160 | + "execution_count": null, |
| 161 | + "metadata": {}, |
| 162 | + "outputs": [], |
| 163 | + "source": [ |
| 164 | + "-- returns 1:\n", |
| 165 | + "SELECT JSON_TYPE('[1, 2, \"abc\"]');\n", |
| 166 | + "\n", |
| 167 | + "-- returns 1:\n", |
| 168 | + "SELECT JSON_TYPE('{\"a\": 1, \"b\": 2}');\n", |
| 169 | + "\n", |
| 170 | + "-- returns 0:\n", |
| 171 | + "SELECT JSON_TYPE('{\"a\": 1, \"b\": 2');" |
| 172 | + ] |
| 173 | + }, |
| 174 | + { |
| 175 | + "cell_type": "markdown", |
| 176 | + "metadata": {}, |
| 177 | + "source": [ |
| 178 | + "Attempting to insert an invalid JSON document will raise an error and the whole record will not be inserted/updated. \n", |
| 179 | + "\n", |
| 180 | + "### Searching JSON Data\n", |
| 181 | + "\n", |
| 182 | + "The JSON_CONTAINS() function accepts the JSON document being searched and another to compare against. It returns 1 when a match is found. For example:" |
| 183 | + ] |
| 184 | + }, |
| 185 | + { |
| 186 | + "cell_type": "code", |
| 187 | + "execution_count": null, |
| 188 | + "metadata": {}, |
| 189 | + "outputs": [], |
| 190 | + "source": [ |
| 191 | + "-- all books with the 'JavaScript' tag:\n", |
| 192 | + "SELECT * FROM `book` WHERE JSON_CONTAINS(tags, '[\"JavaScript\"]');" |
| 193 | + ] |
| 194 | + }, |
| 195 | + { |
| 196 | + "cell_type": "markdown", |
| 197 | + "metadata": {}, |
| 198 | + "source": [ |
| 199 | + "The similar JSON_SEARCH() function returns the path to the given match or NULL when there’s no match. It’s passed the JSON document being searched, 'one' to find the first match, or 'all' to find all matches, and a search string (where % matches any number of characters and _ matches one character in an identical way to LIKE). For example:" |
| 200 | + ] |
| 201 | + }, |
| 202 | + { |
| 203 | + "cell_type": "code", |
| 204 | + "execution_count": null, |
| 205 | + "metadata": {}, |
| 206 | + "outputs": [], |
| 207 | + "source": [ |
| 208 | + "-- all books with tags starting 'Java':\n", |
| 209 | + "SELECT * FROM `book` WHERE JSON_SEARCH(tags, 'one', 'Java%') IS NOT NULL;" |
| 210 | + ] |
| 211 | + }, |
| 212 | + { |
| 213 | + "cell_type": "markdown", |
| 214 | + "metadata": {}, |
| 215 | + "source": [ |
| 216 | + "### JSON Paths\n", |
| 217 | + "\n", |
| 218 | + "A JSON path targets values and can be used to extract or modify parts of a JSON document. The JSON_EXTRACT() function demonstrates this by extracting one or more values:" |
| 219 | + ] |
| 220 | + }, |
| 221 | + { |
| 222 | + "cell_type": "code", |
| 223 | + "execution_count": null, |
| 224 | + "metadata": {}, |
| 225 | + "outputs": [], |
| 226 | + "source": [ |
| 227 | + "-- returns \"SitePoint\":\n", |
| 228 | + "SELECT JSON_EXTRACT('{\"id\": 1, \"website\": \"SitePoint\"}', '$.website');" |
| 229 | + ] |
| 230 | + }, |
| 231 | + { |
| 232 | + "cell_type": "markdown", |
| 233 | + "metadata": {}, |
| 234 | + "source": [ |
| 235 | + "All path definitions start with a $ followed by other selectors:\n", |
| 236 | + "\n", |
| 237 | + "+ a period followed by a name, such as $.website\n", |
| 238 | + "+ [N] where N is the position in a zero-indexed array\n", |
| 239 | + "+ the .[*] wildcard evaluates all members of an object\n", |
| 240 | + "+ the [*] wildcard evaluates all members of an array\n", |
| 241 | + "+ the prefix**suffix wildcard evaluates to all paths that begin with the named prefix and end with the named suffix\n", |
| 242 | + "\n", |
| 243 | + "The following examples refer to the following JSON document:" |
| 244 | + ] |
| 245 | + }, |
| 246 | + { |
| 247 | + "cell_type": "code", |
| 248 | + "execution_count": null, |
| 249 | + "metadata": {}, |
| 250 | + "outputs": [], |
| 251 | + "source": [ |
| 252 | + "{\n", |
| 253 | + " \"a\": 1,\n", |
| 254 | + " \"b\": 2,\n", |
| 255 | + " \"c\": [3, 4],\n", |
| 256 | + " \"d\": {\n", |
| 257 | + " \"e\": 5,\n", |
| 258 | + " \"f\": 6\n", |
| 259 | + " }\n", |
| 260 | + "}" |
| 261 | + ] |
| 262 | + }, |
| 263 | + { |
| 264 | + "cell_type": "markdown", |
| 265 | + "metadata": {}, |
| 266 | + "source": [ |
| 267 | + "Example paths:\n", |
| 268 | + "```\n", |
| 269 | + "> $.a returns 1 \n", |
| 270 | + "> $.c returns [3, 4] \n", |
| 271 | + "> $.c[1] returns 4 \n", |
| 272 | + "> $.d.e returns 5 \n", |
| 273 | + "> $**.e returns [5] \n", |
| 274 | + "```" |
| 275 | + ] |
| 276 | + }, |
| 277 | + { |
| 278 | + "cell_type": "markdown", |
| 279 | + "metadata": {}, |
| 280 | + "source": [ |
| 281 | + "### Extracting JSON Paths in Queries\n", |
| 282 | + "\n", |
| 283 | + "You could extract the name and first tag of your book table using the query:" |
| 284 | + ] |
| 285 | + }, |
| 286 | + { |
| 287 | + "cell_type": "code", |
| 288 | + "execution_count": null, |
| 289 | + "metadata": {}, |
| 290 | + "outputs": [], |
| 291 | + "source": [ |
| 292 | + "SELECT\n", |
| 293 | + " title, tags->\"$[0]\" AS `tag1`\n", |
| 294 | + "FROM `book`;\n" |
| 295 | + ] |
| 296 | + }, |
| 297 | + { |
| 298 | + "cell_type": "markdown", |
| 299 | + "metadata": {}, |
| 300 | + "source": [ |
| 301 | + "For a more complex example, presume you have a user table with JSON profile data. For example:\n", |
| 302 | + " \n", |
| 303 | + "id \tname \tprofile\n", |
| 304 | + "1 \tCraig \t{ “email”: [“[email protected]”, “[email protected]”], “twitter”: “@craigbuckler” }\n", |
| 305 | + "2 \tSitePoint \t{ “email”: [], “twitter”: “@sitepointdotcom” }\n", |
| 306 | + "\n", |
| 307 | + "You can extract the Twitter name using a JSON path. For example:" |
| 308 | + ] |
| 309 | + }, |
| 310 | + { |
| 311 | + "cell_type": "code", |
| 312 | + "execution_count": null, |
| 313 | + "metadata": {}, |
| 314 | + "outputs": [], |
| 315 | + "source": [ |
| 316 | + "SELECT\n", |
| 317 | + " name, profile->\"$.twitter\" AS `twitter`\n", |
| 318 | + "FROM `user`;" |
| 319 | + ] |
| 320 | + }, |
| 321 | + { |
| 322 | + "cell_type": "markdown", |
| 323 | + "metadata": {}, |
| 324 | + "source": [ |
| 325 | + "You could use a JSON path in the WHERE clause to only return users with a Twitter account:" |
| 326 | + ] |
| 327 | + }, |
| 328 | + { |
| 329 | + "cell_type": "code", |
| 330 | + "execution_count": null, |
| 331 | + "metadata": {}, |
| 332 | + "outputs": [], |
| 333 | + "source": [ |
| 334 | + "SELECT\n", |
| 335 | + " name, profile->\"$.twitter\" AS `twitter`\n", |
| 336 | + "FROM `user`\n", |
| 337 | + "WHERE\n", |
| 338 | + " profile->\"$.twitter\" IS NOT NULL;\n" |
| 339 | + ] |
| 340 | + }, |
| 341 | + { |
| 342 | + "cell_type": "markdown", |
| 343 | + "metadata": {}, |
| 344 | + "source": [ |
| 345 | + "### Modifying Part of a JSON Document\n", |
| 346 | + "\n", |
| 347 | + "There are several MySQL functions to modify parts of a JSON document using path notation. These include:\n", |
| 348 | + "\n", |
| 349 | + "+ JSON_SET(doc, path, val[, path, val]...): inserts or updates data in the document\n", |
| 350 | + "+ JSON_INSERT(doc, path, val[, path, val]...): inserts data into the document\n", |
| 351 | + "+ JSON_REPLACE(doc, path, val[, path, val]...): replaces data in the document\n", |
| 352 | + "+ JSON_MERGE(doc, doc[, doc]...): merges two or more document\n", |
| 353 | + "+ JSON_ARRAY_APPEND(doc, path, val[, path, val]...): appends values to the end of an array\n", |
| 354 | + "+ JSON_ARRAY_INSERT(doc, path, val[, path, val]...): inserts an array within the document\n", |
| 355 | + "+ JSON_REMOVE(doc, path[, path]...): removes data from the document\n", |
| 356 | + "\n", |
| 357 | + "You can therefore add a “technical” tag to any book which already has a “JavaScript” tag:" |
| 358 | + ] |
| 359 | + }, |
| 360 | + { |
| 361 | + "cell_type": "code", |
| 362 | + "execution_count": null, |
| 363 | + "metadata": {}, |
| 364 | + "outputs": [], |
| 365 | + "source": [ |
| 366 | + "UPDATE `book`\n", |
| 367 | + " SET tags = JSON_MERGE(tags, '[\"technical\"]')\n", |
| 368 | + "WHERE\n", |
| 369 | + " JSON_SEARCH(tags, 'one', 'JavaScript') IS NOT NULL;\n" |
| 370 | + ] |
| 371 | + }, |
| 372 | + { |
| 373 | + "cell_type": "markdown", |
| 374 | + "metadata": {}, |
| 375 | + "source": [ |
| 376 | + "The MySQL manual provides further information about the [JSON data type](https://dev.mysql.com/doc/refman/en/json.html) and the associated [JSON functions](https://dev.mysql.com/doc/refman//en/json-functions.html).\n", |
| 377 | + "\n", |
| 378 | + "Again, I urge you not to use JSON unless it’s absolutely necessary. You could emulate an entire document-oriented NoSQL database in MySQL, but it would negate many benefits of SQL, and you may as well switch to a real NoSQL system! That said, JSON data types might save effort for more obscure data requirements within an SQL application." |
| 379 | + ] |
124 | 380 | },
|
125 | 381 | {
|
126 | 382 | "cell_type": "code",
|
|
0 commit comments