Tudo isso funciona:
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
Mas você provavelmente pode ver onde estou indo com isso: eu não quero @Shrug, eu quero @¯\_(ツ)_/¯
.
Nenhum deles funciona em qualquer versão de 2008-2017:
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @[¯\_(ツ)_/¯] NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = @[¯\_(ツ)_/¯];
GO
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] [@¯\_(ツ)_/¯] NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = [@¯\_(ツ)_/¯];
GO
Então, existe uma maneira de usar nomes de parâmetros de procedimento armazenado unicode?
Bem, os identificadores são sempre Unicode /
NVARCHAR
, então tecnicamente você não pode criar nada que não tenha um nome Unicode ?.O problema que você está tendo aqui se deve inteiramente à classificação do(s) caractere(s) que está(ão) sendo usado(s). As regras para identificadores regulares (ou seja, não delimitados) são:
Coloquei em negrito as únicas regras que importam neste contexto. A razão pela qual as regras da "primeira letra" não são relevantes aqui é que a primeira letra em todas as variáveis e parâmetros locais é sempre a "arroba"
@
.E para ser claro: o que é considerado uma "letra" e o que é considerado um "dígito decimal" é baseado nas propriedades que cada caractere é atribuído no banco de dados de caracteres Unicode. O Unicode atribui muitas propriedades a cada caractere, como: is_uppercase, is_lowercase, is_digit, is_decimal, is_combining, etc, etc. Isso não é uma questão do que nós mortais consideraríamos letras ou dígitos decimais, mas quais caracteres receberam essas propriedades. Essas propriedades são frequentemente usadas em Expressões Regulares para corresponder à "pontuação", etc. Por exemplo,
\p{Lu}
corresponde a qualquer letra maiúscula (em todos os idiomas / scripts) e\p{IsDingbats}
corresponde a qualquer caractere "Dingbats".Então, na sua tentativa de fazer:
apenas os
_
caracteres (sublinhado ou "linha baixa") eツ
(Katakana Letter Tu U+30C4) se encaixam nessas regras. Agora, todos os caracteres¯\_(ツ)_/¯
são bons para identificadores delimitados, mas infelizmente parece que nomes eGOTO
rótulos de variáveis / parâmetros não podem ser delimitados (embora os nomes de cursor possam ser).Assim, para nomes de variáveis/parâmetros, uma vez que eles não podem ser delimitados, você está preso usando apenas caracteres que se qualificam como "letras" ou "dígitos decimais" a partir do Unicode 3.2 (bem, de acordo com a documentação; eu preciso testar se as classificações foram atualizadas para versões mais recentes do Unicode, pois as classificações são tratadas de maneira diferente dos pesos de classificação).
NO ENTANTO #1 , as coisas não são tão diretas quanto deveriam ser. Agora consegui completar minha pesquisa e descobri que a definição declarada não é totalmente correta. A definição precisa (e verificável) de quais caracteres são válidos para identificadores regulares é:
Primeiro personagem:
_
(linha baixa / sublinhado) ou_
(linha baixa de largura total)@
, mas apenas para variáveis/parâmetros#
, mas se for objeto vinculado ao esquema, então apenas para Tabelas e Procedimentos Armazenados (nesse caso, eles indicam que o objeto é temporário)Personagens subsequentes:
@
,#
ou$
(fato engraçado: o "ID" em "ID_Start" e "ID_Continue" significa "Identifier". Imagine isso ;-)
De acordo com "Utilitários Unicode: UnicodeSet":
Caracteres iniciais válidos
[:Idade=3.2:] & [:ID_Start=Sim:]
Caracteres de continuação válidos
[:Idade=3.2:] & [:ID_Continue=Sim:]
NO ENTANTO #2 , nem mesmo pesquisar no banco de dados Unicode pode ser tão fácil. Essas duas pesquisas produzem uma lista de caracteres válidos para essas categorizações, e esses caracteres são do Unicode 3.2, MAS as definições das várias categorizações mudam nas versões do Unicode Standard. Ou seja, a definição de "ID_Start" no Unicode v 10.0 (o que essa pesquisa está usando hoje, 2018-03-26) não é o que era no Unicode v 3.2. Portanto, a pesquisa online não pode fornecer uma lista exata. Mas você pode pegar os arquivos de dados Unicode 3.2 e pegar a lista de caracteres "ID_Start" e "ID_Continue" de lá para comparar com o que o SQL Server realmente usa. E eu fiz isso e confirmei uma correspondência exata com as regras que mencionei acima em "NOWEVER #1".
As duas postagens de blog a seguir detalham as etapas realizadas para encontrar a lista exata de caracteres, incluindo links para os scripts de importação:
Finalmente, para quem quer apenas ver a lista e não está preocupado com o que foi necessário para descobri-la e verificá-la, você pode encontrá-la aqui:
Lista Completamente Completa de Caracteres Identificadores T-SQL Válidos
(por favor, aguarde um momento para carregar a página; são 3,5 MB e quase 47k linhas)
Em relação aos caracteres ASCII "válidos", como
/
e-
, não funcionam: o problema não tem nada a ver com se os caracteres também são definidos no conjunto de caracteres ASCII. Para ser válido, o caractere precisa ter a propriedadeID_Start
ouID_Continue
ou ser um dos poucos caracteres personalizados anotados separadamente. Existem alguns caracteres ASCII "válidos" (62 do total de 128 — principalmente caracteres de pontuação e controle) que não são válidos em identificadores "regulares".Em relação aos caracteres suplementares: embora certamente possam ser usados em identificadores delimitados (e a documentação não parece indicar o contrário), se for verdade que eles não podem ser usados em identificadores regulares, é muito provável que eles não sejam totalmente suportados em funções internas anteriores aos agrupamentos com reconhecimento de caracteres suplementares foram introduzidos no SQL Server 2012 (eles são tratados como dois caracteres "desconhecidos" individuais), nem poderiam ser diferenciados um do outro em agrupamentos não binários anteriores ao 100- Agrupamentos de nível (introduzido no SQL Server 2008).
Em relação ao ASCII: as codificações de 8 bits não estão sendo usadas aqui, pois todos os identificadores são Unicode /
NVARCHAR
/ UTF-16 LE. A instruçãoSELECT ASCII('ツ');
retorna um valor63
que é um "?" (tente:SELECT CHAR(63);
) já que esse caractere, mesmo se prefixado com um "N" maiúsculo, certamente não está na página de código 1252. No entanto, esse caractere está na página de código coreana e produz o resultado correto, mesmo sem o "N " prefixo, em um banco de dados com um Collation padrão coreano:Em relação à primeira letra que afeta o resultado: isso não é possível, pois a primeira letra para variáveis e parâmetros locais é sempre
@
. A primeira letra que controlamos para esses nomes é, na verdade, o 2º caractere do nome.Em relação ao motivo pelo qual nomes de variáveis locais, nomes de parâmetros e
GOTO
rótulos não podem ser delimitados: eu suspeito que isso seja devido a esses itens serem parte da própria linguagem e não algo que encontrará seu caminho em uma tabela do sistema como dados.Não acho que seja o Unicode que está causando o problema; no caso de nomes de variáveis ou parâmetros locais, é que o caractere não é um caractere ASCII/Unicode 3.2 válido (e não há nenhuma seqüência de escape para variáveis/parâmetros como há para outros tipos de entidade).
Este lote funciona bem, usa um caractere Unicode que simplesmente não viola as regras para identificadores não delimitados:
Assim que você tenta usar uma barra ou um traço, ambos caracteres ASCII válidos, ele explode:
A documentação não explica por que esses identificadores estão sujeitos a regras ligeiramente diferentes de todos os outros identificadores ou por que eles não podem ser escapados como os outros.