所有这些都有效:
CREATE DATABASE [¯\_(ツ)_/¯];
GO
USE [¯\_(ツ)_/¯];
GO
CREATE SCHEMA [¯\_(ツ)_/¯];
GO
CREATE TABLE [¯\_(ツ)_/¯].[¯\_(ツ)_/¯]([¯\_(ツ)_/¯] NVARCHAR(20));
GO
CREATE UNIQUE CLUSTERED INDEX [¯\_(ツ)_/¯] ON [¯\_(ツ)_/¯].[¯\_(ツ)_/¯]([¯\_(ツ)_/¯]);
GO
INSERT INTO [¯\_(ツ)_/¯].[¯\_(ツ)_/¯]([¯\_(ツ)_/¯]) VALUES (N'[¯\_(ツ)_/¯]');
GO
CREATE VIEW [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[¯\_(ツ)_/¯];
GO
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @Shrug NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = @Shrug;
GO
EXEC [¯\_(ツ)_/¯].[¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @Shrug = N'[¯\_(ツ)_/¯]';
GO
但是您可能会看到我的意思:我不想要@Shrug,我想要@¯\_(ツ)_/¯
.
这些都不适用于 2008-2017 的任何版本:
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] @[¯\_(ツ)_/¯] NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = @[¯\_(ツ)_/¯];
GO
CREATE PROC [¯\_(ツ)_/¯].[sp_¯\_(ツ)_/¯] [@¯\_(ツ)_/¯] NVARCHAR(20) AS SELECT [¯\_(ツ)_/¯] FROM [¯\_(ツ)_/¯].[vw_¯\_(ツ)_/¯] WHERE [¯\_(ツ)_/¯] = [@¯\_(ツ)_/¯];
GO
那么,有没有办法使用 unicode 存储过程参数名称呢?
好吧,标识符总是 Unicode /
NVARCHAR
,所以从技术上讲,你不能创建任何没有 Unicode 名称的东西?。您在这里遇到的问题完全是由于所使用的字符的分类。常规(即非分隔)标识符的规则是:
我加粗了在这种情况下唯一重要的规则。“首字母”规则在这里不相关的原因是所有局部变量和参数中的首字母始终是“at 符号”
@
。并且要明确:什么被认为是“字母”和什么被认为是“十进制数字”是基于每个字符在 Unicode 字符数据库中分配的属性。Unicode 为每个字符分配了许多属性,例如:is_uppercase、is_lowercase、is_digit、is_decimal、is_combining 等。这不是我们凡人认为字母或十进制数字的问题,而是哪些字符被分配了这些属性。这些属性通常在正则表达式中用于匹配“标点符号”等。例如,
\p{Lu}
匹配任何大写字母(跨所有语言/脚本),并\p{IsDingbats}
匹配任何“Dingbats”字符。因此,在您尝试执行以下操作时:
只有
_
(下划线或“低线”)和ツ
(片假名字母 Tu U+30C4)字符符合这些规则。现在,其中的所有字符¯\_(ツ)_/¯
都可以用于分隔标识符,但不幸的是,变量/参数名称和标签似乎GOTO
无法分隔(尽管游标名称可以)。因此,对于变量/参数名称,由于它们无法分隔,因此您只能使用符合 Unicode 3.2 的“字母”或“十进制数字”的字符(好吧,根据文档;我需要测试如果分类已针对较新版本的 Unicode 进行了更新,因为分类的处理方式与排序权重不同)。
但是#1,事情并不像他们应该的那样直截了当。我现在已经能够完成我的研究,并且发现所述定义并不完全正确。哪些字符对常规标识符有效的精确(和可验证)定义是:
第一个字符:
_
(低线/下划线)或_
(全角低线)@
,但仅限于变量/参数#
,但如果是模式绑定对象,则仅适用于表和存储过程(在这种情况下,它们表明该对象是临时的)后续字符:
@
,#
, 或$
(有趣的事实:“ID_Start”和“ID_Continue”中的“ID”代表“标识符”。想象一下;-)
根据“Unicode 实用程序:UnicodeSet”:
有效的起始字符
[:Age=3.2:] & [:ID_Start=Yes:]
有效的连续字符
[:Age=3.2:] & [:ID_Continue=是:]
但是#2,即使搜索 Unicode 数据库也不是那么容易。这两个搜索确实为这些分类生成了一个有效字符列表,这些字符来自 Unicode 3.2,但是各种分类的定义随着 Unicode 标准的版本而变化。这意味着,Unicode v 10.0 中“ID_Start”的定义(该搜索今天使用的内容,2018-03-26)与Unicode v 3.2 中的定义不同。因此,在线搜索无法提供准确的列表。但是您可以获取 Unicode 3.2 数据文件并从那里获取“ID_Start”和“ID_Continue”字符列表,以与 SQL Server 实际使用的字符进行比较。我已经做到了这一点,并确认与我在上面“HOWEVER #1”中所述的规则完全匹配。
以下两篇博文详细介绍了查找确切字符列表所采取的步骤,包括导入脚本的链接:
最后,对于只想查看列表而不关心发现和验证它需要什么的人,您可以在此处找到:
完整的有效 T-SQL 标识符字符列表
(请给页面一点时间来加载;它是 3.5 MB 和近 47k 行)
关于“有效” ASCII 字符,例如
/
and-
,不起作用:该问题与字符是否也在 ASCII 字符集中定义无关。为了有效,该字符必须具有ID_Start
orID_Continue
属性,或者是为数不多的单独注明的自定义字符之一。有相当多的“有效” ASCII 字符(总共 128 个中的 62 个 - 主要是标点符号和控制字符)在“常规”标识符中无效。关于补充字符:虽然它们当然可以用于分隔标识符(并且文档似乎没有另外说明),但如果确实不能在常规标识符中使用它们,那很可能是由于它们没有得到完全支持在 SQL Server 2012 中引入 Supplementary Character-Aware Collations 之前的内置函数中(它们被视为两个单独的“未知”字符),在 100-级别排序规则(在 SQL Server 2008 中引入)。
关于 ASCII:这里没有使用 8 位编码,因为所有标识符都是 Unicode
NVARCHAR
// UTF-16 LE。该语句SELECT ASCII('ツ');
返回一个值为63
“?”的值。(尝试SELECT CHAR(63);
:)因为该字符,即使以大写“N”为前缀,也肯定不在代码页 1252 中。但是,该字符在韩语代码页中,即使没有“N”,它也会产生正确的结果" 前缀,在具有韩语默认排序规则的数据库中:关于影响结果的第一个字母:这是不可能的,因为局部变量和参数的第一个字母始终是
@
. 我们为这些名称控制的第一个字母实际上是名称的第二个字符。GOTO
关于为什么不能分隔局部变量名称、参数名称和标签:我怀疑这是因为这些项目是语言本身的一部分,而不是作为数据进入系统表的东西。我不认为是 Unicode 引起了问题。在局部变量或参数名称的情况下,该字符不是有效的 ASCII/Unicode 3.2 字符(并且变量/参数没有任何转义序列,就像其他实体类型一样)。
这批工作正常,它使用一个 Unicode 字符,根本不违反非分隔标识符的规则:
一旦你尝试使用斜杠或破折号,它们都是有效的 ASCII 字符,它会爆炸:
该文档没有说明为什么这些标识符受制于与所有其他标识符略有不同的规则,或者为什么它们不能像其他标识符一样被转义。