Loading...
MySQL 9.5 Reference Manual 9.5의 13.5 The JSON Data Type의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
MySQL은 JSON document 내 데이터에 효율적으로 접근할 수 있도록 RFC 8259에 의해 정의된 네이티브 JSON (JavaScript Object Notation) 데이터 타입을 지원합니다. JSON 데이터 타입은 문자열 컬럼에 JSON 포맷 문자열을 저장하는 것에 비해 다음과 같은 장점이 있습니다:
JSON 컬럼에 저장되는 JSON document에 대한 자동 유효성 검사. 유효하지 않은 document는 에러를 발생시킵니다.
최적화된 스토리지 포맷. JSON 컬럼에 저장된 JSON document는 내부 포맷으로 변환되어 document 요소에 빠르게 읽기 접근을 할 수 있습니다. 서버가 이후에 이 바이너리 포맷에 저장된 JSON value를 읽을 때, 그 value를 텍스트 표현으로부터 파싱할 필요가 없습니다. 이 바이너리 포맷은 서버가 document 내에서 key나 배열 인덱스로 서브오브젝트 또는 중첩된 value를, 그 이전이나 이후의 모든 value를 읽지 않고 직접 조회할 수 있도록 구조화되어 있습니다.
MySQL은 또한 JSON_MERGE_PATCH() 함수을 사용하여 RFC 7396에 정의된 JSON Merge Patch 포맷도 지원합니다. 예제와 추가 정보를 위해 이 함수의 설명과 Normalization, Merging, and Autowrapping of JSON Values를 참조하십시오.
참고
이 설명에서는 JSON을 모노타입으로 표기할 때는 JSON 데이터 타입을, 일반 폰트로 “JSON”이라고 표기할 때는 일반적인 JSON 데이터를 가리키는 의미로 사용합니다.
JSON document를 저장하는 데 필요한 공간은 LONGBLOB 또는 LONGTEXT와 대략 동일합니다. 자세한 내용은 Section 13.7, “Data Type Storage Requirements”를 참조하십시오. JSON 컬럼에 저장되는 JSON document의 크기는 max_allowed_packet 시스템 변수 값으로 제한된다는 점이 중요합니다. (서버가 내부적으로 메모리에서 JSON value를 조작할 때는 이보다 클 수 있습니다. 이 제한은 서버가 이를 저장할 때 적용됩니다.) JSON document를 저장하는 데 필요한 공간의 양은 JSON_STORAGE_SIZE() 함수를 사용하여 얻을 수 있습니다. JSON 컬럼의 경우, 스토리지 크기—따라서 이 함수가 반환하는 값—는 (이 섹션 후반에서 설명하는 JSON 부분 업데이트 최적화를 참조) 그 컬럼에 대해 수행되었을지 모를 어떠한 부분 업데이트 이전에 컬럼이 사용하던 크기입니다.
JSON 데이터 타입과 함께 JSON value에 대한 생성, 조작, 검색과 같은 연산을 가능하게 하는 SQL 함수 집합도 제공됩니다. 다음 설명에서는 이러한 연산의 예를 보여 줍니다. 각 함수에 대한 자세한 내용은 Section 14.17, “JSON Functions”을 참조하십시오.
GeoJSON value를 대상으로 하는 공간 함수 집합도 제공됩니다. Section 14.16.11, “Spatial GeoJSON Functions”를 참조하십시오.
JSON 컬럼은 다른 바이너리 타입 컬럼과 마찬가지로 직접 인덱스되지 않습니다. 대신, JSON 컬럼에서 스칼라 value를 추출하는 생성 칼럼에 인덱스를 생성할 수 있습니다. 자세한 예제는 Indexing a Generated Column to Provide a JSON Column Index를 참조하십시오.
MySQL 옵티마이저는 또한 JSON 표현식과 일치하는 가상 컬럼에 대한 호환 가능한 인덱스를 찾습니다.
InnoDB 스토리지 엔진은 JSON 배열에 대한 다중 값 인덱스를 지원합니다. Multi-Valued Indexes를 참조하십시오.
MySQL NDB Cluster는 JSON 컬럼과 MySQL JSON 함수를 지원하며, 여기에는 JSON 컬럼을 인덱스 할 수 없는 문제에 대한 우회 방법으로 JSON 컬럼에서 생성된 컬럼에 인덱스를 생성하는 것도 포함됩니다. 하나의 NDB 테이블당 최대 3개의 JSON 컬럼을 지원합니다.
MySQL 9.5에서 옵티마이저는 JSON 컬럼에 대해, 기존 document를 제거하고 전체 새 document를 컬럼에 쓰는 대신 부분, 인플레이스 업데이트를 수행할 수 있습니다. 이 최적화는 다음 조건을 만족하는 업데이트에 대해 수행될 수 있습니다:
업데이트 대상 컬럼이 JSON으로 선언되어 있어야 합니다.
UPDATE 문이 컬럼을 업데이트하기 위해 JSON_SET(), JSON_REPLACE(), JSON_REMOVE() 이 세 함수 중 하나를 사용해야 합니다. 컬럼 값의 직접 대입(예를 들어, UPDATE mytable SET jcol = '{"a": 10, "b": 25}')은 부분 업데이트로 수행될 수 없습니다.
하나의 UPDATE 문에서 여러 JSON 컬럼을 업데이트 하는 경우에도 이 방식으로 최적화될 수 있습니다. MySQL은 값이 위에서 나열한 세 함수를 사용하여 업데이트 되는 컬럼에 대해서만 부분 업데이트를 수행할 수 있습니다.
UPDATE mytable SET jcol1 = JSON_SET(jcol2, '$.a', 100)과 같은 문은 부분 업데이트로 수행될 수 없습니다.이전에 나열한 함수에 대한 중첩 호출은 입력 컬럼과 대상 컬럼이 동일한 한, 어떠한 조합으로든 사용할 수 있습니다.
모든 변경은 기존 배열 또는 오브젝트 value를 새로운 value로 대체해야 하며, 부모 오브젝트나 배열에 새로운 요소를 추가해서는 안 됩니다.
대체되는 value는 대체 후 value보다 최소한 같거나 커야 합니다. 즉, 새 value가 기존 value보다 더 클 수 없습니다.
이 요구 사항에 대한 가능한 예외는, 이전에 부분 업데이트를 수행하여 더 큰 value를 위한 충분한 공간이 남아 있는 경우입니다. JSON_STORAGE_FREE() 함수를 사용하여 JSON 컬럼에 대해 어떤 부분 업데이트에 의해 얼마나 많은 공간이 비워졌는지 확인할 수 있습니다.
이러한 부분 업데이트는 공간을 절약하는 컴팩트 포맷으로 바이너리 로그에 기록될 수 있으며, 이는 binlog_row_value_options 시스템 변수를 PARTIAL_JSON으로 설정하여 활성화할 수 있습니다.
테이블에 저장된 JSON 컬럼 value의 부분 업데이트와 행의 부분 업데이트를 바이너리 로그에 기록하는 것을 구분하는 것이 중요합니다. JSON 컬럼에 대한 전체 업데이트가 바이너리 로그에는 부분 업데이트로 기록될 수 있습니다. 이는 이전 목록의 마지막 두 조건 중 하나(또는 둘 다)가 충족되지 않았지만, 다른 조건들은 만족되는 경우에 발생할 수 있습니다.
binlog_row_value_options에 대한 설명도 참조하십시오.
다음 몇 개 섹션에서는 JSON value의 생성과 조작에 관한 기본 정보를 제공합니다.
JSON 배열은 쉼표로 구분된 value 목록을 포함하며 [ 및 ] 문자로 둘러싸여 있습니다:
1["abc", 10, null, true, false]
JSON 오브젝트는 쉼표로 구분된 key-value pair 집합을 포함하며 { 및 } 문자로 둘러싸여 있습니다:
1{"k1": "value", "k2": 10}
위 예에서 볼 수 있듯이, JSON 배열과 오브젝트는 문자열 또는 숫자인 스칼라 value, JSON null 리터럴, 또는 JSON 불리언 true 또는 false 리터럴을 포함할 수 있습니다. JSON 오브젝트의 key는 반드시 문자열이어야 합니다. 시간(date, time, 또는 datetime) 스칼라 value도 허용됩니다:
1["12:18:29.000000", "2015-07-29", "2015-07-29 12:18:29.000000"]
JSON 배열 요소와 JSON 오브젝트 key value 내에는 중첩이 허용됩니다:
1[99, {"id": "HK500", "cost": 75.99}, ["hot", "cold"]] 2{"k1": "value", "k2": [10, 20]}
MySQL에서 이를 위해 제공되는 여러 함수 (see Section 14.17.2, “Functions That Create JSON Values”) 및 CAST(value AS JSON)을 사용하여 다른 타입의 value를 JSON 타입으로 캐스팅함으로써 JSON value를 얻을 수도 있습니다 (see Converting between JSON and non-JSON values). 다음 몇 단락에서는 MySQL이 입력으로 제공되는 JSON value를 처리하는 방법을 설명합니다.
MySQL에서 JSON value는 문자열로 작성됩니다. MySQL은 JSON value가 필요한 컨텍스트에서 사용되는 모든 문자열을 파싱하며, 유효한 JSON이 아니면 에러를 생성합니다. 이러한 컨텍스트에는 JSON 데이터 타입을 가진 컬럼에 value를 INSERT 하는 경우와, JSON value를 기대하는 함수(보통 MySQL JSON 함수 문서에서 json_doc 또는 _json_val_로 표시됨)에 인자를 전달하는 경우가 포함됩니다. 다음 예에서 이를 확인할 수 있습니다:
JSON 컬럼에 value를 INSERT 하려는 시도는 value가 유효한 JSON value이면 성공하고, 그렇지 않으면 실패합니다:1mysql> CREATE TABLE t1 (jdoc JSON); 2Query OK, 0 rows affected (0.20 sec) 3 4mysql> INSERT INTO t1 VALUES('{"key1": "value1", "key2": "value2"}'); 5Query OK, 1 row affected (0.01 sec) 6 7mysql> INSERT INTO t1 VALUES('[1, 2,'); 8ERROR 3140 (22032) at line 2: Invalid JSON text: 9"Invalid value." at position 6 in value (or column) '[1, 2,'.
“at position N”이라는 문구가 포함된 이러한 에러 메시지에서 position 값은 0-based이지만, 실제로 문제가 발생한 위치를 대략적으로 나타내는 값으로 간주해야 합니다.
JSON_TYPE() 함수는 JSON 인자를 기대하며 이를 JSON value로 파싱하려고 시도합니다. value가 유효하면 그 JSON 타입을 반환하고, 그렇지 않으면 에러를 발생시킵니다:1mysql> SELECT JSON_TYPE('["a", "b", 1]'); 2+----------------------------+ 3| JSON_TYPE('["a", "b", 1]') | 4+----------------------------+ 5| ARRAY | 6+----------------------------+ 7 8mysql> SELECT JSON_TYPE('"hello"'); 9+----------------------+ 10| JSON_TYPE('"hello"') | 11+----------------------+ 12| STRING | 13+----------------------+ 14 15mysql> SELECT JSON_TYPE('hello'); 16ERROR 3146 (22032): Invalid data type for JSON data in argument 1 17to function json_type; a JSON string or JSON type is required.
MySQL은 JSON 컨텍스트에서 사용되는 문자열을 utf8mb4 문자 집합과 utf8mb4_bin 콜레이션을 사용하여 처리합니다. 다른 문자 집합의 문자열은 필요에 따라 utf8mb4로 변환됩니다. (ascii 또는 utf8mb3 문자 집합의 문자열의 경우, ascii와 utf8mb3는 utf8mb4의 서브셋이므로 변환이 필요하지 않습니다.)
리터럴 문자열을 사용하여 JSON value를 작성하는 대신, 구성 요소 요소로부터 JSON value를 구성하기 위한 함수들이 있습니다. JSON_ARRAY()는 (비어 있을 수도 있는) value 목록을 받아 그 value를 포함하는 JSON 배열을 반환합니다:
1mysql> SELECT JSON_ARRAY('a', 1, NOW()); 2+----------------------------------------+ 3| JSON_ARRAY('a', 1, NOW()) | 4+----------------------------------------+ 5| ["a", 1, "2015-07-27 09:43:47.000000"] | 6+----------------------------------------+
JSON_OBJECT()는 (비어 있을 수도 있는) key-value pair 목록을 받아 해당 pair를 포함하는 JSON 오브젝트를 반환합니다:
1mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc'); 2+---------------------------------------+ 3| JSON_OBJECT('key1', 1, 'key2', 'abc') | 4+---------------------------------------+ 5| {"key1": 1, "key2": "abc"} | 6+---------------------------------------+
JSON_MERGE_PRESERVE()는 두 개 이상의 JSON document를 받아 결합된 결과를 반환합니다:
1mysql> SELECT JSON_MERGE_PRESERVE('["a", 1]', '{"key": "value"}'); 2+-----------------------------------------------------+ 3| JSON_MERGE_PRESERVE('["a", 1]', '{"key": "value"}') | 4+-----------------------------------------------------+ 5| ["a", 1, {"key": "value"}] | 6+-----------------------------------------------------+ 71 row in set (0.00 sec)
머징 규칙에 관한 정보는 Normalization, Merging, and Autowrapping of JSON Values를 참조하십시오.
(MySQL은 또한 다소 다른 동작을 하는 JSON_MERGE_PATCH()를 지원합니다. 이 두 함수 간의 차이점에 대해서는 JSON_MERGE_PATCH() compared with JSON_MERGE_PRESERVE()를 참조하십시오.)
JSON value는 사용자 정의 변수에 대입할 수 있습니다:
1mysql> SET @j = JSON_OBJECT('key', 'value'); 2mysql> SELECT @j; 3+------------------+ 4| @j | 5+------------------+ 6| {"key": "value"} | 7+------------------+
그러나 사용자 정의 변수는 JSON 데이터 타입이 될 수 없으므로, 앞의 예에서 @j는 JSON value처럼 보이고 JSON value와 동일한 문자 집합과 콜레이션을 가지지만, JSON 데이터 타입을 가지지는 않습니다. 대신, JSON_OBJECT()의 결과는 변수에 대입될 때 문자열로 변환됩니다.
JSON value를 변환하여 생성된 문자열은 문자 집합으로 utf8mb4, 콜레이션으로 utf8mb4_bin을 가집니다:
1mysql> SELECT CHARSET(@j), COLLATION(@j); 2+-------------+---------------+ 3| CHARSET(@j) | COLLATION(@j) | 4+-------------+---------------+ 5| utf8mb4 | utf8mb4_bin | 6+-------------+---------------+
utf8mb4_bin은 바이너리 콜레이션이므로, JSON value의 비교는 대소문자를 구분합니다.
1mysql> SELECT JSON_ARRAY('x') = JSON_ARRAY('X'); 2+-----------------------------------+ 3| JSON_ARRAY('x') = JSON_ARRAY('X') | 4+-----------------------------------+ 5| 0 | 6+-----------------------------------+
JSON 리터럴인 null, true, false에도 대소문자 구분이 적용되며, 이들은 항상 소문자로 작성해야 합니다:
1mysql> SELECT JSON_VALID('null'), JSON_VALID('Null'), JSON_VALID('NULL'); 2+--------------------+--------------------+--------------------+ 3| JSON_VALID('null') | JSON_VALID('Null') | JSON_VALID('NULL') | 4+--------------------+--------------------+--------------------+ 5| 1 | 0 | 0 | 6+--------------------+--------------------+--------------------+ 7 8mysql> SELECT CAST('null' AS JSON); 9+----------------------+ 10| CAST('null' AS JSON) | 11+----------------------+ 12| null | 13+----------------------+ 141 row in set (0.00 sec) 15 16mysql> SELECT CAST('NULL' AS JSON); 17ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json: 18"Invalid value." at position 0 in 'NULL'.
JSON 리터럴의 대소문자 구분은 어떤 대소문자로든 작성할 수 있는 SQL NULL, TRUE, FALSE 리터럴의 대소문자 구분과 다릅니다:
1mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL); 2+--------------+--------------+--------------+ 3| ISNULL(null) | ISNULL(Null) | ISNULL(NULL) | 4+--------------+--------------+--------------+ 5| 1 | 1 | 1 | 6+--------------+--------------+--------------+
때때로 JSON document에 인용부호 문자(" 또는 ')를 삽입해야 하거나 그렇게 하는 것이 바람직할 수 있습니다. 예를 들어, MySQL에 대한 사실을 서술하는 문장 문자열을 적절한 키워드와 pair로 이루어진 JSON 오브젝트로 만들어, 다음 SQL 문으로 생성된 테이블에 INSERT 하려고 한다고 가정해 보겠습니다:
1mysql> CREATE TABLE facts (sentence JSON);
이 키워드-문장 pair 중 하나는 다음과 같습니다:
1mascot: The MySQL mascot is a dolphin named "Sakila".
이를 facts 테이블에 JSON 오브젝트로 INSERT 하는 한 가지 방법은 MySQL JSON_OBJECT() 함수를 사용하는 것입니다. 이 경우, 다음과 같이 각 인용부호 문자를 백슬래시로 이스케이프 해야 합니다:
1mysql> INSERT INTO facts VALUES 2 > (JSON_OBJECT("mascot", "Our mascot is a dolphin named \"Sakila\"."));
JSON 오브젝트 리터럴로 value를 INSERT 하는 경우에는 동일한 방식으로 동작하지 않으며, 이 경우에는 다음과 같이 더블 백슬래시 이스케이프 시퀀스를 사용해야 합니다:
1mysql> INSERT INTO facts VALUES 2 > ('{"mascot": "Our mascot is a dolphin named \\"Sakila\\"."}');
더블 백슬래시를 사용하면 MySQL이 이스케이프 시퀀스 처리를 수행하지 않고, 문자열 리터럴을 스토리지 엔진에 전달하게 됩니다. 위에서 보여 준 두 가지 방식 중 어느 하나로 JSON 오브젝트를 INSERT 한 후, 간단한 SELECT를 실행하면 JSON 컬럼 value에 백슬래시가 포함되어 있음을 확인할 수 있습니다:
1mysql> SELECT sentence FROM facts; 2+---------------------------------------------------------+ 3| sentence | 4+---------------------------------------------------------+ 5| {"mascot": "Our mascot is a dolphin named \"Sakila\"."} | 6+---------------------------------------------------------+
mascot를 key로 사용하여 이 특정 문장을 조회하려면, 다음과 같이 컬럼-경로 연산자 ->를 사용할 수 있습니다:
1mysql> SELECT col->"$.mascot" FROM qtest; 2+---------------------------------------------+ 3| col->"$.mascot" | 4+---------------------------------------------+ 5| "Our mascot is a dolphin named \"Sakila\"." | 6+---------------------------------------------+ 71 row in set (0.00 sec)
이는 백슬래시와 주변 인용부호를 그대로 유지합니다. mascot를 key로 사용하여 원하는 value를 주변 인용부호나 이스케이프 없이 표시하려면, 다음과 같이 인라인 경로 연산자 ->>를 사용하십시오:
1mysql> SELECT sentence->>"$.mascot" FROM facts; 2+-----------------------------------------+ 3| sentence->>"$.mascot" | 4+-----------------------------------------+ 5| Our mascot is a dolphin named "Sakila". | 6+-----------------------------------------+
참고
앞의 예는 서버 SQL mode인 NO_BACKSLASH_ESCAPES가 활성화된 경우에는 표시된 대로 동작하지 않습니다. 이 mode가 설정된 경우, 단일 백슬래시를 사용하여 JSON 오브젝트 리터럴을 INSERT 할 수 있으며, 백슬래시가 그대로 유지됩니다. 이 mode가 설정된 상태에서 INSERT 시 JSON_OBJECT() 함수를 사용하는 경우에는 다음과 같이 single quote와 double quote를 번갈아 사용해야 합니다:
1mysql> INSERT INTO facts VALUES 2 > (JSON_OBJECT('mascot', 'Our mascot is a dolphin named "Sakila".'));
JSON value의 이스케이프된 문자에 대해 이 mode가 미치는 영향에 대한 자세한 내용은 JSON_UNQUOTE() 함수의 설명을 참조하십시오.
문자열이 파싱되어 유효한 JSON document로 판별되면, 동시에 정규화도 수행됩니다. 이는 document를 왼쪽에서 오른쪽으로 읽을 때 뒤에 나타나는 key와 중복되는 key를 가지는 멤버가 버려진다는 의미입니다. 다음 JSON_OBJECT() 호출로 생성된 오브젝트 value에서는, key1이라는 key 이름이 값 내에서 더 앞서 나타나기 때문에 두 번째 key1 요소만 포함됩니다:
1mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def'); 2+------------------------------------------------------+ 3| JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def') | 4+------------------------------------------------------+ 5| {"key1": "def", "key2": "abc"} | 6+------------------------------------------------------+
JSON 컬럼에 value를 INSERT 할 때에도 정규화가 수행됩니다:
1mysql> CREATE TABLE t1 (c1 JSON); 2 3mysql> INSERT INTO t1 VALUES 4 > ('{"x": 17, "x": "red"}'), 5 > ('{"x": 17, "x": "red", "x": [3, 5, 7]}'); 6 7mysql> SELECT c1 FROM t1; 8+------------------+ 9| c1 | 10+------------------+ 11| {"x": "red"} | 12| {"x": [3, 5, 7]} | 13+------------------+
이러한 “last duplicate key wins” 동작은 RFC 7159에서 제안되며, 대부분의 JavaScript 파서에서 구현되어 있습니다. (Bug #86866, Bug #26369555)
MySQL은 원래 JSON document에서 key, value 또는 요소 사이의 불필요한 공백을 제거하고, 표시 시에는 쉼표(,) 또는 콜론(:) 뒤에 (필요한 경우) 하나의 공백을 남기거나 삽입합니다. 이는 가독성을 높이기 위한 것입니다.
MySQL에서 JSON value를 생성하는 함수들(see Section 14.17.2, “Functions That Create JSON Values”)은 항상 정규화된 value를 반환합니다.
조회 효율을 보다 높이기 위해, MySQL은 JSON 오브젝트의 key도 정렬합니다. 이 정렬의 결과는 변경될 수 있으며, 릴리즈 간에 일관성이 보장되지 않는다는 점을 인지해야 합니다.
두 개의 머징 알고리즘이 지원되며, 이는 JSON_MERGE_PRESERVE()와 JSON_MERGE_PATCH() 함수에 의해 구현됩니다. 이 두 함수는 중복 key를 처리하는 방식에서 차이가 있습니다: JSON_MERGE_PRESERVE()는 중복 key에 대한 value를 유지하고, JSON_MERGE_PATCH()는 마지막 value를 제외한 나머지를 버립니다. 다음 몇 단락에서는 오브젝트와 배열 등 서로 다른 조합의 JSON document를 머지할 때, 각 함수가 이를 어떻게 처리하는지를 설명합니다.
Merging arrays.
여러 배열을 결합하는 컨텍스트에서는, 배열이 하나의 배열로 머지됩니다. JSON_MERGE_PRESERVE()는 나중에 지정된 배열을 첫 번째 배열의 끝에 이어붙이는 방식으로 이를 수행합니다. JSON_MERGE_PATCH()는 각 인자를 단일 요소(즉, 인덱스가 0인)로 이루어진 배열로 간주하고, “last duplicate key wins” 로직을 적용하여 마지막 인자만 선택합니다. 다음 쿼리에서 결과를 비교해 볼 수 있습니다:
1mysql> SELECT 2 -> JSON_MERGE_PRESERVE('[1, 2]', '["a", "b", "c"]', '[true, false]') AS Preserve, 3 -> JSON_MERGE_PATCH('[1, 2]', '["a", "b", "c"]', '[true, false]') AS Patch\G 4*************************** 1. row *************************** 5Preserve: [1, 2, "a", "b", "c", true, false] 6 Patch: [true, false]
여러 오브젝트를 머지하면 하나의 오브젝트가 생성됩니다. JSON_MERGE_PRESERVE()는 동일한 key를 가지는 여러 오브젝트를 처리할 때, 그 key에 대한 모든 고유한 value를 배열로 결합하고, 이 배열를 결과에서 해당 key의 value로 사용합니다. JSON_MERGE_PATCH()는 왼쪽에서 오른쪽으로 이동하면서 중복 key에 대한 value를 버려서, 결과에는 그 key에 대한 마지막 value만 포함되도록 합니다. 다음 쿼리는 중복 key a에 대한 결과의 차이를 보여 줍니다:
1mysql> SELECT 2 -> JSON_MERGE_PRESERVE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}', '{"c": 5, "d": 3}') AS Preserve, 3 -> JSON_MERGE_PATCH('{"a": 3, "b": 2}', '{"c": 3, "a": 4}', '{"c": 5, "d": 3}') AS Patch\G 4*************************** 1. row *************************** 5Preserve: {"a": [1, 4], "b": 2, "c": [3, 5], "d": 3} 6 Patch: {"a": 4, "b": 2, "c": 5, "d": 3}
배열 value가 요구되는 컨텍스트에서 사용되는 비배열 value는 자동 래핑됩니다: value는 [와 ] 문자로 둘러싸여 배열로 변환됩니다. 다음 문장에서 각 인자는 배열로 자동 래핑됩니다 ([1], [2]). 이들은 머지되어 하나의 결과 배열가 됩니다. 앞의 두 경우와 마찬가지로, JSON_MERGE_PRESERVE()는 같은 key를 가진 value를 결합하고, JSON_MERGE_PATCH()는 마지막 value를 제외한 모든 중복 key의 value를 버립니다:
1mysql> SELECT 2 -> JSON_MERGE_PRESERVE('1', '2') AS Preserve, 3 -> JSON_MERGE_PATCH('1', '2') AS Patch\G 4*************************** 1. row *************************** 5Preserve: [1, 2] 6 Patch: 2
배열과 오브젝트 value는 오브젝트를 배열로 자동 래핑한 뒤, 배열 머지를 통해 결합됩니다. 이때 머징 함수 선택(JSON_MERGE_PRESERVE() 또는 JSON_MERGE_PATCH())에 따라 value 결합 방식(결합 또는 “last duplicate key wins”)이 달라집니다. 다음 예에서 이를 확인할 수 있습니다:
1mysql> SELECT 2 -> JSON_MERGE_PRESERVE('[10, 20]', '{"a": "x", "b": "y"}') AS Preserve, 3 -> JSON_MERGE_PATCH('[10, 20]', '{"a": "x", "b": "y"}') AS Patch\G 4*************************** 1. row *************************** 5Preserve: [10, 20, {"a": "x", "b": "y"}] 6 Patch: {"a": "x", "b": "y"}
JSON 경로 표현식은 JSON document 내에서 value를 선택합니다.
경로 표현식은 JSON document의 일부를 추출하거나 수정하는 함수에서, document 내에서 연산을 수행할 위치를 지정하는 데 유용합니다. 예를 들어, 다음 쿼리는 JSON document에서 name key를 가진 멤버의 value를 추출합니다:
1mysql> SELECT JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name'); 2+---------------------------------------------------------+ 3| JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name') | 4+---------------------------------------------------------+ 5| "Aztalan" | 6+---------------------------------------------------------+
경로 구문은 고려 중인 JSON document를 나타내기 위해 선행 $ 문자를 사용하며, 그 뒤에 document 내에서 점점 더 특정한 부분을 나타내는 선택기가 선택적으로 이어집니다:
오브젝트 내에서 주어진 key를 가진 멤버를 지정하려면 마침표 뒤에 key 이름을 사용합니다. key 이름이 경로 표현식 내에서 허용되지 않는 경우(예: 공백 포함), double quotation mark로 둘러싸야 합니다.
배열를 선택하는 _path_에 [N]을 덧붙이면, 배열 내에서 position _N_에 있는 value를 지정합니다. 배열 position은 0부터 시작하는 정수입니다. _path_가 배열 value를 선택하지 않는다면, path[0]는 _path_와 동일한 value로 평가됩니다:
1mysql> SELECT JSON_SET('"x"', '$[0]', 'a'); 2+------------------------------+ 3| JSON_SET('"x"', '$[0]', 'a') | 4+------------------------------+ 5| "a" | 6+------------------------------+ 71 row in set (0.00 sec)
[M to N]은 position _M_에 있는 value부터 position _N_에 있는 value까지의 배열 value 서브셋 또는 범위를 지정합니다.last는 오른쪽 끝 배열 요소의 인덱스에 대한 동의어로 지원됩니다. 배열 요소의 상대 주소 지정도 지원됩니다. _path_가 배열 value를 선택하지 않는 경우, path[last]는 나중에 이 섹션에서 설명하는 대로 (see Rightmost array element) _path_와 동일한 value로 평가됩니다.
경로에는 * 또는 ** 와일드카드를 포함할 수 있습니다:
.[*]는 JSON 오브젝트 내 모든 멤버의 value를 의미합니다.
[*]는 JSON 배열 내 모든 요소의 value를 의미합니다.
prefix**suffix는 지정된 prefix로 시작하고 지정된 suffix로 끝나는 모든 경로를 의미합니다.
document 내에 존재하지 않는 경로(존재하지 않는 데이터로 평가되는 경로)는 NULL로 평가됩니다.
$가 세 개의 요소를 가진 다음 JSON 배열를 가리킨다고 가정해 보겠습니다:
1[3, {"a": [5, 6], "b": 10}, [99, 100]]
그렇다면 다음과 같습니다:
$[0]은 3으로 평가됩니다.
$[1]은 {"a": [5, 6], "b": 10}으로 평가됩니다.
$[2]는 [99, 100]으로 평가됩니다.
$[3]은 NULL로 평가됩니다 (네 번째 배열 요소를 가리키지만 존재하지 않기 때문입니다).
$[1]과 $[2]는 비스칼라 value로 평가되므로, 중첩된 value를 선택하는 보다 구체적인 경로 표현식의 기본으로 사용할 수 있습니다. 예:
$[1].a는 [5, 6]으로 평가됩니다.
$[1].a[1]은 6으로 평가됩니다.
$[1].b는 10으로 평가됩니다.
$[2][0]은 99로 평가됩니다.
앞에서 언급했듯이, key 이름을 지정하는 경로 구성요소는 따옴표 없는 key 이름이 경로 표현식에서 허용되지 않는 경우 반드시 인용부호로 감싸야 합니다. $가 다음 value를 가리킨다고 가정해 보겠습니다:
1{"a fish": "shark", "a bird": "sparrow"}
두 key 모두 공백을 포함하고 있으므로 인용부호로 감싸야 합니다:
$."a fish"는 shark로 평가됩니다.
$."a bird"는 sparrow로 평가됩니다.
와일드카드를 사용하는 경로는 여러 value를 포함하는 배열로 평가됩니다:
1mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*'); 2+---------------------------------------------------------+ 3| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*') | 4+---------------------------------------------------------+ 5| [1, 2, [3, 4, 5]] | 6+---------------------------------------------------------+ 7mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]'); 8+------------------------------------------------------------+ 9| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]') | 10+------------------------------------------------------------+ 11| [3, 4, 5] | 12+------------------------------------------------------------+
다음 예에서 경로 $**.b는 $.a.b와 $.c.b라는 여러 경로로 평가되며, 매칭되는 경로 value의 배열를 생성합니다:
1mysql> SELECT JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b'); 2+---------------------------------------------------------+ 3| JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b') | 4+---------------------------------------------------------+ 5| [1, 2] | 6+---------------------------------------------------------+
Ranges from JSON arrays.
to 키워드를 사용하여 범위를 지정함으로써 JSON 배열의 서브셋을 지정할 수 있습니다. 예를 들어, $[1 to 3]는 배열의 두 번째, 세 번째, 네 번째 요소를 포함합니다:
1mysql> SELECT JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[1 to 3]'); 2+----------------------------------------------+ 3| JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[1 to 3]') | 4+----------------------------------------------+ 5| [2, 3, 4] | 6+----------------------------------------------+ 71 row in set (0.00 sec)
구문은 M to N이며, _M_과 _N_은 각각 JSON 배열에서 범위의 첫 번째와 마지막 인덱스입니다. _N_은 _M_보다 커야 하며, _M_은 0 이상이어야 합니다. 배열 요소는 0부터 인덱싱됩니다.
범위는 와일드카드가 지원되는 컨텍스트에서 사용할 수 있습니다.
Rightmost array element.
last 키워드는 배열의 마지막 요소의 인덱스에 대한 동의어로 지원됩니다. last - N 형태의 표현식은 상대 주소 지정 및 범위 정의 내에서 사용할 수 있습니다:
1mysql> SELECT JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[last-3 to last-1]'); 2+--------------------------------------------------------+ 3| JSON_EXTRACT('[1, 2, 3, 4, 5]', '$[last-3 to last-1]') | 4+--------------------------------------------------------+ 5| [2, 3, 4] | 6+--------------------------------------------------------+ 71 row in set (0.01 sec)
경로가 배열가 아닌 value에 대해 평가되는 경우, 평가 결과는 그 value가 단일 요소 배열로 래핑되었을 때와 동일합니다:
1mysql> SELECT JSON_REPLACE('"Sakila"', '$[last]', 10); 2+-----------------------------------------+ 3| JSON_REPLACE('"Sakila"', '$[last]', 10) | 4+-----------------------------------------+ 5| 10 | 6+-----------------------------------------+ 71 row in set (0.00 sec)
JSON 컬럼 identifier와 JSON 경로 표현식을 사용하는 column->path는 JSON_EXTRACT(column, path)의 동의어로 사용할 수 있습니다. 자세한 내용은 Section 14.17.3, “Functions That Search JSON Values”를 참조하십시오. 또한 Indexing a Generated Column to Provide a JSON Column Index도 참조하십시오.
일부 함수는 기존 JSON document를 받아 이를 특정 방식으로 수정한 뒤, 수정된 document를 반환합니다. 경로 표현식은 document 내에서 변경을 수행할 위치를 나타냅니다. 예를 들어, JSON_SET(), JSON_INSERT(), JSON_REPLACE() 함수는 각각 JSON document와 document를 수정할 위치 및 사용할 value를 설명하는 하나 이상의 경로-value pair를 인자로 받습니다. 이들 함수는 document 내에서 기존 value와 존재하지 않는 value를 처리하는 방식이 서로 다릅니다.
다음 document를 고려해 보십시오:
1mysql> SET @j = '["a", {"b": [true, false]}, [10, 20]]';
JSON_SET()는 존재하는 경로에 대해 value를 대체하고, 존재하지 않는 경로에 대해서는 value를 추가합니다:.
1mysql> SELECT JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2); 2+--------------------------------------------+ 3| JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2) | 4+--------------------------------------------+ 5| ["a", {"b": [1, false]}, [10, 20, 2]] | 6+--------------------------------------------+
이 경우, 경로 $[1].b[0]는 기존 value(true)를 선택하며, 이는 경로 인자 뒤에 오는 value(1)로 대체됩니다. 경로 $[2][2]는 존재하지 않으므로, 이에 해당하는 value(2)가 $[2]가 선택한 value에 추가됩니다.
JSON_INSERT()는 새 value를 추가하지만 기존 value는 대체하지 않습니다:
1mysql> SELECT JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2); 2+-----------------------------------------------+ 3| JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2) | 4+-----------------------------------------------+ 5| ["a", {"b": [true, false]}, [10, 20, 2]] | 6+-----------------------------------------------+
JSON_REPLACE()는 기존 value를 대체하고 새로운 value는 무시합니다:
1mysql> SELECT JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2); 2+------------------------------------------------+ 3| JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2) | 4+------------------------------------------------+ 5| ["a", {"b": [1, false]}, [10, 20]] | 6+------------------------------------------------+
경로-value pair는 왼쪽에서 오른쪽으로 평가됩니다. 한 pair를 평가하여 생성된 document는 다음 pair가 평가될 때 기준이 되는 새로운 value가 됩니다.
JSON_REMOVE()는 JSON document와 document에서 제거할 value를 지정하는 하나 이상의 경로를 인자로 받습니다. 반환 값은 document 내에 존재하는 경로가 선택하는 value를 제외한, 원래 document입니다:
1mysql> SELECT JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]'); 2+---------------------------------------------------+ 3| JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]') | 4+---------------------------------------------------+ 5| ["a", {"b": [true]}] | 6+---------------------------------------------------+
각 경로는 다음과 같은 영향을 미칩니다:
$[2]는 [10, 20]과 일치하며, 이를 제거합니다.
첫 번째 $[1].b[1]는 b 요소 내의 false와 일치하며, 이를 제거합니다.
두 번째 $[1].b[1]는 아무 것과도 일치하지 않습니다. 해당 요소는 이미 제거되었고, 경로는 더 이상 존재하지 않으므로 아무 영향도 주지 않습니다.
이 Manual의 다른 곳에서 설명된 MySQL 지원 JSON 함수들 중 많은 함수는 (see Section 14.17, “JSON Functions”) JSON document 내의 특정 요소를 식별하기 위해 경로 표현식을 필요로 합니다. 경로는 경로의 스코프 뒤에 하나 이상의 경로 다리(path leg)가 따라오는 구조를 가집니다. MySQL JSON 함수에서 사용되는 경로의 경우, 스코프는 항상 검색 또는 다른 연산의 대상이 되는 document이며, 선행 '$' 문자로 표현됩니다. 경로 다리는 마침표 문자(.)로 구분됩니다. 배열의 셀은 [N]으로 표현되며, 여기서 _N_은 0 이상의 정수입니다. key 이름은 double-quoted 문자열이거나 유효한 ECMAScript identifier여야 합니다 (ECMAScript Language Specification의 Identifier Names and Identifiers을 참조하십시오). 경로 표현식은 JSON 텍스트와 마찬가지로 ascii, utf8mb3, 또는 utf8mb4 문자 집합을 사용하여 인코딩해야 합니다. 다른 문자 인코딩은 암묵적으로 utf8mb4로 변환됩니다. 전체 구문은 다음과 같습니다:
1pathExpression: 2 scope[(pathLeg)*] 3 4pathLeg: 5 member | arrayLocation | doubleAsterisk 6 7member: 8 period ( keyName | asterisk ) 9 10arrayLocation: 11 leftBracket ( nonNegativeInteger | asterisk ) rightBracket 12 13keyName: 14 ESIdentifier | doubleQuotedString 15 16doubleAsterisk: 17 '**' 18 19period: 20 '.' 21 22asterisk: 23 '*' 24 25leftBracket: 26 '[' 27 28rightBracket: 29 ']'
앞에서 언급했듯이, MySQL에서 경로의 스코프는 항상 $로 표현되는, 연산 대상인 document입니다. JSON 경로 표현식에서 document의 동의어로 '$'를 사용할 수 있습니다.
참고
일부 구현은 JSON 경로 스코프에 대한 컬럼 reference를 지원하지만, MySQL 9.5는 이를 지원하지 않습니다.
와일드카드 * 및 ** 토큰은 다음과 같이 사용됩니다:
.*는 오브젝트 내 모든 멤버의 value를 나타냅니다.
[*]는 배열 내 모든 셀의 value를 나타냅니다.
[prefix]**suffix는 _prefix_로 시작하고 _suffix_로 끝나는 모든 경로를 나타냅니다. _prefix_는 선택 사항이지만 _suffix_는 필수입니다. 즉, 경로는 **로 끝날 수 없습니다.
또한, 경로에는 *** 시퀀스를 포함할 수 없습니다.
경로 구문 예제는 JSON_CONTAINS_PATH(), JSON_SET(), JSON_REPLACE()와 같이, 인자로 경로를 받는 다양한 JSON 함수 설명에서 찾아볼 수 있습니다. * 및 ** 와일드카드 사용을 포함한 예제는 JSON_SEARCH() 함수 설명을 참조하십시오.
MySQL은 또한 to 키워드를 사용한 JSON 배열 서브셋에 대한 범위 표기($[2 to 10] 등)와, 배열의 오른쪽 끝 요소에 대한 동의어인 last 키워드를 지원합니다. 자세한 정보와 예제는 Searching and Modifying JSON Values를 참조하십시오.
JSON value는 =, <, <=, >, >=, <>, !=, <=> 연산자를 사용하여 비교할 수 있습니다.
다음 비교 연산자와 함수는 아직 JSON value에 대해 지원되지 않습니다:
위에서 나열한 비교 연산자와 함수에 대한 우회 방법은 JSON value를 네이티브 MySQL 숫자 또는 문자열 데이터 타입으로 캐스팅하여, 일관된 비-JSON 스칼라 타입을 갖도록 하는 것입니다.
JSON value의 비교는 두 단계로 이루어집니다. 첫 번째 단계 비교는 비교 대상 value의 JSON 타입에 기반합니다. 타입이 다른 경우, 비교 결과는 오직 어떤 타입이 더 높은 우선순위를 가지는지에 의해 결정됩니다. 두 value가 동일한 JSON 타입을 가지는 경우, 두 번째 단계 비교가 타입별 규칙을 사용하여 수행됩니다.
다음 목록은 JSON 타입의 우선순위를, 가장 높은 우선순위에서 가장 낮은 우선순위 순으로 보여 줍니다. (타입 이름은 JSON_TYPE() 함수가 반환하는 이름입니다.) 동일한 줄에 표시된 타입은 동일한 우선순위를 갖습니다. 목록에서 앞에 나오는 JSON 타입을 가진 value는, 목록에서 뒤에 나오는 JSON 타입을 가진 value보다 항상 크게 비교됩니다.
1BLOB 2BIT 3OPAQUE 4DATETIME 5TIME 6DATE 7BOOLEAN 8ARRAY 9OBJECT 10STRING 11INTEGER, DOUBLE 12NULL
동일한 우선순위를 가진 JSON value에 대해서는, 비교 규칙이 타입별입니다:
BLOB
두 value의 처음 N 바이트를 비교하며, 여기서 _N_은 더 짧은 value의 바이트 수입니다. 처음 N 바이트가 동일하면, 더 짧은 value가 더 긴 value보다 먼저 정렬됩니다.
BIT
BLOB과 동일한 규칙을 사용합니다.
OPAQUE
BLOB과 동일한 규칙을 사용합니다. OPAQUE value는 다른 타입 중 어느 하나로도 분류되지 않는 value입니다.
DATETIME
더 이른 시점을 나타내는 value가 더 나중 시점을 나타내는 value보다 먼저 정렬됩니다. 두 value가 MySQL의 DATETIME과 TIMESTAMP 타입에서 각각 왔더라도, 동일한 시점을 나타낸다면 두 value는 동일합니다.
TIME
더 작은 time value가 더 큰 value보다 먼저 정렬됩니다.
DATE
더 이른 날짜가 더 나중 날짜보다 먼저 정렬됩니다.
ARRAY
두 JSON 배열는 길이가 동일하고, 배열의 각 위치에 있는 value가 서로 동일한 경우에만 같습니다.
배열가 동일하지 않은 경우, 비교 결과는 차이가 처음 발생하는 위치의 요소에 의해 결정됩니다. 그 위치에서 더 작은 value를 가진 배열가 먼저 정렬됩니다. 더 짧은 배열의 모든 value가 더 긴 배열의 해당 value와 동일한 경우, 더 짧은 배열가 먼저 정렬됩니다.
예:
1[] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"]
BOOLEAN
JSON false 리터럴은 JSON true 리터럴보다 작게 평가됩니다.
OBJECT
두 JSON 오브젝트는 동일한 key 집합을 가지고, 각 key가 두 오브젝트에서 동일한 value를 가질 때만 같습니다.
예:
1{"a": 1, "b": 2} = {"b": 2, "a": 1}
동일하지 않은 두 오브젝트 간의 정렬 순서는 지정되어 있지 않지만 결정적입니다.
STRING
문자열은 두 문자열의 utf8mb4 표현에서 처음 N 바이트를 기준으로 사전식으로 정렬되며, 여기서 _N_은 더 짧은 문자열의 길이입니다. 처음 N 바이트가 동일하면, 더 짧은 문자열이 더 긴 문자열보다 작다고 간주됩니다.
예:
1"a" < "ab" < "b" < "bc"
이 정렬은 콜레이션이 utf8mb4_bin인 SQL 문자열의 정렬과 동일합니다. utf8mb4_bin은 바이너리 콜레이션이므로, JSON value 비교는 대소문자를 구분합니다:
1"A" < "a"
INTEGER, DOUBLE
JSON value는 정수형 숫자와 부동소수형 숫자를 모두 포함할 수 있습니다. 이들 숫자 타입에 대한 일반적인 설명은 Section 11.1.2, “Numeric Literals”를 참조하십시오.
네이티브 MySQL 숫자 타입을 비교하는 규칙은 Section 14.3, “Type Conversion in Expression Evaluation”에서 설명하지만, JSON value 내 숫자를 비교하는 규칙은 약간 다릅니다:
네이티브 MySQL 숫자 타입인 INT와 DOUBLE을 사용하는 두 컬럼 간 비교에서는, 모든 비교가 정수와 double 사이에서 이루어지므로, 정수는 모든 row에 대해 double로 변환됩니다. 즉, 정수형 숫자가 부동소수형 숫자로 변환됩니다.
반면, 쿼리가 숫자를 포함하는 두 JSON 컬럼을 비교하는 경우, 숫자가 정수인지 double인지 미리 알 수 없습니다. 모든 row에서 가장 일관된 동작을 제공하기 위해, MySQL은 부동소수형 숫자를 정수형 숫자로 변환합니다. 이렇게 하면 정렬이 일관되며, 정수형 숫자의 정밀도가 손실되지 않습니다. 예를 들어, 스칼라 9223372036854775805, 9223372036854775806, 9223372036854775807, 9.223372036854776e18이 주어지면, 정렬 순서는 다음과 같습니다:
19223372036854775805 < 9223372036854775806 < 9223372036854775807 2< 9.223372036854776e18 = 9223372036854776000 < 9223372036854776001
비-JSON 숫자 비교 규칙을 JSON 비교에 사용한다면, 정렬이 일관되지 않을 수 있습니다. MySQL의 일반적인 숫자 비교 규칙은 다음과 같은 정렬을 제공합니다:
정수 비교:
19223372036854775805 < 9223372036854775806 < 9223372036854775807
(9.223372036854776e18에 대해서는 정의되지 않음)
double 비교:
19223372036854775805 = 9223372036854775806 = 9223372036854775807 = 9.223372036854776e18
어떤 JSON value를 SQL NULL과 비교하든, 그 결과는 UNKNOWN입니다.
JSON value와 비-JSON value를 비교하는 경우, 비-JSON value는 다음 테이블의 규칙에 따라 JSON으로 변환된 후, 앞에서 설명한 방식대로 비교됩니다.
다음 테이블은 MySQL이 JSON value와 다른 타입의 value 간에 캐스팅 할 때 따르는 규칙을 요약하여 보여 줍니다:
Table 13.3 JSON Conversion Rules
| other type | CAST(other type AS JSON) | CAST(JSON AS other type) |
|---|---|---|
| JSON | 변경 없음 | 변경 없음 |
utf8 character type (utf8mb4,<br> utf8mb3, ascii) | 문자열이 JSON value로 파싱됩니다. | JSON value가 utf8mb4 문자열로 직렬화됩니다. |
| Other character types | 다른 문자 인코딩은 암묵적으로<br> utf8mb4로 변환되며,<br> 이 문자 타입에 대해 설명한 대로 처리됩니다. | JSON value가 utf8mb4 문자열로 직렬화된 후,<br> 다른 문자 인코딩으로 캐스팅됩니다.<br> 결과는 의미가 없을 수도 있습니다. |
NULL | JSON 타입의 NULL value가 생성됩니다. | 적용 불가. |
| Geometry types | 지리 정보 value는<br> ST_AsGeoJSON()을 호출하여<br> JSON document로 변환됩니다. | 허용되지 않는 연산입니다. 우회 방법: CAST(json_val<br> AS CHAR)의 결과를 ST_GeomFromGeoJSON()에 전달하십시오. |
| All other types | 단일 스칼라 value로 구성된 JSON document가 생성됩니다. | JSON document가 대상 타입의 단일 스칼라 value로만 구성되고, 그 스칼라 value가 대상 타입으로 캐스팅될 수 있는 경우 성공합니다. 그렇지 않으면 NULL을 반환하고 warning을 발생시킵니다. |
JSON value에 대한 ORDER BY와 GROUP BY는 다음 원칙에 따라 동작합니다:
스칼라 JSON value의 정렬은 앞에서 논의한 규칙과 동일한 규칙을 사용합니다.
오름차순 정렬에서 SQL NULL은 JSON null 리터럴을 포함한 모든 JSON value보다 먼저 정렬되며, 내림차순 정렬에서는 그 반대로, SQL NULL이 JSON null 리터럴을 포함한 모든 JSON value 뒤에 정렬됩니다.
JSON value에 대한 정렬 키는 max_sort_length 시스템 변수 값에 의해 제한되므로, 처음 max_sort_length 바이트 이후에서만 차이가 나는 키는 동일한 것으로 비교됩니다.
비스칼라 value의 정렬은 현재 지원되지 않으며, warning이 발생합니다.
정렬의 경우, JSON 스칼라를 다른 네이티브 MySQL 타입으로 캐스팅 하는 것이 유리할 수 있습니다. 예를 들어, jdoc이라는 컬럼이 음수가 아닌 value를 가진 id key 멤버가 포함된 JSON 오브젝트를 저장하고 있다면, id value를 기준으로 정렬하려면 다음 표현식을 사용하십시오:
1ORDER BY CAST(JSON_EXTRACT(jdoc, '$.id') AS UNSIGNED)
만약 ORDER BY에서 사용된 표현식과 동일한 표현식을 사용하는 생성 칼럼에 대해 인덱스가 정의되어 있다면, MySQL 옵티마이저는 이를 인식하고 쿼리 실행 계획에서 해당 인덱스 사용을 고려합니다. Section 10.3.11, “Optimizer Use of Generated Column Indexes”를 참조하십시오.
JSON value의 집계에 대해, SQL NULL value는 다른 데이터 타입과 마찬가지로 무시됩니다. Non-NULL value는 MIN(), MAX(), GROUP_CONCAT()을 제외하고 숫자 타입으로 변환되어 집계됩니다. 숫자 타입으로의 변환은 숫자 스칼라인 JSON value에 대해서는 의미 있는 결과를 생성해야 하지만, value에 따라 잘림 및 정밀도 손실이 발생할 수 있습니다. 기타 JSON value를 숫자로 변환하는 것은 의미 있는 결과를 생성하지 않을 수 있습니다.
13.4.11 Using Spatial Indexes
13.6 Data Type Default Values