如果SQL Server USER_NAME()是一个sysname,为什么它返回NVARCHAR(256)?

时间:2013-04-18 18:56:58

标签: sql-server

我正在使用一个列,我希望保留SQL Server 2008 R2中USER_NAME()函数的值。在BOL中,该函数被记录为返回类型为NVARCHAR(256)

然而,在其中一个例子中,他们这样做:

SELECT name FROM sysusers WHERE name = USER_NAME(1)

并且sysusers.name列的类型为sysname,这是(据我所知)有效的NVARCHAR(128) NOT NULL。这种不一致性在CURRENT_USER的文档中得到进一步巩固,该文档说“此函数等同于USER_NAME()”,但表明其类型为sysname(当然,它继续有一个示例,它使用CURRENT_USER作为VARCHAR(30)列的默认值...)

是什么给出的? BOL是否错误USER_NAME()的类型?我使用NVARCHAR(128)安全吗?

1 个答案:

答案 0 :(得分:10)

好吧,我们来看看:

SELECT name, system_type_id, user_type_id, max_length
  FROM sys.types WHERE name IN (N'sysname', N'nvarchar');

结果:

name      system_type_id  user_type_id  max_length
--------  --------------  ------------  ----------
nvarchar  231             231           8000
sysname   231             256           256

sysname只是nvarchar的别名类型,其中 字符数 为128(不是256)。 sys.types表示256的原因是nvarchar每个字符有2个字节 - 所以128个字符x 2个字节= 256个字节。它们与我们通常所做的“长度”并不意味着相同的事情。

没有人回答“为什么”BOL说的原因 - 联机丛书是错误的,就是这样。证明:

SELECT x = USER_NAME() INTO #foo;
EXEC tempdb..sp_help '#foo';

部分结果:

Column_name  Type      Length
-----------  --------  ------
x            nvarchar  256

-----------------------^^^
---- again, this is 128 characters

是的,您应该使用NVARCHAR(128)安全,但为了以防万一,它是否会花费您额外的费用来匹配文档?另请停止查看已弃用的系统表(如sysusers),以获取有关数据类型选择的指导并确认文档。虽然sys.database_principalssys.server_principals在这种情况下也使用sysname,但它们是检查SQL Server当前工作方式的更可靠的地方,除非您真正在研究SQL Server如何工作13+几年前。