Por exemplo, se estou criando uma view com um name '4aii'
, por que o SQL Server se importa que comece com um 4
? Eu poderia chamar a mesa Fouraii
ou IVaii
.
Além disso, o que []
faz nos bastidores para permitir que qualquer string seja usada como um nome?
Uma corda é uma corda, amirita?
Em primeiro lugar, você precisa distinguir entre números (literais numéricos), strings (literais de string) e identificadores.
'4aii'
é uma string literal, que pode ser um valor de alguma "coisa", mas não identifica (nome) uma coisa.4aii
ou[4aii]
seriam identificadores (se fosse permitido).O analisador de consulta precisa entender o significado de um token que está sendo observado. Ao permitir que os nomes comecem com dígitos, você, por extensão, permite que eles consistam exclusivamente em dígitos. Então, dado
select 12345 from mytable
, como você (e o analisador) saberia se12345
é um literal inteiro ou o nome de uma coluna?No entanto, se você permitir que os identificadores comecem apenas com letras (ou caracteres de sublinhado), poderá dizer sem ambiguidade se estiver olhando para um identificador (
abc123
) ou uma string literal ('abc123'
) -- o último é colocado entre aspas.Colchetes no SQL Server, acentos graves (`) no MySQL e aspas duplas em mecanismos compatíveis com ANSI SQL, significam identificadores, e você os usa quando seus identificadores não podem ser facilmente distinguidos de outros tokens: comece com um dígito, tenha espaços ou outros caracteres especiais neles etc. Portanto,
[4aii]
ou"4aii"
diga claramente ao analisador que está lidando com um identificador.Uma pequena demonstração do dbfiddle.
Sim e Não: uma string é uma string, mas os nomes de objeto/item não são strings. Portanto, embora essa afirmação seja verdadeira, também não é relevante para o comportamento que você está vendo.
Ignorando o raciocínio conceitual para as regras específicas, a resposta técnica para "por que uma funciona e não a outra" é que o SQL Server segue (com personalização mínima), as diretrizes do Padrão Unicode para identificadores. A documentação do Unicode pode ser encontrada aqui:
Unicode® Standard Anexo nº 31: IDENTIFICADOR UNICODE E SINTAXE DE PADRÃO
Identificadores que não estão incluídos em nenhum
[...]
ou"..."
são identificadores "regulares", enquanto aqueles que estão incluídos são identificadores "delimitados". Identificadores regulares são nomes que são válidos em todos os contextos (isto é, estas são as regras para nomear coisas nesta linguagem, software, etc). Identificadores delimitados são todo o resto: nomes que não são válidos e não devem funcionar, no entanto, eles recebem uma isenção se você os envolver em qualquer um desses delimitadores. A maioria dos identificadores pode ser delimitada; é apenasGOTO
rótulos e variáveis (incluindo variáveis de tabela) / parâmetros que não podem ser delimitados. A diferença parece ser que os identificadores que existem puramente para uso na linguagem T-SQL (ou seja, não um nome que será armazenado em um arquivo de dados ou arquivo de log como metadados) não podem ser delimitados (tanto quanto você esperaria em qualquer língua).Agora, a documentação do SQL Server não está exatamente completa/correta, mas está correta sobre a classificação do que é um caractere "identificador" válido (inicial e contínuo) proveniente do Unicode 3.2. Se você quiser a lista real de regras para identificadores regulares e delimitados, eu os documentei aqui:
Lista Completamente Completa de Regras para Identificadores T-SQL
Para ver a pesquisa que comprova a relação entre as categorizações do Unicode 3.2 e o que o SQL Server aceita para identificadores regulares, visite:
Abordando as preocupações observadas nos comentários desta resposta:
_
,#
e@
é contabilizado na especificação Unicode. A seção 1.2 aborda as personalizações das regras básicas e ainda fornece quatro exemplos de personalizações:_
,#
,@
e$
. Essas 4 personalizações "potenciais" são exatamente as mesmas 4 que o SQL Server usa. Portanto, o SQL Server permite@Variable
e#TempTable
não aponta para fora deste documento Unicode como sendo a fonte das regras.Ident_Start
eIdent_Continue
em cada nova versão do Padrão Unicode. A única maneira de ver o conjunto correto de caracteres correspondentes a essas propriedades é fazer download do Unicode Versão 3.2.TAMBÉM, no que diz respeito à pergunta indicada no título, depende de quão frouxamente você define "número". Ou seja, se você seguir as etapas de pesquisa mostradas nas duas postagens mencionadas diretamente acima, de modo que tenha criado uma tabela para conter o Unicode Character Database v3.2 e algumas propriedades adicionais, poderá obter uma lista de 52 não -letras (principalmente "números") que são caracteres válidos para iniciar um identificador por meio da seguinte consulta:
Escolhendo alguns desses personagens para testar, podemos ver que eles realmente funcionam:
E, apenas para mostrar que eles são "números" em mais do que apenas seus nomes, a consulta a seguir prova que eles recebem um valor numérico (conforme mostrado na
NumericValue
coluna da[v3-2].UnicodeCharacterDatabase
tabela:No entanto, eles não são números que podem ser usados em operações numéricas:
Em relação à questão da análise e da necessidade de determinar se
3e2
é um número ou identificador: embora isso seja uma consideração, e possivelmente por que os números são excluídos da categoria geral Unicode "Ident_start", não é um universal, e não necessariamente por que O SQL Server os exclui. Três pontos a considerar:3e2
por si só seja ambíguo, se fosse qualificado com pelo menos um nome de esquema, não seria:dbo.3e2
4aii
não é realmente ambíguo. A análise interna seria capaz de identificar isso facilmente como não sendo um número potencialMySQL / MariaDB não tem essa restrição. Eles permitem identificadores não delimitados como
4aii
e3e
, mas não3e2
ou300
. Consegui executar com sucesso o seguinte no MySQL:Então, novamente, o motivo pelo qual você não pode fazer isso no SQL Server é porque o SQL Server adere à recomendação do Unicode Standard para identificadores. Por que esses caracteres foram escolhidos pelo Unicode Consortium não é especificamente declarado, mas parece ser pelo menos "melhor prática". Ainda assim, como comprovado com o MySQL, é possível analisar identificadores que começam com um número.
O que você está observando são as regras do lexer da implementação. É parte de um processo chamado análise léxica, que é uma maneira elegante de dizer "dar sentido às coisas". Idealmente, isso seguiria as regras fornecidas no SQL Spec (
<identifier>
). Essas regras são todas publicadas pela Microsoft como Regras para Identificadores Regulares . Se você deseja usar identificadores irregulares, você deve citá-los ou "delimitá-los" de outros tokens (Tsql's[]
ou aspas duplas""
) o que elimina qualquer possibilidade de sintaxe ambígua.Não, tome por exemplo isso.
Essa é uma frase. Mas, mais importante, são 5 palavras. Você sabe que são cinco palavras porque o espaço em branco é significativo. Você terá que saber que são cinco palavras se quiser analisar os assuntos, objetos e voz para entender isso como uma instrução.
Um exemplo rápido,
Essa é a string "3e2"? O número 300? Um nome de variável? E se você quis dizer o número e esqueceu que escreveu
3e2 = 500
anteriormente em seu script?A regra existe para que um analisador de sintaxe possa entender o que você quer dizer. Pode haver exemplos não ambíguos,
4aii
como os mencionados em suas perguntas, mas há um subconjunto de rótulos ambíguos. Então, para evitar essa ambiguidade, temos essa regra.Não tive problemas nos últimos 20 anos com uma visão chamada
... mas então eu tive o diabo de um tempo escrevendo um script osql para descartar essa visão (e outras semelhantes) do servidor (SQL Server 2000):
DROP VIEW não funcionaria a menos que esses nomes fossem citados.
E havia, como sempre, algumas restrições misteriosas sobre o uso de concatenação de strings e EXEC e QUOTENAME.
Se suas ferramentas não permitirem que você crie um nome de objeto como esse... seja grato por pequenas misericórdias.