2017-10-10 7 views
3

Je travaillais sur du code SQL aujourd'hui où l'initiateur avait confondu l'alias d'une table, qui était la lettre l, mais ils avaient tapé avec le numéro 1.Entier comme alias SQL ne pas erreur, mais donne un résultat incorrect

Même si cette erreur avait été commise, le code était toujours exécuté.

Voici un exemple du code

SELECT l.[Name] 
     ,l.Address 
     ,1.Postcode 
FROM List l 

avec l'erreur étant le code 1.Postcode au lieu de l.Postcode

Les résultats sont sortis avec la colonne Code postal tous des 1, comme ci-dessous

Incorrect

Si l'erreur était d'utiliser t.Postcode alors il ld donne une erreur

L'identifiant en plusieurs parties "t.Postcode" n'a pas pu être lié.

Mais au lieu de erroring 1.Postcode est traité comme 1 AS Postcode

Correction de la ligne l.Postcode donne les données correctes, comme ci-dessous

Correct

Alors ma question est pourquoi ne pas la ligne 1.Postcode erreur?

+0

S'il vous plaît ajouter une balise de base de données. J'ai repoduit dans le serveur SQL, intrigant. – HoneyBadger

+0

SQL Server 2008 R2, vient d'ajouter la balise. C'est bizarre, n'est-ce pas? – ChrisM

+0

J'ai testé dans SQL Server 2014. Oui c'est bizarre. – HoneyBadger

Répondre

2

Votre syntaxe 1.Postcode est traitée par sql-server comme +1.0 AS Postcode

Il y a un malentendu, il jette aucune erreur parce qu'il n'y a pas d'erreur de lancer, et il donne le droit résultat ... pour cette syntaxe ..

Le problème principal ici est que l'espace entre la valeur de colonne et l'alias de colonne n'est pas obligatoire, et dans certaines circonstances, peut être omis.

SELECT de Microsoft docs:

SELECT [ ALL | DISTINCT ] 
[ TOP (expression) [ PERCENT ] [ WITH TIES ] ] 
<select_list> 
<select_list> ::= 
    { 
     * 
     | { 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 ] 

Comme vous pouvez le voir, compte tenu du point entre 1 et Postcode comme séparateur, 1 n'est pas un table_name, view_name, table_alias, nor a udt_column_name, il ne reste plus qu'à method_name et expression.
Mais 1.Postcode ne peut pas être un method_name (cannot start with a number), de sorte que votre cas est expression [ [ AS ] column_alias ]

où:

expression
est une constante, la fonction, toute combinaison de noms de colonnes, de constantes, et des fonctions connectées par un opérateur ou des opérateurs, ou une sous-requête.

Eh bien .. encore une fois, 1 ne peut pas être fonction ni un nom de Colum (cannot start with a number), il MUST être un constant.

le 1er caractère 1 est un nombre différent de 0 .. il ne peut être rien d'autre qu'un bit, integer, decimal or float constant, mais le 2ème caractère . limite seulement à la décimale et le flotteur constant.

Après la . nous avons P, il est pas un nombre .. et ce n'est pas E ou e (qui indique les constantes flottantes) nous avons donc trouvé une constante décimale.

Ce qui suit est pas AS (s'il vous plaît noter le vide après AS) afin qu'il puisse être l'alias de colonne, et Postcode est un alias de colonne valide .. nous avons donc notre nouvelle colonne, sa valeur est 1 (précisément 1.0) et son nom est Postcode

jeter un oeil à ces exemples et profiter:

select 
    1.Postcode_decimal, -- 1.0 AS Postcode_decimal 
    1.ePostcode_float, -- 1.0E0 AS Postcode_float 
    1.asPostcode_decimal, -- 1.0 AS asPostcode_decimal 
    1.as PostcodeAS_decimal, -- 1.0 AS PostcodeAS_decimal 
    1Postcode_int, -- 1 AS Postcode_int 
    1.+1.Postcode_expression, -- (1.0 + 1.0) AS Postcode_expression 
    1.%1.+1+0.-.0/.1e-1Postcode_more_complex_expr, -- (1.0 % 1.0) + 1 + (0.0/0.1E-1) AS Postcode_more_complex_expr 
    0xPostcode_varbin, -- 0x00 as Postcode_varbin 
    3.5[3.5], -- 3.5 AS [3.5] 
    'Hello'Postcode_varchar, 
    '1.0'[1.0], -- value is varchar, name is '1.0' 
    -- you can single quote an alias 
    22'Postcode_int2', 
    22'2.2', 
    -- but beware of two single quotes are treated as one literal single quote.. 
    'Hello''Postcode_varchar'_ -- yes, the underscore can be an identifier.. 
into 
    #test_alias 

SELECT * FROM #test_alias 

select column_ordinal, name, is_nullable, system_type_name, max_length, precision, source_column 
from sys.dm_exec_describe_first_result_set(N'SELECT * FROM #test_alias',null,1) 

drop table #test_alias 

Sorties:

Postcode_decimal Postcode_float asPostcode_decimal PostcodeAS_decimal Postcode_int Postcode_expression Postcode_more_complex_expr Postcode_varbin Postcode_varchar 1.0 Postcode_int2 2.2 _      3.5 
1     1    1     1     1    2     1       0x    Hello    1.0 22    22 Hello'Postcode_varchar 3.5 

et

column_ordinal name      is_nullable system_type_name max_length precision 
1    Postcode_decimal   0   numeric(1,0)  5   1   
2    Postcode_float    0   float    8   53   
3    asPostcode_decimal   0   numeric(1,0)  5   1   
4    PostcodeAS_decimal   0   numeric(1,0)  5   1   
5    Postcode_int    0   int     4   10   
6    Postcode_expression   1   numeric(2,0)  5   2   
7    Postcode_more_complex_expr 1   float    8   53   
8    Postcode_varbin    0   varbinary(1)  1   0   
9    Postcode_varchar   0   varchar(5)   5   0   
10    1.0       0   varchar(3)   3   0   
11    Postcode_int2    0   int     4   10   
12    2.2       0   int     4   10   
13    _       0   varchar(22)   22   0   
14    3.5       0   numeric(2,1)  5   2   
+0

Merci, j'ai apprécié les exemples – ChrisM

+1

heureux d'entendre :) – MtwStark