유니 코드 매개 변수 및 변수 이름을 만드는 방법


53

이 모든 것이 작동합니다.

CREATE DATABASE [¯\_(ツ)_/¯];
GO
USE [¯\_(ツ)_/¯];
GO
CREATE SCHEMA [¯\_(ツ)_/¯];
GO
CREATE TABLE [¯\_(ツ)_/¯].[¯\_(ツ)_/¯]([¯\_(ツ)_/¯] NVARCHAR(20));
GO
CREATE UNIQUE CLUSTERED INDEX [¯\_(ツ)_/¯] ON [¯\_(ツ)_/¯].[¯\_(ツ)_/¯]([¯\_(ツ)_/¯]);
GO
INSERT INTO [¯\_(ツ)_/¯].[¯\_(ツ)_/¯]([¯\_(ツ)_/¯]) VALUES (N'[¯\_(ツ)_/¯]');
GO
CREATE VIEW [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[¯\_(ツ)_/¯];
GO
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @Shrug NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = @Shrug;
GO
EXEC [¯\_(ツ)_/¯].[¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @Shrug = N'[¯\_(ツ)_/¯]';
GO

그러나 당신은 아마도 내가 어디로 가고 있는지 알 수 있습니다 : 나는 @Shrug을 원하지 않습니다 @¯\_(ツ)_/¯.

2008-2017의 모든 버전에서 이러한 기능이 작동하지 않습니다.

CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @[¯\_(ツ)_/¯] NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = @[¯\_(ツ)_/¯];
GO
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] [@¯\_(ツ)_/¯] NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = [@¯\_(ツ)_/¯];
GO

유니 코드 저장 프로 시저 매개 변수 이름을 사용하는 방법이 있습니까?

답변:


44

식별자는 항상 유니 코드 / NVARCHAR이므로 기술적으로 유니 코드 이름이없는 것을 만들 수 없습니다.

여기서 겪고있는 문제는 전적으로 사용중인 캐릭터의 분류 때문입니다. 일반 (즉, 구분되지 않은) 식별자에 대한 규칙 은 다음과 같습니다.

  • 첫 글자는 다음과 같아야합니다.
    • 유니 코드 표준 3.2에 의해 정의 된 문자.
    • 밑줄 (_), 부호 (@) 또는 숫자 부호 (#)
  • 후속 문자는 다음과 같습니다.
    • 유니 코드 표준 3.2에 정의 된 문자
    • 기본 라틴어 또는 기타 국가 대본의 십진수입니다.
    • 밑줄 (_), 기호 (@), 숫자 기호 (#) 또는 달러 기호 ($)
  • 공백이나 특수 문자는 사용할 수 없습니다.
  • 보충 문자는 허용되지 않습니다.

이 맥락에서 중요한 유일한 규칙을 굵게 표시했습니다. 여기서 "첫 글자"규칙이 관련이없는 이유는 모든 지역 변수 및 매개 변수의 첫 글자가 항상 "at 부호"이기 때문 @입니다.

그리고 "문자"로 간주되고 "소수"로 간주되는 것은 각 문자가 유니 코드 문자 데이터베이스에 할당 된 속성 을 기반으로합니다 . 유니 코드는 is_uppercase, is_lowercase, is_digit, is_decimal, is_combining 등과 같은 각 문자에 많은 속성을 할당합니다. 이것은 필멸자가 문자 나 십진수를 고려하는 것이 아니라 어떤 속성에 할당 된 문자인지는 중요하지 않습니다. 이러한 속성은 정규 표현식에서 "문장"등에 일치시키기 위해 자주 사용됩니다. 예를 들어, \p{Lu}대문자 (모든 언어 / 스크립트에서)와 \p{IsDingbats}일치하고 "Dingbats"문자 와 일치합니다.

따라서 시도하려는 경우 :

DECLARE @¯\_(ツ)_ INT;

단지는 _밑줄 (또는 "낮은 라인")와 문자는 그 규칙에 맞게 (가타카나 문자 화 U + 30C4). 이제 모든 문자는 ¯\_(ツ)_/¯구분 된 식별자에 적합하지만 불행히도 변수 / 매개 변수 이름과 GOTO레이블을 구분 할 수없는 것으로 보입니다 (커서 이름은 가능하지만).

따라서 변수 / 매개 변수 이름의 경우 구분 할 수 없으므로 유니 코드 3.2에서 "문자"또는 "소수 자릿수"로 자격이되는 문자 만 사용하고 있습니다 (문서에 따르면 잘 테스트해야합니다. 분류가 정렬 가중치와 다르게 처리되므로 최신 버전의 유니 코드에 대한 분류가 업데이트 된 경우)

그러나 # 1 은 상황이 간단하지 않습니다. 나는 이제 내 연구를 완료 할 수 있었고 명시된 정의가 완전히 정확하지 않다는 것을 발견했다. 일반 식별자에 유효한 문자의 정확한 (확인 가능한) 정의는 다음과 같습니다.

  • 첫 캐릭터 :

    • 유니 코드 3.2 에서 "ID_Start"로 분류 된 모든 문자 일 수 있습니다 ( "문자"뿐만 아니라 "문자 숫자"도 포함)
    • 일 수 _(저 라인 / 밑줄) 또는 _(전각 낮은 선)
    • 될 수 @있지만, 단지 변수 / 매개 변수
    • 가능 #하지만 스키마 바운드 개체 인 경우 테이블 및 저장 프로 시저에 대해서만 가능합니다 (이 경우 개체가 임시임을 나타냅니다)
  • 후속 문자 :

    • 유니 코드 3.2 에서 "ID_Continue"( "10 진"숫자를 포함하지만 "간격 및 비 간격 조합 표시"및 "구두 부호 연결"포함)로 분류 모든 항목이 될 수 있습니다.
    • 일 수있다 @, #또는$
    • 유니 코드 3.2 에서 형식 제어 문자로 분류 26 자 중 하나 일 수 있습니다.

(재미있는 사실 : "ID_Start"및 "ID_Continue"의 "ID"는 "식별자"를 나타냅니다. ;-)

"유니 코드 유틸리티 : UnicodeSet"에 따르면 :

  • 유효한 시작 문자

    [: 나이 = 3.2 :] & [: ID_Start = 예 :]

    -- Test one "Letter" from each of 10+ languages, as of Unicode 3.2
    DECLARE @ᔠᑥᑒᏯשፙᇏᆇᄳᄈლဪඤagೋӁウﺲﶨ   INT;
    -- works
    
    
    -- Test a Supplementary Character that is a "Letter" as of Unicode 3.2
    DECLARE @𝒲 INT;-- Mathematical Script Capital W (U+1D4B2)
    /*
    Msg 102, Level 15, State 1, Line XXXXX
    Incorrect syntax near '0xd835'.
    */
  • 유효한 연속 문자

    [: 연령 = 3.2 :] & [: ID_Continue = 예 :]

    -- Test various decimal numbers, but none are Supplementary Characters
    DECLARE @६৮༦൯௫୫9 INT;
    -- works (including some Hebrew and Arabic, which are right-to-left languages)
    
    
    -- Test a Supplementary Character that is a "decimal" number as of Unicode 3.2
    DECLARE @𝟜 INT; -- MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR (U+1D7DC)
    /*
    Msg 102, Level 15, State 1, Line XXXXX
    Incorrect syntax near '0xd835'.
    */
    -- D835 is the first character in the surrogate pair D835 DFDC that makes up U+1D7DC

그러나 유니 코드 데이터베이스를 검색하는 것조차 쉽지 않습니다. 이 두 가지 검색은 해당 분류에 유효한 문자 목록을 생성하며 해당 문자는 유니 코드 3.2에서 나온 것이지만 다양한 분류의 정의는 유니 코드 표준 버전에 따라 변경됩니다. 즉, 유니 코드 v 10.0 (현재 검색에서 사용중인 2018-03-26)에서 "ID_Start"의 정의는 유니 코드 v 3.2의 정의 가 아닙니다 . 따라서 온라인 검색에서 정확한 목록을 제공 할 수 없습니다. 그러나 유니 코드 3.2 데이터 파일을 가져 와서 "ID_Start"및 "ID_Continue"문자 목록을 가져 와서 SQL Server가 실제로 사용하는 것과 비교할 수 있습니다. 그리고 나는 이것을하고 "HOWEVER # 1"에서 위에서 언급 한 규칙과 정확히 일치 함을 확인했습니다.

다음 두 블로그 게시물은 가져 오기 스크립트에 대한 링크를 포함하여 정확한 문자 목록을 찾기 위해 수행 된 단계를 자세히 설명합니다.

  1. The Uni-Code : T-SQL 정규 식별자의 유효한 문자 목록 검색, 1 부
  2. 유니 코드 : T-SQL 정규 식별자에 대한 유효한 문자 목록 검색, 2 부

마지막으로, 목록을보고 싶어하고 목록을 발견하고 확인하는 데 관심이없는 사람은 여기에서 찾을 수 있습니다.

유효한 T-SQL 식별자 문자의 완전 전체 목록
(페이지를로드하는 순간을 적어주세요, 그것은 3.5 MB 거의 47K 라인입니다)


/and와 같은 "유효한"ASCII 문자와 관련하여 -작동하지 않음 : ASCII 문자 세트에 문자가 정의되어 있는지 여부와는 문제가 없습니다. 유효하려면 문자에 ID_Start또는 ID_Continue속성이 있거나 별도로 언급 된 몇 가지 사용자 지정 문자 중 하나 여야합니다. "일반"식별자에는 유효하지 않은 "유효한"ASCII 문자 (총 128 개 중 62 개 (대부분 문장 부호 및 제어 문자) 중 62 개)가 있습니다.

보충 문자와 관련하여 : 구분 된 식별자로 확실히 사용할 수 있지만 문서가 달리 명시하지 않는 것처럼 보이지만 정규 식별자로 사용할 수없는 것이 사실이라면 완전히 지원되지 않기 때문에 가능합니다. 보충 문자 인식 데이터 정렬 이전의 기본 제공 함수는 SQL Server 2012에 도입되었으며 (두 개의 개별 "알 수없는"문자로 취급 됨) 100-100 이전의 비 이진 데이터 정렬에서 서로 구별 될 수도 없습니다. 데이터 정렬 수준 (SQL Server 2008에서 도입)

ASCII 관련 : 모든 식별자가 유니 코드 NVARCHAR// UTF-16 LE 이므로 8 비트 인코딩은 여기에서 사용되지 않습니다 . 명령문 SELECT ASCII('ツ');63"?" 값을 리턴합니다. (try SELECT CHAR(63);:) 문자 앞에 대문자 "N"이 붙어 있어도 코드 페이지 1252에는없는 것이 확실합니다. 그러나 해당 문자는 한국어 코드 페이지에 있으며 "N 없이도 올바른 결과를 생성합니다. 한국어 기본 데이터 정렬이있는 데이터베이스에서 "접두사 :

SELECT UNICODE('ツ'); -- 12484

결과에 영향을 미치는 첫 글자와 관련하여 : 지역 변수 및 매개 변수의 첫 글자는 항상이므로 불가능합니다 @. 우리가이 이름들을 통제 할 첫 글자는 실제로 이름의 두 번째 문자입니다.

로컬 변수 이름, 매개 변수 이름 및 GOTO레이블을 구분할 수없는 이유와 관련하여 :이 항목이 언어 자체의 일부이기 때문에 시스템 테이블에 데이터로 들어가는 것이 아니라고 생각합니다.


고마워요 이로 인해 훌륭한 블로그 게시물을 만들게되었습니다. gist.github.com/BrentOzar/9b08b5ab2b617847dbe4aa0297b4cd5b
Brent Ozar

8
@BrentOzar 최근에 CT 스캔을 받았습니까?
Ross Presser

와우, 그것은 꽤 인상적인 대답입니다! 그리고 나는 Ross Presser의 발언을 두 번째로합니다.
SQL Nerd

22

문제를 일으키는 것이 유니 코드라고 생각하지 않습니다. 로컬 변수 또는 매개 변수 이름의 경우 문자가 유효한 ASCII / 유니 코드 3.2 문자가 아니며 다른 엔터티 유형과 마찬가지로 변수 / 매개 변수에 대한 이스케이프 시퀀스가 ​​없습니다.

이 배치는 정상적으로 작동하며, 구분되지 않은 식별자에 대한 규칙을 위반하지 않는 유니 코드 문자를 사용합니다.

CREATE OR ALTER PROCEDURE dbo.[💩]
  @ツ int
AS
  CREATE TABLE [#ツ] (ツ int);
  INSERT [#ツ](ツ) SELECT @ツ;
  SELECT +1 FROM [#ツ];
GO
EXEC dbo.[💩] @ツ = 1;

유효한 ASCII 문자 인 슬래시 또는 대시를 사용하려고하면 다음과 같이 폭탄이 적용됩니다.

Msg 102, Level 15, State 1, Procedure 💩 Incorrect syntax near '-'.

이 설명서에는 이러한 식별자가 다른 모든 식별자와 약간 다른 규칙을 따르는 이유 또는 다른 식별자와 같이 이스케이프 할 수없는 이유는 다루지 않습니다.


안녕 아론 여기에 몇 가지 요점을 명확히하기 위해 : 1) 첫 번째 문자는 실제로 @var / param 이름 이므로 첫 번째 문자는 문제가되지 않습니다 . 작동하지 않는 문자는 유효한 문자가 앞에 있어도 어떤 위치에서도 작동하지 않아야합니다. 2) 의사는 보충 문자를 일반 식별자 (사용하려는 모든 경우에 해당되는 것처럼 보일 수는 없음) 만 사용할 수 있지만 공백이있는 것처럼 구분 된 식별자에는 제한을 두지 않습니다. 또한 이들은 DB의 것이 아니라 T-SQL 언어의 일부이기 때문에 이것들이 다르다고 생각합니다.
Solomon Rutzky 2015 년

@ SolooloRutzky 문제는 간단하고 전적으로 매개 변수 이름을 다른 엔터티처럼 구분할 수없는 것 같습니다. 매개 변수 이름을 대괄호 또는 큰 따옴표로 묶을 수 있으면이 위치에 문자를 넣을 수 있습니다. 이 질문은 매개 변수 이름에 유니 코드 문자를 사용할 수 없으며 분명히 그렇지 않습니다. 사용할 있는 유니 코드 문자 와 사용할 수없는 일부 ASCII 문자가 있습니다 .
Aaron Bertrand

예, 변수 / 매개 변수 이름과 GOTO레이블을 구분할 수있는 경우 길이 만 제한 한다는 데 동의합니다 . 이러한 소수의 항목을 구문 분석 및 / 또는 처리하는 것은 다른 수준에서 발생하거나 구분 된 값을 허용 할 수없는 다른 제약 조건이 있다고 가정 할 수 있습니다. 적어도 나는 그것이 임의적이거나 감독 적이 지 않기를 바랍니다.
Solomon Rutzky

(내가 얼마 전에 대답했을 때 의견에 대한 업데이트를 보지 못했습니다). 예, 질문은 OP가 유니 코드 문자를 사용할 수 없다는 것을 암시하지만 모든 이름이 항상 유니 코드 / NVARCHAR이므로 질문 문구가 기술적으로 잘못되었습니다. 여기서 사용되지 않는 8 비트 인코딩이므로 ASCII와 아무 관련이 없습니다. 여기에있는 모든 문자는 다양한 8 비트 코드 페이지에도 존재하더라도 유니 코드 문자입니다. 내 대답에서 설명했듯이 사용할 수있는 문자는 어느 문자에 is_alphabetic또는 태그가 붙어 있는지에 대한 문제입니다 numeric_type=decimal.
Solomon Rutzky 2016 년

나는 똥으로 가득 찬 저장된 procs를 보았지만 결코 이름을 짓지 않았습니다!
Mitch Wheat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.