>我读到sysname不能为空,但是在系统过程sp_grantdbaccess
的定义中,我看到将null分配给过程的一个参数(如果我没看错的话(。这怎么可能?
ALTER PROCEDURE [sys].[sp_grantdbaccess]
@loginame sysname,
@name_in_db sysname = NULL OUT
SYSNAME
不能NULL
"是不正确的。当链接问题的答案说它等效于默认NVARCHAR(128) NOT NULL
时是正确的 - 然后仅在列定义中有效。比较:
-- When not specified, columns are NULL
SET ANSI_NULL_DFLT_ON ON
-- Works
CREATE TABLE T(N NVARCHAR(128)); INSERT T DEFAULT VALUES; SELECT * FROM T
GO
DROP TABLE T
GO
-- When not specified, columns are NOT NULL
SET ANSI_NULL_DFLT_ON OFF
-- Error: can't insert NULL
CREATE TABLE T(N NVARCHAR(128)); INSERT T DEFAULT VALUES; SELECT * FROM T
GO
DROP TABLE T
GO
现在尝试与SYSNAME
相同的操作:
-- When not specified, columns are NULL
SET ANSI_NULL_DFLT_ON ON
-- Error: SYSNAME is NOT NULL, regardless of defaults
CREATE TABLE T(N SYSNAME); INSERT T DEFAULT VALUES; SELECT * FROM T
GO
DROP TABLE T
GO
但这并不意味着SYSNAME
不能NULL
,我们所要做的就是说它可能是:
-- Works
CREATE TABLE T(N SYSNAME NULL); INSERT T DEFAULT VALUES; SELECT * FROM T
GO
DROP TABLE T
GO
在使用类型(变量、存储过程参数(的几乎所有其他上下文中,我们无法指定NULL
或NOT NULL
并且始终允许NULL
值,因此此NOT NULL
元数据很少相关。上面的代码使用常规表并非偶然:如果您尝试使用表变量进行相同的操作,您会发现ANSI_NULL_DFLT_ON
被忽略,如果未指定,NULL
始终是列的默认值,因此唯一相关的情况是:
-- Can't insert NULL
DECLARE @T TABLE (N SYSNAME); INSERT @T DEFAULT VALUES; SELECT * FROM T@
GO
-- OK
DECLARE @T TABLE (N SYSNAME NULL); INSERT @T DEFAULT VALUES; SELECT * FROM @T
GO