Как sysname = null в этой системной хранимой процедуре SQL Server, если sysname не может быть null? - PullRequest
0 голосов
/ 12 сентября 2018

Я прочитал, что sysname не может быть пустым , но в определении системной процедуры sp_grantdbaccess я вижу присвоение нуля одному из аргументов процедуры (если я прочитал это право). Как это может быть?

ALTER PROCEDURE [sys].[sp_grantdbaccess]
    @loginame   sysname,
    @name_in_db sysname = NULL OUT

1 Ответ

0 голосов
/ 12 сентября 2018

"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
...