AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 201598
Accepted
Brent Ozar
Brent Ozar
Asked: 2018-03-19 08:47:38 +0800 CST2018-03-19 08:47:38 +0800 CST 2018-03-19 08:47:38 +0800 CST

Como criar parâmetros Unicode e nomes de variáveis

  • 772

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?

sql-server t-sql
  • 2 2 respostas
  • 5727 Views

2 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2018-03-19T12:51:12+08:002018-03-19T12:51:12+08:00

    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:

    • A primeira letra deve ser:
      • Uma letra conforme definido pelo Unicode Standard 3.2.
      • sublinhado (_), arroba (@) ou sinal de número (#)
    • As letras subsequentes podem ser:
      • Letras conforme definido no Padrão Unicode 3.2.
      • Números decimais do latim básico ou de outros scripts nacionais.
      • sublinhado (_), arroba (@), sinal numérico (#) ou cifrão ($)
    • Espaços incorporados ou caracteres especiais não são permitidos.
    • Caracteres suplementares não são permitidos.

    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:

    DECLARE @¯\_(ツ)_/¯ INT;
    

    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 e GOTOró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:

      • Pode ser qualquer coisa classificada em Unicode 3.2 como "ID_Start" (que inclui "Letras", mas também "caracteres numéricos semelhantes a letras")
      • Pode ser _(linha baixa / sublinhado) ou _(linha baixa de largura total)
      • Pode ser @, mas apenas para variáveis/parâmetros
      • Pode ser #, 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:

      • Pode ser qualquer coisa classificada em Unicode 3.2 como "ID_Continue" (que inclui números "decimais", mas também "marcas de combinação de espaçamento e não espaçamento" e "marcas de pontuação de conexão")
      • Pode ser @, #ou$
      • Pode ser qualquer um dos 26 caracteres classificados em Unicode 3.2 como caracteres de controle de formato

    (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:]

      -- Test one "Letter" from each of 10+ languages, as of Unicode 3.2
      DECLARE @ᔠᑥᑒᏯשፙᇏᆇᄳᄈლဪඤaൌgೋӁウﺲﶨ   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'.
      */
      
    • Caracteres de continuação válidos

      [:Idade=3.2:] & [:ID_Continue=Sim:]

      -- 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
      

    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:

    1. O Uni-Code: a busca pela lista verdadeira de caracteres válidos para identificadores regulares T-SQL, parte 1
    2. O Uni-Code: a busca pela lista verdadeira de caracteres válidos para identificadores regulares T-SQL, parte 2

    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 propriedade ID_Startou ID_Continueou 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ção SELECT ASCII('ツ');retorna um valor 63que é 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:

    SELECT UNICODE('ツ'); -- 12484
    

    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 GOTOró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.

    • 44
  2. Aaron Bertrand
    2018-03-19T09:04:30+08:002018-03-19T09:04:30+08:00

    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:

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

    Assim que você tenta usar uma barra ou um traço, ambos caracteres ASCII válidos, ele explode:

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

    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.

    • 22

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve