

# 데이터 정렬 제한 및 동작 차이점
<a name="collation.limitations"></a>

Babelfish는 데이터 정렬 지원을 위해 ICU 라이브러리를 사용합니다. PostgreSQL은 특정 버전의 ICU로 빌드되며 최대 한 버전의 데이터 정렬을 일치시킬 수 있습니다. 시간이 흐름에 따라 언어가 발전하면서 사소한 변형이 있는 것처럼 버전 간 변형은 피할 수 없습니다. 다음 목록에는 Babelfish 데이터 정렬의 알려진 제한 사항 및 동작 변형이 나와 있습니다.
+ **인덱스 및 데이터 정렬 유형 종속성** – International Components for Unicode(ICU) 데이터 정렬 라이브러리(Babelfish에서 사용하는 라이브러리)를 따르는 사용자 지정 유형의 인덱스는 라이브러리 버전이 변경되어도 무효화되지 않습니다.
+ **COLLATIONPROPERTY 함수** – 데이터 정렬 속성은 지원되는 Babelfish BBF 데이터 정렬에 대해서만 구현됩니다. 자세한 내용은 [Babelfish supported collations table](babelfish-collations.md#bfish-collations-table)을 참조하세요.
+ **유니코드 정렬 규칙 차이점** - SQL Server의 SQL 데이터 정렬은 유니코드로 인코딩된 데이터(`nchar` 및 `nvarchar`)를 유니코드로 인코딩되지 않은 데이터(`char` 및 `varchar`)와 다르게 정렬합니다. Babelfish 데이터베이스는 항상 UTF-8으로 인코딩되며, `char` 또는 `varchar`에 대한 정렬 순서가 `nchar` 또는 `nvarchar`에 대한 정렬 순서와 같도록 데이터 유형에 관계없이 항상 유니코드 정렬 규칙을 일관되게 적용합니다.
+ **2차와 동일한 데이터 정렬 및 정렬 동작** – 기본 ICU 유니코드 2차와 동일한(`CI_AS`) 데이터 정렬은 문장 부호 및 기타 영숫자가 아닌 문자를 숫자 문자 앞에 정렬하고 숫자 문자는 알파벳 문자 앞에 정렬합니다. 그러나 문장 부호 및 기타 특수 문자의 순서는 다릅니다.
+ **3차 데이터 정렬, ORDER BY용 차선책** – SQL 데이터 정렬(예: `SQL_Latin1_General_Pref_CP1_CI_AS`)은 `TERTIARY_WEIGHTS` 함수 및 `CI_AS` 데이터 정렬에서 균등하게 비교되는 문자열을 정렬하는 기능을 지원하여 `ABC`, `ABc`, `AbC`, `Abc`, `aBC`, `aBc`, `abC`, `abc`와 같이 먼저 대문자로 정렬되도록 합니다. 따라서 `DENSE_RANK OVER (ORDER BY column)` 분석 함수는 이러한 문자열을 동일한 순위를 갖는 것으로 평가하지만 파티션 내에서 먼저 대문자를 정렬합니다.

  `COLLATE` 절을 `@colCaseFirst=upper`를 지정하는 3차 `CS_AS` 데이터 정렬을 지정하는 `ORDER BY` 절에 추가하여 Babelfish와 비슷한 결과를 얻을 수 있습니다. 그러나 `colCaseFirst` 한정자는 `CI_AS` 데이터 정렬과 같이 2차와 동일한 문자열이 아닌 3차와 동일한 문자열에만 적용됩니다. 따라서 단일 ICU 데이터 정렬을 사용하여 3차 SQL 데이터 정렬을 에뮬레이션할 수 없습니다.

  해결 방법으로 먼저 `BBF_SQL_Latin1_General_CP1_CI_AS` 데이터 정렬을 사용하려면 `SQL_Latin1_General_Pref_CP1_CI_AS` 데이터 정렬을 사용하는 애플리케이션을 수정하는 것이 좋습니다. 그런 다음, `COLLATE BBF_SQL_Latin1_General_Pref_CP1_CS_AS`를 이 열의 `ORDER BY` 절에 추가합니다.
+ **문자 확장** – 문자 확장은 단일 문자를 기본 수준의 문자 시퀀스와 동일하게 취급합니다. SQL Server의 기본 `CI_AS` 데이터 정렬은 문자 확장을 지원합니다. ICU 데이터 정렬은 악센트를 구분하지 않는 데이터 정렬에 대해서만 문자 확장을 지원합니다.

  문자 확장이 필요한 경우 비교를 위해 `AI` 데이터 정렬을 사용합니다. 그러나 이러한 데이터 정렬은 현재 LIKE 연산자에서 지원되지 않습니다.
+ **char 및 varchar 인코딩** – SQL 데이터 정렬이 `char` 또는 `varchar` 데이터 유형에 사용되는 경우 ASCII 127 이전 문자의 정렬 순서는 해당 SQL 데이터 정렬에 대한 특정 코드 페이지에 따라 결정됩니다. SQL 데이터 정렬의 경우 `char` 또는 `varchar`로 선언된 문자열은 `nchar` 또는 `nvarchar`로 선언된 문자열과 다르게 정렬될 수 있습니다.

  PostgreSQL은 데이터베이스 인코딩으로 모든 문자열을 인코딩하므로 모든 문자를 UTF-8으로 변환하고 유니코드 규칙을 사용하여 정렬합니다.

  SQL 데이터 정렬은 유니코드 규칙을 사용하여 nchar 및 nvarchar 데이터 유형을 정렬하므로 Babelfish는 UTF-8을 사용하여 서버의 모든 문자열을 인코딩합니다. Babelfish는 유니코드 규칙을 사용하여 char 및 varchar 문자열을 정렬하는 것과 동일한 방식으로 nchar 및 nvarchar 문자열을 정렬합니다.
+ **보조 문자** – SQL Server 함수 `NCHAR`, `UNICODE`, `LEN`은 유니코드 기본 다국어 평면(BMP) 외부의 코드 포인트에 대한 문자를 지원합니다. 대조적으로 SC가 아닌 데이터 정렬은 서로게이트 쌍 문자를 사용하여 보조 문자를 처리합니다. 유니코드 데이터 형식의 경우 SQL Server는 UCS-2 또는 보조 문자를 사용하는 경우 전체 유니코드 범위(1,114,114자)를 사용하여 최대 65,535자를 나타낼 수 있습니다.
+ **가나 구분(KS) 데이터 정렬** - 가나 구분(KS) 데이터 정렬은 `Hiragana` 및 `Katakana` 일본어 가나 문자를 다르게 취급합니다. ICU는 일본 데이터 정렬 표준 `JIS X 4061`을 지원합니다. 이제 사용되지 않는 `colhiraganaQ [on | off]` 로캘 한정자는 KS 데이터 정렬과 동일한 기능을 제공할 수 있습니다. 그러나 SQL Server와 동일한 이름의 KS 데이터 정렬은 현재 Babelfish에서 지원하지 않습니다.
+ **전자/반자 구분(WS) 데이터 정렬** – 싱글바이트 문자(반자)와 더블바이트 문자(전자)로 표현되는 동일한 문자가 다르게 처리되는 경우의 데이터 정렬을 *전자/반자 구분(WS)*이라고 합니다. 그러나 SQL Server와 동일한 이름의 WS 데이터 정렬은 현재 Babelfish에서 지원하지 않습니다.
+ **변형 선택기 구분(VSS) 데이터 정렬** - 변형 선택기 구분(VSS) 데이터 정렬은 일본어 데이터 정렬 `Japanese_Bushu_Kakusu_140` 및 `Japanese_XJIS_140`에서 표의 문자 변형 선택기를 구분합니다. 변형 시퀀스는 기본 문자와 추가 변형 선택기로 구성됩니다. `_VSS` 옵션을 선택하지 않은 경우 변형 선택기는 비교 시 고려되지 않습니다.

  VSS 데이터 정렬은 현재 Babelfish에서 지원되지 않습니다.
+ **BIN 및 BIN2 데이터 정렬** – BIN2 데이터 정렬은 코드 포인트 순서에 따라 문자를 정렬합니다. UTF-8의 바이트별 이진 순서는 유니코드 코드 포인트 순서를 준수하므로 가장 성능이 좋은 데이터 정렬이 될 수 있습니다. 유니코드 코드 포인트 순서가 애플리케이션에서 작동하는 경우 BIN2 데이터 정렬을 사용하는 것이 좋습니다. 그러나 BIN2 데이터 정렬을 사용하면 문화적으로 예상치 못한 순서로 데이터가 클라이언트에 표시될 수 있습니다. 시간이 진행되면서 소문자에 대한 새로운 매핑이 유니코드에 추가되므로 `LOWER` 함수는 ICU의 다른 버전에서 다르게 수행될 수 있습니다. 이 경우는 BIN2 데이터 정렬과 관련된 문제가 아닌 좀 더 일반적인 데이터 정렬 버전 관리 문제의 특별한 경우입니다.

  Babelfish는 Babelfish 배포를 통해 `BBF_Latin1_General_BIN2` 데이터 정렬을 제공하여 유니코드 코드 포인트 순서로 정렬합니다. BIN 데이터 정렬에서는 첫 번째 문자만 wchar로 정렬됩니다. 나머지 문자는 해당 인코딩에 따라 코드 포인트 순서로 바이트별 정렬이 효과적으로 이뤄집니다. 이 방법은 유니코드 데이터 정렬 규칙을 따르지 않으며 Babelfish에서 지원하지 않습니다.
+ **비결정적 데이터 정렬 및 CHARINDEX 제한** - 버전 2.1.0 이전 Babelfish 릴리스의 경우 CHARINDEX를 비결정적 데이터 정렬과 함께 사용할 수 없습니다. 기본적으로 Babelfish는 대소문자를 구분하지 않는(비결정적) 데이터 정렬을 사용합니다. 이전 버전의 Babelfish에 CHARINDEX를 사용하면 다음과 같은 런타임 오류가 발생합니다.

  ```
  nondeterministic collations are not supported for substring searches
  ```
**참고**  
이 제한 사항 및 해결 방법은 Babelfish 버전 1.x(Aurora PostgreSQL 13.x 버전)에만 적용됩니다. Babelfish 2.1.0 이상 릴리스에는 문제가 발생하지 않습니다.

  이 문제를 해결하려면 다음 중 한 방법을 시도하면 됩니다.
  + 표현식을 대소문자를 구분하는 데이터 정렬로 명시적으로 변환하고 LOWER 또는 UPPER를 적용하여 두 인수를 모두 케이스 폴드(case-fold)합니다. 예를 들어 `SELECT charindex('x', a) FROM t1`은 다음이 됩니다.

    ```
    SELECT charindex(LOWER('x'), LOWER(a COLLATE sql_latin1_general_cp1_cs_as)) FROM t1
    ```
  + SQL 함수 f\$1charindex를 만들고 CHARINDEX 호출을 다음 함수에 대한 호출로 바꿉니다.

    ```
    CREATE function f_charindex(@s1 varchar(max), @s2 varchar(max)) RETURNS int
    AS
    BEGIN
    declare @i int = 1
    WHILE len(@s2) >= len(@s1)
    BEGIN
      if LOWER(@s1) = LOWER(substring(@s2,1,len(@s1))) return @i
      set @i += 1
      set @s2 = substring(@s2,2,999999999)
    END
    return 0
    END
    go
    ```