{#syntax-syntax} # 구문 어느 언어로 쓰였든 모든 문장이 지키는 어휘 층입니다. 이 레퍼런스가 구문에 쓰는 표기법, 그리고 식별자·리터럴·연산자·주석·null의 규칙입니다. Cypher와 GQL과 SQL이 파서 하나를 공유하므로, 이 규칙들은 셋 모두에서 같습니다. 규칙이 셋 사이에서 다른 곳에서는 그 차이를 따로 적었습니다. {#syntax-syntax-conventions} ## 구문 표기 규약 이 레퍼런스의 모든 개요는 같은 방식으로 적혀 있습니다:
MATCH pattern [, pattern ] ... [ WHERE condition ]
개요에서 그 밖의 것은 표기법이 아닙니다. 쉼표·괄호·화살표는 문장의 일부이며, 보인 대로 입력합니다. **굵게** : 키워드입니다. 보이는 대로 입력하십시오. 대소문자는 상관없습니다. *기울임* : 직접 채우는 자리입니다. 각각 같은 페이지의 *매개변수* 아래에 정의돼 있습니다. `[ ]` : 감싼 부분은 생략할 수 있습니다. `{ ... | ... }` : 세로 막대로 구분한 선택지를 중괄호로 감싼 것입니다. 정확히 하나를 고르십시오. `...` : 그 앞의 항목을 반복할 수 있습니다. `[, ... ]` : 그 앞의 항목을 쉼표로 구분해 반복할 수 있습니다. 개요가 두 줄 이상 : 같은 문장의 다른 형태들입니다. 그중 하나를 쓰십시오. `where` *placeholder* `is one of:` : 한 줄에 담기에 너무 큰 자리표를 뒤따르는 줄에서 펼쳐 보입니다. 대괄호와 중괄호는 결코 글자 그대로가 아닙니다. 어떤 문장에는 실제로 대괄호가 들어갑니다. 리스트 리터럴, 맵, 간선 패턴이 그렇습니다. 그런 경우에는 개요가 산문으로 그 사실을 적거나, `-[` *variable* `]->`처럼 대괄호를 다른 자리에 보여 줍니다. {#syntax-identifiers} ## 식별자 식별자는 그래프·레이블·변수·속성 키·컬럼·인덱스·제약의 이름입니다. {#syntax-case-folding} ### 대소문자 접힘 따옴표 없는 식별자는 **소문자**로 접힙니다. PostgreSQL이 따옴표 없는 SQL 식별자를 접는 것과 정확히 같습니다. 그래서 `MOVIE`, `Movie`, `movie`가 모두 같은 레이블을 가리킵니다: ```cypher MATCH (n:MOVIE {title: 'The Matrix'}) RETURN n.title AS title; ``` ``` title -------------- "The Matrix" ``` 큰따옴표로 감싼 식별자는 적힌 대로 받아들여집니다. `"MOVIE"`는 `movie`와 다른 이름입니다. `MOVIE`라는 레이블은 없으므로, 그 패턴은 실패하는 것이 아니라 아무것에도 일치하지 않습니다: ```cypher MATCH (n:"MOVIE" {title: 'The Matrix'}) RETURN n.title AS title; ``` ``` title ------- (0 rows) ``` 따옴표는 변수에도 통하며, 따옴표를 붙인 변수는 언급할 때마다 따옴표를 붙여야 합니다: ```cypher MATCH ("Film":movie {title: 'The Matrix'}) RETURN "Film".title AS title; ``` ``` title -------------- "The Matrix" ``` 속성 키도 같은 방식으로 접힙니다. `{MixedKey: 1}`은 키 `mixedkey`를 저장하고, `{"MixedKey": 1}`은 `MixedKey`를 저장합니다. 둘은 서로 다른 키이고 한 정점이 둘 다 가질 수 있으므로, 키에 따옴표를 붙일 때는 일관되게 붙이거나 아예 붙이지 마십시오. 백틱은 인용 문자가 아닙니다. `` `movie` `` 는 인용된 식별자가 아니라 구문 오류입니다: ```cypher MATCH (n:`movie`) RETURN n.title; ``` ``` ERROR: syntax error at or near "`" LINE 1: MATCH (n:`movie`) RETURN n.title; ^ ``` {#syntax-characters} ### 문자 따옴표 없는 식별자는 글자나 밑줄로 시작하고, 그 뒤로 글자·숫자·밑줄·달러 기호가 이어집니다. "글자"에는 ASCII가 아닌 글자도 포함되므로 `café`도 유효한 식별자입니다. 숫자로 시작할 수는 없습니다. `1abc`는 뒤에 군더더기가 붙은 숫자로 읽힙니다. 큰따옴표로 감싼 식별자에는 null 바이트를 뺀 어떤 문자든 들어갈 수 있고, 그 안의 큰따옴표는 두 번 적습니다(`"say ""hi"""`). 길이 제한은 PostgreSQL의 것입니다. 63바이트이고, 그보다 긴 이름은 그 길이로 잘립니다. 이 제한은 글자가 아니라 바이트를 세므로, 여러 바이트 글자로 된 이름은 더 일찍 제한에 닿습니다. {#syntax-reserved-words} ### 예약어 어떤 키워드는 **예약돼** 있습니다. 문법이 그 단어를 이름이 아니라 키워드로 읽습니다. `both`, `let`, `finish`, `insert`, `offset`, `xor`가 모두 예약어입니다. 일부는 PostgreSQL에서 물려받은 것이고 일부는 그래프 절을 위해 더한 것입니다. 각각이 어느 자리에서 여전히 동작하는지는 단어마다 다르므로, 자리별 표는 [키워드](../appendix/keywords.md)에 있습니다. 패턴 변수는 그중 어느 것도 살아남지 못하는 자리입니다: ```cypher MATCH (both:movie {title: 'The Matrix'}) RETURN both.title; ``` ``` ERROR: syntax error at or near "both" LINE 1: MATCH (both:movie {title: 'The Matrix'}) RETURN both.title; ^ ``` 따옴표를 붙이면 그 제한이 풀립니다. 인용된 식별자는 결코 키워드로 읽히지 않기 때문입니다: ```cypher MATCH ("both":movie {title: 'The Matrix'}) RETURN "both".title AS title; ``` ``` title -------------- "The Matrix" ``` 예약어는 `RETURN` 별칭과 속성 키로는 여전히 허용됩니다. 그 두 자리는 키워드와 혼동될 수 없기 때문입니다: ```cypher MATCH (m:movie {title: 'The Matrix'}) RETURN m.title AS both; ``` ``` both -------------- "The Matrix" ``` {#syntax-literals} ## 리터럴 {#syntax-strings} ### 문자열 문자열 리터럴은 **작은**따옴표로 감쌉니다. 큰따옴표는 문자열이 아니라 식별자를 만들므로, `"plain"`은 변수 참조이고 그런 변수가 유효 범위에 없으면 실패합니다. 리터럴 안의 작은따옴표는 두 번 적습니다. 역슬래시 이스케이프는 JSON의 규칙을 따릅니다. Cypher의 문자열이 `jsonb` 문자열이 되기 때문입니다: | 이스케이프 | 뜻 | | --- | --- | | `''` | 작은따옴표입니다. | | `\"` | 큰따옴표입니다. | | `\\` | 역슬래시입니다. | | `\/` | 슬래시입니다. | | `\b` `\f` `\n` `\r` `\t` | 백스페이스, 폼 피드, 줄바꿈, 캐리지 리턴, 탭입니다. | | `\u` 뒤에 16진수 네 자리 | 그 코드 포인트의 문자입니다. | 그 밖의 역슬래시 조합은 거부됩니다. `'a\qb'`는 `Escape sequence "\q" is invalid`를 냅니다. ```cypher RETURN 'plain', 'it''s', 'a\tb', 'a\\tb', 'say \" hi'; ``` ``` ?column? | ?column? | ?column? | ?column? | ?column? ----------+----------+----------+----------+------------- "plain" | "it's" | "a\tb" | "a\\tb" | "say \" hi" ``` 출력은 각 값의 `jsonb` 표현이고, 그것은 출력하는 것을 다시 이스케이프합니다. 세 번째 컬럼은 문자 세 개, `a`와 탭과 `b`를 담고 있습니다. {#syntax-numbers} ### 숫자 숫자 리터럴은 SQL에서와 같이 적으며, PostgreSQL의 비십진 표기와 구분자 표기도 받아들여집니다. 16진 `0x`, 8진 `0o`, 2진 `0b`, 그리고 자릿수 구분자로 쓰는 밑줄입니다. ```cypher RETURN 1, -1, 1.5, 1e3, 1E-3, 0x1F, 0o17, 0b101, 1_000; ``` ``` ?column? | ?column? | ?column? | ?column? | ?column? | ?column? | ?column? | ?column? | ?column? ----------+----------+----------+----------+----------+----------+----------+----------+---------- 1 | -1 | 1.5 | 1000 | 0.001 | 31 | 15 | 5 | 1000 ``` 소수점 없이 적은 숫자는 JSON 정수이고, 그 둘을 나누면 버림이 일어납니다. `7 / 2`는 `3`입니다. `3.5`를 원하면 `7.0 / 2`로 쓰십시오. {#syntax-booleans-null-lists-and-maps} ### 불리언, null, 리스트, 맵 `true`, `false`, `null`은 대소문자와 무관한 키워드입니다. 리스트는 대괄호로, 맵은 중괄호로 적습니다. 둘 다 중첩되고, 둘 다 값의 타입을 섞을 수 있습니다. 둘 다 `jsonb`가 되기 때문입니다. ```cypher RETURN true, false, null, [1, 'two', true, null], {a: 1, b: [2], c: {d: 3}}; ``` ``` ?column? | ?column? | ?column? | ?column? | ?column? ----------+----------+----------+------------------------+----------------------------------- t | f | | [1, "two", true, null] | {"a": 1, "b": [2], "c": {"d": 3}} ``` 맵의 키는 식별자이고 식별자처럼 접힙니다. `[]`와 `{}`는 빈 리스트와 빈 맵입니다. 리터럴이 저장되는 `jsonb` 값과 어떤 관계인지는 [데이터 타입](types.md)을 참고하십시오. {#syntax-operators} ## 연산자 {#syntax-precedence} ### 우선순위 연산자는 이 순서로 결합하며, 느슨한 것이 먼저입니다. 같은 행의 두 연산자는 우선순위가 같고 그 행이 적은 대로 결합합니다. | 우선순위 | 연산자 | 결합 방향 | | --- | --- | --- | | 1 (가장 느슨) | `UNION` `EXCEPT` | 왼쪽 | | 2 | `INTERSECT` | 왼쪽 | | 3 | `OR` `XOR` | 왼쪽 | | 4 | `AND` | 왼쪽 | | 5 | `NOT` | 오른쪽 | | 6 | `IS NULL` `IS NOT NULL` `IS [NOT] UNKNOWN` | 없음 | | 7 | `<` `<=` `>` `>=` `=` `<>` `!=` | 없음 | | 8 | `IN` `BETWEEN` | 없음 | | 9 | `\|\|` 와 `jsonb` 연산자를 포함한 그 밖의 모든 연산자 | 왼쪽 | | 10 | `+` `-` (이항) | 왼쪽 | | 11 | `*` `/` `%` | 왼쪽 | | 12 | `^` | 왼쪽 | | 13 | `-` (단항) | 오른쪽 | | 14 | `STARTS WITH` `ENDS WITH` `CONTAINS` `=~` | 없음 | | 15 | `[` `]` (첨자), `(` `)` (호출) | 왼쪽 | | 16 | `::` | 왼쪽 | | 17 (가장 단단) | `.` | 왼쪽 | 이 표는 Cypher 표현식이 담을 수 있는 연산자를 나열합니다. SQL은 자기만의 단계에 몇 개를 더합니다. `AT TIME ZONE`, `COLLATE`, `LIKE`, `ILIKE`, `SIMILAR TO`입니다. Cypher의 표현식 문법은 그중 어느 것도 받지 않습니다. 이 표에서 흔한 기대와 다른 것이 세 가지 있습니다. `^`는 **왼쪽** 결합이고 단항 마이너스보다 느슨하게 결합합니다. 산술의 규칙이 아니라 PostgreSQL의 규칙입니다. 그래서 `2 ^ 3 ^ 2`는 `(2 ^ 3) ^ 2`이고 `-2 ^ 2`는 `(-2) ^ 2`입니다: ```cypher RETURN 2 ^ 3 ^ 2 AS pow, -2 ^ 2 AS neg; ``` ``` pow | neg -----+----- 64 | 4 ``` 문자열 일치 연산자는 첨자·호출·형 변환·속성 읽기를 뺀 모든 것보다 **단단히** 결합합니다. 이어 붙이기보다도, 산술보다도 단단히 결합합니다. 그래서 아래 `||`의 오른쪽 피연산자는 `'c'`만이 아니라 `STARTS WITH` 검사 전체입니다: ```cypher RETURN 'ab' || 'c' STARTS WITH 'a'; ``` ``` ?column? ----------- "abfalse" ``` 다른 쪽으로 읽히길 원한다면 괄호를 쓰십시오. `('ab' || 'c') STARTS WITH 'a'`는 `true`입니다. 비교는 이어지지 않습니다. `1 < 2 < 3`은 두 개의 비교가 아니라 구문 오류입니다. {#syntax-logical-operators} ### 논리 연산자 `AND`, `OR`, `NOT`, `XOR`는 불리언을 받아 불리언을 반환하며, 세 개의 값을 다룹니다. 진리표는 [null과 삼치 논리](#syntax-null-and-three-valued-logic)를 참고하십시오. `XOR`는 SQL의 집합에 AgensGraph가 더한 것이고, 우선순위는 `OR`와 같습니다. {#syntax-comparison-and-predicates} ### 비교와 조건 `=`, `<>`(또는 `!=`), `<`, `<=`, `>`, `>=`는 두 값을 비교합니다. `jsonb` 타입이 서로 다른 값을 비교해도 실패하지 않습니다. `jsonb` 자신의 타입 순서로 그것들을 정렬합니다. `IN`은 리스트에 속하는지 검사합니다. `IS NULL`과 `IS NOT NULL`은 어떤 값이든 비교하지 않고 null인지 검사합니다. `IS UNKNOWN`과 `IS NOT UNKNOWN`은 불리언에 대한 그 검사를 표준이 표기하는 방식이며, 여기서도 받아들여집니다: ```cypher RETURN 2 IN [1, 2, 3] AS present, null IS NULL AS nul, null IS UNKNOWN AS unk; ``` ``` present | nul | unk ---------+-----+----- t | t | t ``` {#syntax-string-matching} ### 문자열 일치 문자열을 일치시키는 연산자가 네 개 있습니다. `LIKE`, `ILIKE`, `SIMILAR TO`는 **SQL 전용**입니다. Cypher의 표현식 문법의 일부가 아니고, 거기서는 구문 오류입니다. PostgreSQL의 정규 표현식 연산자(`~`, `~*`, `!~`, `!~*`)는 Cypher에서 동작합니다. | 연산자 | 검사 | | --- | --- | | *string* `STARTS WITH` *prefix* | 문자열이 그 접두 문자열로 시작합니다. | | *string* `ENDS WITH` *suffix* | 문자열이 그 접미 문자열로 끝납니다. | | *string* `CONTAINS` *substring* | 그 부분 문자열이 문자열 어디에든 나타납니다. | | *string* `=~` *pattern* | 문자열 전체가 POSIX 정규 표현식과 일치합니다. | ```cypher RETURN 'Matrix' STARTS WITH 'Mat' AS sw, 'Matrix' ENDS WITH 'rix' AS ew, 'Matrix' CONTAINS 'atr' AS c, 'Matrix' =~ '^M.*x$' AS re; ``` ``` sw | ew | c | re ----+----+---+---- t | t | t | t ``` 넷 중 어느 것도 인덱스로 답할 수 없습니다. 인덱스로 처리돼야 하는 조건에는 `=`이나 범위가 필요합니다. 속성의, 인덱스에 보이는 형태는 [데이터 타입](types.md)이 다룹니다. {#syntax-arithmetic} ### 산술 `+`, `-`, `*`, `/`, `%`, `^`는 숫자에 대해 동작하고, 단항 `+`와 `-`는 부호를 바꿉니다. 속성에 대해서는 SQL의 수치 타입이 아니라 `jsonb`를 상대로 동작하며, 그래서 `+`에 일이 둘 더 생깁니다. 문자열 둘을 이어 붙이고, 리스트에 덧붙입니다. ```cypher MATCH (p:person {name: 'Keanu Reeves'}) RETURN p.born + 1 AS plus, p.born % 7 AS mod, -p.born AS neg, p.name + '!' AS concat, [1, 2] + 3 AS appended; ``` ``` plus | mod | neg | concat | appended ------+-----+-------+-----------------+----------- 1965 | 4 | -1964 | "Keanu Reeves!" | [1, 2, 3] ``` 맵 둘에 대한 `+`는 `invalid expression: {"a": 1} + {"b": 2}`로 거부됩니다. 맵은 대신 `jsonb`의 이어 붙이기 연산자로 병합하십시오: ```cypher RETURN {a: 1} || {b: 2} AS merged; ``` ``` merged ------------------ {"a": 1, "b": 2} ``` 값이 아니라 요소에 병합하려면 `SET n += ` *map*을 쓰십시오. {#syntax-jsonb-operators} ### jsonb 연산자 속성은 `jsonb`이므로 PostgreSQL의 `jsonb` 연산자가 속성에 곧바로 적용됩니다. 알아 둘 만한 것들은 이렇습니다: | 연산자 | 결과 | | --- | --- | | *json* `->` *key* / *index* | 그 멤버를 `jsonb`로 | | *json* `->>` *key* / *index* | 그 멤버를 `text`로 | | *json* `#>` *path* | 텍스트 배열 경로에 있는 값을 `jsonb`로 | | *json* `#>>` *path* | 텍스트 배열 경로에 있는 값을 `text`로 | | *json* `?` *key* | 그 키가 있는지 | | *json* `@>` *json* | 왼쪽 값이 오른쪽을 포함하는지 | | *json* `<@` *json* | 왼쪽 값이 오른쪽에 포함되는지 | | *json* `\|\|` *json* | 이어 붙이기. 객체 둘은 병합되고, 그 밖의 조합은 배열을 만듭니다. | ```cypher MATCH (m:movie {title: 'The Matrix'}) RETURN properties(m) -> 'title' AS as_json, properties(m) ->> 'title' AS as_text, properties(m) ? 'genre' AS has_genre, properties(m) @> '{"genre": "Action"}' AS is_action; ``` ``` as_json | as_text | has_genre | is_action --------------+--------------+-----------+----------- "The Matrix" | "The Matrix" | t | t ``` `->>`은 `text`를 반환했지만, Cypher의 `RETURN`이 스칼라 컬럼을 다시 `jsonb`로 감싸므로 따옴표가 그대로 남습니다. 평범한 문자열로 꺼내려면 그 쿼리를 SQL로 감싸십시오. [데이터 타입](#types-what-a-return-hands-back)을 참고하십시오. Cypher 안에서 PostgreSQL의 나머지 `jsonb` 연산자를 지배하는 규칙이 두 가지 있고, 둘 다 산술 표기를 Cypher가 차지했다는 점에서 따라옵니다. `jsonb` 값 둘 사이의 `-`는 뺄셈이므로, `jsonb`의 키 삭제 연산자는 Cypher에서 닿을 수 없습니다. `properties(m) - 'plot'`은 `invalid expression`을 냅니다. 키는 SQL로 감싸서 지우거나 `REMOVE`로 지우십시오. 네이티브 `jsonb` 연산자 옆에 문자열 리터럴만 두면 그것은 JSON 문자열이 아니라 JSON 문서 전체로 파싱됩니다. 그래서 `m.title || '!'`은 `Token "!" is invalid`로 실패합니다. `m.title || to_jsonb('!'::text)`처럼 그 연산자에 타입이 있는 피연산자를 주십시오. 또는 Cypher 쪽 해석을 취하는 `+`를 쓰십시오. {#syntax-comments} ## 주석 주석은 `--`부터 그 줄의 끝까지, 또는 `/*`부터 짝이 되는 `*/`까지입니다. 블록 주석은 중첩되므로, 주석이 들어 있는 영역을 주석 처리해도 짝이 맞습니다. `//`는 주석이 아니고 구문 오류입니다. ```cypher MATCH (m:movie {title: 'The Matrix'}) -- one film /* a block comment over two lines */ RETURN m.title AS title; ``` ``` title -------------- "The Matrix" ``` {#syntax-null-and-three-valued-logic} ## null과 삼치 논리 `null`은 *알 수 없음*을 뜻합니다. 비교에 쓸 수 있는 값이 아니고, 속성 값도 아닙니다. 속성에 null을 할당하면 그 속성이 지워집니다. [`allow_null_properties`](#guc-allow_null_properties)를 켜 둔 경우는 예외입니다. {#syntax-truth-tables} ### 진리표 `AND`, `OR`, `XOR`는 세 개의 값으로 다음과 같이 확장됩니다. 아래 표는 모든 조합을 실행한 출력입니다: ```psql SELECT a #>> '{}' AS a, b #>> '{}' AS b, andv::text AS "a AND b", orv::text AS "a OR b", xorv::text AS "a XOR b" FROM (UNWIND [true, false, null] AS a UNWIND [true, false, null] AS b RETURN a, b, a AND b AS andv, a OR b AS orv, a XOR b AS xorv) q; ``` ``` a | b | a AND b | a OR b | a XOR b -------+-------+---------+--------+--------- true | true | true | true | false true | false | false | true | true true | null | null | true | null false | true | false | true | true false | false | false | false | false false | null | false | null | null null | true | null | true | null null | false | false | null | null null | null | null | null | null ``` `NOT`은 참을 거짓으로, 거짓을 참으로, null을 null로 바꿉니다: ```psql SELECT a #>> '{}' AS a, notv::text AS "NOT a" FROM (UNWIND [true, false, null] AS a RETURN a, NOT a AS notv) q; ``` ``` a | NOT a -------+------- true | false false | true null | null ``` 그래서 `AND`는 한쪽이 거짓이면 곧바로 거짓이고, `OR`는 한쪽이 참이면 곧바로 참이며, 다른 쪽이 무엇이든 그렇습니다. null이 얽힌 그 밖의 모든 것은 null입니다. `IN`도 같은 규칙에서 따라옵니다. null을 담은 리스트에서 찾지 못한 값이라도 실은 거기 있었을 수 있으므로, 답은 거짓이 아니라 알 수 없음입니다. ```psql SELECT expr, res::text AS result FROM ( RETURN '2 IN [1, 2, 3]' AS expr, 2 IN [1,2,3] AS res UNION ALL RETURN '2 IN [1, null, 3]', 2 IN [1,null,3] UNION ALL RETURN '2 IN [1, 2, null]', 2 IN [1,2,null] UNION ALL RETURN '2 IN [1]', 2 IN [1] UNION ALL RETURN '2 IN []', 2 IN [] UNION ALL RETURN 'null IN [1, 2, 3]', null IN [1,2,3] UNION ALL RETURN 'null IN [1, null, 3]', null IN [1,null,3] UNION ALL RETURN 'null IN []', null IN [] ) q; ``` ``` expr | result ------------------------+-------- "2 IN [1, 2, 3]" | true "2 IN [1, null, 3]" | null "2 IN [1, 2, null]" | true "2 IN [1]" | false "2 IN []" | false "null IN [1, 2, 3]" | null "null IN [1, null, 3]" | null "null IN []" | false ``` 빈 리스트가 예외입니다. 그 안에는 아무것도 없으므로 null에 대해서도 답이 거짓입니다. {#syntax-expressions-that-yield-null} ### null을 내놓는 표현식 오류나 값이 아니라 null을 내놓는 표현식들입니다: | 표현식 | 이유 | | --- | --- | | `n.no_such_property` | 그 요소에 그런 속성이 없습니다. | | `[][0]`, `head([])` | 그 리스트에 그런 요소가 없습니다. | | `1 + null` | 알 수 없는 피연산자와의 산술입니다. | | `1 < null`, `null = null` | 알 수 없는 값과의 비교입니다. | | `sin(null)`, `toUpper(null)` | null을 주고 호출한 함수입니다. | ```cypher MATCH (m:movie {title: 'The Matrix'}) RETURN m.no_such_property AS missing_property, [][0] AS missing_element, head([]) AS head_of_empty, 1 + null AS arithmetic, 1 < null AS comparison, sin(null) AS function, null = null AS equality; ``` ``` missing_property | missing_element | head_of_empty | arithmetic | comparison | function | equality ------------------+-----------------+---------------+------------+------------+----------+---------- null | null | null | null | null | null | null ``` `IS NULL`이 있는 것은 `null = null`이 null이기 때문입니다. null을 검사하는 유일한 방법입니다. {#syntax-a-condition-takes-only-a-boolean} ### 조건은 불리언만 받는다 `WHERE`, `FILTER`, `CASE WHEN`과 그 밖의 모든 조건은 불리언만 받고 그 밖의 것은 받지 않습니다. `jsonb` 문자열·숫자·리스트·맵으로 평가되는 조건은 오류입니다: ```cypher CREATE GRAPH demo; SET graph_path = demo; CREATE VLABEL t; CREATE (:t {name: 'Jack'}); MATCH (n:t) WHERE n.name RETURN n.name; ``` ``` ERROR: cannot cast "Jack" (jsonb type string) to boolean ``` 그 오류는 조건을 평가하는 데서 나오므로, 오류가 이름으로 부르는 값은 실행기가 먼저 도달한 행의 값입니다. 애초에 `jsonb`가 아닌 조건은 그보다 앞서, 문장이 파싱될 때 거부됩니다: ```cypher MATCH (n:t) WHERE 1 RETURN n.name; ``` ``` ERROR: argument of WHERE must be type boolean, not type integer LINE 1: MATCH (n:t) WHERE 1 RETURN n.name; ^ ``` 뜻하는 검사를 그대로 쓰십시오. `WHERE n.name IS NOT NULL`은 그 속성이 있는지 묻습니다: ```cypher MATCH (n:t) WHERE n.name IS NOT NULL RETURN n.name AS name; ``` ``` name -------- "Jack" ``` `WHERE n.name <> ''`은 그것이 비어 있지 않은지 묻고, `WHERE n.active`는 그 속성이 실제로 불리언을 담고 있을 때 동작합니다. `jsonb` 불리언이 불리언으로 형 변환되기 때문입니다. null은 여전히 받아들여지고 SQL에서와 같이 동작합니다. 조건이 null인 행은 반환되지 않고 아무 오류도 나지 않습니다. 그래서 `WHERE n.no_such_property`는 아무 행도 반환하지 않습니다. ```{note} 이것은 비어 있지 않은 값을 조건으로 받아들였던 이전 릴리스와의 의도적인 호환성 단절입니다. 그런 방식으로 쓴 쿼리는 뜻하지 않은 것을 기준으로 걸러 내는 대신 실패합니다. 무엇을 고쳐야 하는지는 [Cypher 호환성](#cypher-compatibility-a-condition-takes-only-a-boolean)이 나열합니다. ``` {#syntax-compatibility} ## 호환성 {#syntax-opencypher} ### openCypher 다른 곳에서 Cypher를 알고 온 독자가 걸릴 어휘상의 차이가 세 가지 있습니다. * **식별자는 소문자로 접히고, 백틱은 인용 문자가 아닙니다.** 큰따옴표를 쓰십시오. `` `My Label` `` 은 구문 오류입니다. * **문자열 리터럴은 작은따옴표만 받습니다.** 큰따옴표는 식별자를 만듭니다. * **`//`는 주석이 아닙니다.** `--`나 `/* */`를 쓰십시오. `XOR`, `STARTS WITH`, `ENDS WITH`, `CONTAINS`, `=~`는 모두 있고, openCypher에서와 같은 뜻입니다. {#syntax-isoiec-39075} ### ISO/IEC 39075 이 레퍼런스의 표기법은 표준의 구문 생성 규칙과 같은 규약을 따르지만, 표준의 BNF는 아닙니다. `IS [NOT] UNKNOWN`은 불리언에 대한 null 검사를 표준이 표기하는 방식이고 `IS [NOT] NULL`과 함께 받아들여집니다. `XOR`도 그렇습니다. 둘 다 표준의 ``(ISO/IEC 39075:2024 §20.20)에 속합니다. `UNKNOWN`을 *값*으로 쓰면 구문 오류입니다. 나머지는 [GQL 적합성](../appendix/gql-conformance.md)을 참고하십시오. {#syntax-see-also} ## 관련 항목 - [데이터 타입](types.md) — `graphid`, `vertex`, `edge`, `graphpath`, 그리고 `jsonb` 속성 - [서버 설정](guc.md) — 모든 세션에 필요한 `graph_path`를 포함 - [키워드](../appendix/keywords.md) — 전체 키워드 목록과 단어별 범주 - [Cypher, GQL, SQL](../concepts/languages.md) — 어느 언어를 꺼내 쓸까 - [PostgreSQL: SQL 구문](https://www.postgresql.org/docs/18/sql-syntax.html) — 같은 렉서의 SQL 쪽 절반