使用下划线解析SQL Server编号文字

时间:2016-03-14 12:51:13

标签: sql sql-server tsql sql-server-2012

我想知道它为什么会起作用以及为什么它不会返回错误:

SELECT 2015_11

结果:

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

第二种情况:

SELECT 2.1_a

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

检查元数据:

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)     ║
╚══════╩══════════════════╝

虽然以字母开头的标识符表现得像我认为的那样:

SELECT a_11
-- Invalid column name 'a_11'.

LiveDemo

2 个答案:

答案 0 :(得分:9)

SQL将查询视为

SELECT 2015_11

as

SELECT 2015 _11 

的捷径
SELECT 2015 AS [_11]

SQL Server期望列名遵循一些命名约定规则,详见此MSDN link

  

变量,函数和存储过程的名称必须符合以下Transact-SQL标识符规则。   第一个字符必须是以下之一:

     
      
  1. Unicode标准3.2定义的字母。字母的Unicode定义包括从a到z的拉丁字符   A到Z,还有其他语言的字母。
  2.   
  3. 下划线(_),符号(@)或数字符号(#)。

         

    标识符开头的某些符号在SQL Server中具有特殊含义。以at开头的常规标识符   sign总是表示局部变量或参数,不能使用   作为任何其他类型对象的名称。开始的标识符   带数字符号表示临时表或过程。一个   以双数字符号(##)开头的标识符表示全局   临时对象。虽然数字符号或双数字符号   字符可用于开始其他类型对象的名称,   我们不推荐这种做法。

  4.         

    某些Transact-SQL函数的名称以符号(@@)的double开头。为避免与这些功能混淆,你不应该这样做   使用以@@。开头的名称。

SELECT的语法与MSDN类似

  

SELECT [ALL | DISTINCT] [TOP(表达式)[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])}]             |表达             [[AS] column_alias]            }         | column_alias = expression       } [,... n]

在这种情况下,SQL解析器首先检查表名,然后检查列名,Identity和rowguid,依此类推,直到它与

匹配。

<强> |表达[[AS] column_alias]

然后读取字面值直到下划线字符,当它意识到文字必须已经结束并开始将后面的字符解析为 Column_alias 而没有明确的AS

要验证此操作,请尝试在SQL Server中执行以下代码

SELECT 2015AS _11

这将产生与

相同的结果
SELECT 2015_11

另外要验证我刚才写的内容,请参阅SSMS的截图,该截图在AS

上执行代码突出显示

enter image description here

在您的第一个示例中,2015是整数字面值,在第二个示例中,2.1是十进制字面值

在第三个例子中,a不是有效的文字。如果你试试

SELECT 'a'_8

这会给你一些像

的结果
╔═════╗
║ _8  ║
╠═════╣
║ a   ║
╚═════╝

PS :你会发现这与#以及

的工作方式大致相同

所以SELECT 2015#11会给出类似的结果

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

答案 1 :(得分:3)

要了解发生的情况,您需要了解SQL Server接受的标识符。有许多规则,记录在案here。但是,重要的是:

  

第一个字符必须是以下之一:

     
      
  1. Unicode标准3.2定义的字母。字母的Unicode定义包括从a到z的拉丁字符   A到Z,还有其他语言的字母。

  2.   
  3. 下划线(_),符号(@)或数字符号(#)。

  4.   

重要的一点是,当SQL Server解析器遇到一个数字时,它会对自己说:&#34;这是一个数字&#34;。当它击中下划线时,它会说&#34;嗯,没有更多的数字,必须开始别的东西&#34;。解析器将第二个组件识别为有效标识符,因此将其视为:

select 2015 _11

用于列别名,即使没有as

相关问题