2016-03-14 7 views
8

Mi chiedo perché funziona e perché non restituisce un errore:numero di analisi di SQL Server letterale con sottolineatura

SELECT 2015_11 

Risultato:

╔══════╗ 
║ _11 ║ 
╠══════╣ 
║ 2015 ║ 
╚══════╝ 

Secondo caso:

SELECT 2.1_a 

╔═════╗ 
║ _a ║ 
╠═════╣ 
║ 2.1 ║ 
╚═════╝ 

Verifica dei metadati:

SELECT name, system_type_name 
FROM sys.dm_exec_describe_first_result_set(
N'SELECT 2015_11', NULL, 0) 
UNION ALL 
SELECT name, system_type_name 
FROM sys.dm_exec_describe_first_result_set(
N'SELECT 3.2_a', NULL, 0) 

╔══════╦══════════════════╗ 
║ name ║ system_type_name ║ 
╠══════╬══════════════════╣ 
║ _11 ║ int    ║ 
║ _a ║ numeric(2,1)  ║ 
╚══════╩══════════════════╝ 

Mentre identificatore che inizia con la lettera si comporta come penso che dovrebbe:

SELECT a_11 
-- Invalid column name 'a_11'. 

LiveDemo

risposta

9

SQL tratta domanda come

SELECT 2015_11 

come

SELECT 2015 _11 

che è scorciatoia per

SELECT 2015 AS [_11] 

SQL Server prevede i nomi delle colonne di seguire alcune regole di denominazione di convenzione come descritto in questo MSDN link

The names of variables, functions, and stored procedures must comply with the following rules for Transact-SQL identifiers. The first character must be one of the following:

  1. A letter as defined by the Unicode Standard 3.2. The Unicode definition of letters includes Latin characters from a through z, from A through Z, and also letter characters from other languages.
  2. The underscore (_), at sign (@), or number sign (#).

    Certain symbols at the beginning of an identifier have special meaning in SQL Server. A regular identifier that starts with the at sign always denotes a local variable or parameter and cannot be used as the name of any other type of object. An identifier that starts with a number sign denotes a temporary table or procedure. An identifier that starts with double number signs (##) denotes a global temporary object. Although the number sign or double number sign characters can be used to begin the names of other types of objects, we do not recommend this practice.

Some Transact-SQL functions have names that start with double at signs (@@). To avoid confusion with these functions, you should not use names that start with @@.

Anche la sintassi per SELECT secondo MSDN è come

SELECT [ ALL | DISTINCT ] [ TOP (expression) [ PERCENT ] [ WITH TIES ] ] ::= { * | { table_name | view_name | table_alias }.* | { [ { table_name | view_name | table_alias }. ] { column_name | $IDENTITY | $ROWGUID } | udt_column_name [ { . | :: } { { property_name | field_name } | method_name (argument [ ,...n]) } ] | expression [ [ AS ] column_alias ] } | column_alias = expression } [ ,...n ]

In questo caso il parser SQL controlla prima il nome della tabella, quindi il nome della colonna, Identity e rowguid e così via finché raggiunge la corrispondenza con

| espressione [[AS] column_alias]

E poi legge il valore letterale fino a carattere di sottolineatura che è quando si rende conto che letterale devono essere stati completati e inizia l'analisi dei personaggi più tardi come column_alias senza il più esplicito AS

Per verificare questo prova seguente codice in SQL Server

SELECT 2015AS _11 

questo produrrà stessi risultati

SELECT 2015_11 

anche per verificare ciò che ho appena scritto sopra vedere lo screenshot da SSMS che fa un codice di evidenziazione AS

enter image description here

Nel vostro primo esempio 2015 è integer letterale e nel secondo esempio 2.1 è decimale letterale

Nel terzo esempio a non è un valore letterale valido. Se si tenta

SELECT 'a'_8 

Questo vi darà risultato simile

╔═════╗ 
║ _8 ║ 
╠═════╣ 
║ a ║ 
╚═════╝ 

PS: Vedrai che questo funziona più o meno allo stesso modo con # così

Così SELECT 2015#11 sarà dare risultati simili

╔══════╗ 
║ #11 ║ 
╠══════╣ 
║ 2015 ║ 
╚══════╝ 
+0

Potrebbe fornire alcuni documenti su questo comportamento? Sono d'accordo che potrebbe essere il caso, ma dovrebbe essere menzionato da qualche parte. – lad2025

+0

Underscore triggs "next token" dallo scanner. I.e letterale 2015 seguito da (spazio vuoto mancante) e poi _11 (alias colonna valida). – jarlh

3

A und per capire cosa sta succedendo, è necessario capire cosa SQL Server accetta come identificatori. Ci sono molte regole, che sono documentate here. Ma, l'importante è:

The first character must be one of the following:

  1. A letter as defined by the Unicode Standard 3.2. The Unicode definition of letters includes Latin characters from a through z, from A through Z, and also letter characters from other languages.

  2. The underscore (_), at sign (@), or number sign (#).

Il punto importante è che quando il parser SQL Server rileva una cifra, che dice a se stesso: "Questo è un numero". Quando colpisce il trattino basso, dice "Bene, non più numero, deve iniziare qualcos'altro". Il parser riconosce il secondo componente come un identificatore valido, quindi questa viene trattata come:

select 2015 _11 

che è per un alias di colonna, anche senza la as.

Problemi correlati