AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 217424
Accepted
James
James
Asked: 2018-09-13 11:35:45 +0800 CST2018-09-13 11:35:45 +0800 CST 2018-09-13 11:35:45 +0800 CST

为什么对象名称不能以数字开头?

  • 772

例如,如果我正在使用 name 创建视图'4aii',为什么 SQL Server 会关心它以 a 开头4?我可以打电话给桌子Fouraii或IVaii。

此外,[]在幕后做了什么来允许将任何字符串用作名称?

一根绳子就是一根绳子,amirite?

sql-server identifier
  • 5 5 个回答
  • 13429 Views

5 个回答

  • Voted
  1. mustaccio
    2018-09-13T12:01:38+08:002018-09-13T12:01:38+08:00

    首先,您需要区分数字(数字文字)、字符串(字符串文字)和标识符。'4aii'是一个字符串文字,它可以是某个“事物”的值,但它不标识(名称)一个事物。4aii或[4aii]将是标识符(如果允许的话)。

    查询解析器需要理解它正在查看的标记的含义。通过允许名称以数字开头,您通过扩展允许它们仅由数字组成。那么,给定select 12345 from mytable,您(和解析器)如何知道12345是整数文字还是列名?

    但是,如果您允许标识符仅以字母(或下划线字符)开头,您可以明确地说您是在查看标识符 ( abc123) 还是字符串文字 ( 'abc123') —— 后者用引号引起来。

    SQL Server 中的方括号、MySQL 中的反引号 (`) 和 ANSI SQL 兼容引擎中的双引号表示标识符,当您的标识符无法与其他标记区分开时,您可以使用它们:以数字开头,有空格或它们中的其他特殊字符等。因此,[4aii]或者"4aii"清楚地告诉解析器它正在处理一个标识符。

    一个小 dbfiddle 演示。

    • 20
  2. Best Answer
    Solomon Rutzky
    2018-09-13T21:32:49+08:002018-09-13T21:32:49+08:00

    一根绳子就是一根绳子,amirite?

    是和否:字符串是字符串,但对象/项目名称不是字符串。因此,尽管该陈述是正确的,但它也与您所看到的行为无关。

    忽略特定规则的概念推理,“为什么一个工作而不是另一个工作”的技术答案是 SQL Server 遵循(具有最少的定制),Unicode 标准的标识符指南。Unicode 文档可以在这里找到:

    Unicode® 标准附件 #31:UNICODE 标识符和模式语法

    未包含在其中的标识符[...]或者"..."是“常规”标识符,而包含在其中的标识符是“分隔”标识符。常规标识符是在所有上下文中都有效的名称(即,这些是用这种语言、软件等命名事物的规则)。定界标识符是其他一切:无效且不应工作的名称,但是,如果您将它们包装在其中任何一个定界符中,它们将获得豁免。大多数标识符都可以分隔;它只是GOTO不能分隔的标签和变量(包括表变量)/参数。区别似乎在于,纯粹为了在 T-SQL 语言中使用而存在的标识符(即不是一个将作为元数据存储在数据文件或日志文件中的名称)不能被分隔(就像你在任何语言)。

    现在,SQL Server 文档并不完全完整/正确,但它对来自 Unicode 3.2 的有效“标识符”字符(开始和继续)的分类是正确的。如果您想要常规标识符和分隔标识符的实际规则列表,我将它们记录在这里:

    完整的 T-SQL 标识符规则列表

    要查看证明 Unicode 3.2 分类与 SQL Server 接受的常规标识符之间关系的研究,请访问:

    1. Uni-Code:搜索 T-SQL 正则标识符的有效字符的真实列表,第 1 部分
    2. Uni-Code:搜索 T-SQL 正则标识符的有效字符的真实列表,第 2 部分

    解决对此答案的评论中指出的问题:

    1. 是的,甚至允许非分隔标识符以 , 和 开头_,#并且@ 在Unicode 规范中进行了说明。第 1.2 节介绍了对基本规则的自定义,甚至提供了四个示例自定义:_、#、@和$。这 4 个四个“潜在”自定义项与 SQL Server 使用的 4 个完全相同。因此,SQL Server 允许并且@Variable不#TempTable指向该 Unicode 文档作为规则的来源。
    2. 如上所述,SQL Server 文档确实声明所使用的分类来自 Unicode 字符数据库的 3.2 版,并且它们当前是 10 版。您不能使用 Unicode 网站上的Ident_*的当前定义,如表示有效/无效字符。Ident_Start每个新版本的Ident_ContinueUnicode 标准都添加了字符。查看与这些属性匹配的正确字符集的唯一方法是下载 Unicode 版本 3.2。
    3. 以上两点都在上面直接提到的两篇博客文章中进行了处理(名为“Uni-Code:搜索 T-SQL 正则标识符的有效字符的真实列表”)。在将此答案视为不正确之前,请阅读这两个帖子。这里实际发生的事情背后有很多细微差别,我在这两篇文章中提到,逐步展示了如何匹配有效字符列表。

    另外,关于标题中所述的问题,这取决于您对“数字”的定义松散程度。意思是,如果您按照上面直接提到的两篇文章中所示的研究步骤进行操作,这样您就创建了一个表来保存 Unicode Character Database v3.2 和一些其他属性,您可以获得 52 个非- 字母(主要是“数字”)是通过以下查询启动标识符的有效字符:

    SELECT ucd.*
    FROM   [v3-2].UnicodeCharacterDatabase ucd
    WHERE  ucd.[IDStart] = 1
    AND    ucd.[GeneralCategory] NOT LIKE 'L%';
    

    选择其中一些字符进行测试,我们可以看到它们确实有效:

    USE [tempdb];
    CREATE TABLE dbo.Ⅳaii ([Col1] INT); -- ROMAN NUMERAL FOUR (U+2163)
    
    CREATE TABLE dbo.ↂaii ([Col1] INT); -- ROMAN NUMERAL TEN THOUSAND (U+2182)
    
    CREATE TABLE dbo.〤aii ([Col1] INT); -- HANGZHOU NUMERAL FOUR (U+3024)
    

    而且,为了表明它们不仅仅是名称中的“数字”,以下查询证明它们被分配了一个数值(如表中的NumericValue列[v3-2].UnicodeCharacterDatabase所示:

    SELECT 1 WHERE N'〤' LIKE N'[3-5]'; -- HANGZHOU NUMERAL FOUR (U+3024)
    -- 1
    

    但是,它们不是可用于数值运算的数字:

    SELECT 〤 + 0;
    /*
    Msg 207, Level 16, State 1, Line 23
    Invalid column name '〤'.
    */
    

    关于解析和需要能够确定3e2是数字还是标识符的问题:虽然这是一个考虑因素,并且可能为什么数字被排除在“Ident_start”Unicode 通用类别之外,但它不是通用的,也不一定是为什么SQL Server 将它们排除在外。需要考虑的三点:

    1. 虽然3e2它本身是模棱两可的,但如果它至少有一个模式名称,那么它就不会是:dbo.3e2
    2. 这个名字4aii一点也不模棱两可。内部解析将能够很容易地将其识别为不是潜在数字
    3. MySQL / MariaDB没有这个限制。它们允许使用非分隔标识符,例如4aiiand 3e,但不允许使用3e2or 300。我能够在 MySQL 中成功执行以下操作:

      create table 4aii (3e int);
      

    同样,您不能在 SQL Server 中执行此操作的原因是 SQL Server 遵循 Unicode 标准对标识符的建议。没有具体说明为什么 Unicode 联盟选择了这些字符,但似乎至少是“最佳实践”。尽管如此,正如 MySQL 所证明的那样,可以解析以数字开头的标识符。

    • 17
  3. Evan Carroll
    2018-09-13T13:55:41+08:002018-09-13T13:55:41+08:00

    您正在观察的是实现的词法分析器规则。这是一个称为词法分析的过程的一部分,这是一种“理解事物”的奇特方式。理想情况下,这将遵守 SQL Spec ( <identifier>) 中给出的规则。这些规则均由 Microsoft 作为常规标识符规则发布。如果您希望使用不规则标识符,您必须将它们引用或将它们与其他标记(Tsql[]或双引号"")“分隔”,这消除了语法歧义的任何可能性。

    一根绳子就是一根绳子,amirite?

    不,以这个为例。

    “不,就以这个为例。”

    就这么一句话。但是,更重要的是5个字。你知道这是五个词,因为空格很重要。如果你要解析主题、对象和声音,你必须知道它是五个词,才能将其理解为指令。

    • 14
  4. Shadow
    2018-09-13T19:20:01+08:002018-09-13T19:20:01+08:00

    一个简单的例子,

    3e2
    

    那是字符串“3e2”吗?数字300?变量名?如果您指的是数字,却忘记了您3e2 = 500之前在脚本中写的内容怎么办?

    规则在那里,以便语法解析器可以理解您的意思。可能有像4aii您的问题中提到的那样不含糊的例子 - 但是有一部分标签是模棱两可的。因此,为了避免这种歧义,我们制定了这条规则。

    • 7
  5. david
    2019-12-09T17:32:07+08:002019-12-09T17:32:07+08:00

    在过去的 20 年中,我的视图名为

     530_all
    

    ...但后来我有时间编写一个 osql 脚本以从服务器(SQL Server 2000)中删除该视图(以及其他类似的视图):

    exec( 'DROP VIEW ' + @ONAME )
    

    除非引用这些名称,否则 DROP VIEW 将不起作用。

    和往常一样,对字符串连接以及 EXEC 和 QUOTENAME 的使用有一些神秘的限制。

    如果您的工具不允许您创建这样的对象名称……感谢您的小小怜悯。

    • 1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve