为什么IS NOT NULL在SQL Server中为Varchar(max)返回NULL值?

Col*_*lin 27 sql-server sql-server-2005

这是查询:

  1. 看起来列表中出现了一些NULL值.
  2. 一些NULL值被查询过滤掉.我检查过.
  3. 如果我添加AND AdditionalFields = '',这两个结果仍然返回
  4. AdditionalFields是一个varchar(最大)
  5. 数据库是SQL Server 10,兼容级别= Sql Server 2005(90)
  6. 我正在使用Management Studio 2008

我似乎有空字符串,其长度为NULL,或NULL值等于空字符串.这是一个新的数据类型吗?!

编辑: 新数据类型 - 此处称为"Numpty"

编辑2 将数据插入临时表将Numpties转换为NULLS.(这个sql的结果是10)

CREATE TABLE #temp(ID uniqueidentifier , Value varchar(max))

INSERT INTO #temp 
SELECT top 10 g.ID, g.AdditionalFields
FROM grants g 
WHERE g.AdditionalFields IS NOT NULL AND LEN(g.AdditionalFields) IS NULL

SELECT COUNT(*) FROM #temp WHERE Value is null

DROP TABLE #temp
Run Code Online (Sandbox Code Playgroud)

编辑3 我可以通过运行更新来修复数据:

UPDATE Grants SET AdditionalFields = NULL
WHERE AdditionalFields IS NOT NULL AND LEN(AdditionalFields) IS NULL
Run Code Online (Sandbox Code Playgroud)

因此,我认为字段必须包含某些内容,而不是模式定义的某些问题.但它是什么?我怎么阻止它回来?

编辑4 我的数据库中有另外两个字段,varchar(max)在字段IS NOT NULL和LEN(字段)IS NULL时返回行.所有这些字段都是TEXT,并更改为VARCHAR(MAX).数据库也从Sql Server 2005迁移到2008.看起来我们默认情况下已经有ANSI_PADDING等.

另一个例子: 在此输入图像描述

转换为varbinary 在此输入图像描述

执行计划: 执行计划 编辑5:删除表定义 - 结果证明是不相关的

编辑6 脚本生成脚本以将TEXT更改为VARCHAR(MAX)然后更新值以防止错误并提高性能

--Generate scripts to alter TEXT to VARCHAR(MAX)
SELECT 'ALTER TABLE [' + tab.table_schema + '].[' + tab.table_name  + '] ALTER COLUMN [' + col.column_name + '] VARCHAR(MAX)' + CASE WHEN col.IS_NULLABLE = 'YES' THEN ' NULL' ELSE ' NOT NULL' END + ' GO'
FROM INFORMATION_SCHEMA.tables tab
INNER JOIN INFORMATION_SCHEMA.COLUMNS col ON col.table_name = tab.table_name
          AND tab.table_schema = col.table_schema
          AND tab.table_catalog = col.table_catalog
WHERE tab.table_type <> 'VIEW' and col.DATA_TYPE = 'text'

--Generate scripts to set value to value in VARCHAR(MAX) fields
SELECT 'UPDATE [' + tab.table_schema + '].[' + tab.table_name  + '] SET [' + col.column_name + '] = [' + col.column_name + ']'
FROM INFORMATION_SCHEMA.tables tab
INNER JOIN INFORMATION_SCHEMA.COLUMNS col ON col.table_name = tab.table_name
          AND tab.table_schema = col.table_schema
          AND tab.table_catalog = col.table_catalog
WHERE tab.table_type <> 'VIEW' AND col.DATA_TYPE = 'varchar' and col.CHARACTER_MAXIMUM_LENGTH = -1
Run Code Online (Sandbox Code Playgroud)

Mic*_*Sim 17

我有一个示例代码来重现上述行为.如果您有一个TEXT字段存储的值大于它可以放在一行中的值,并且之后将其设置为NULL并执行列转换,则会出现问题VARCHAR(MAX).

大值存储在单独的页面中.然后将此字段的值设置为NULL.如果您现在将此列转换为a VARCHAR(MAX),则SQL Server似乎无法正确执行.通常,在TEXTVARCHAR(MAX)转换外部网页保持原样,但也许是因为它被设置为NULL,列改变食堂的事情了.

更新:它似乎与TEXT列中的大值无关.短值显示相同的行为(扩展样本).所以这只是明确的设置,NULL通过UPDATE和重要的转换.

CREATE TABLE [dbo].[Test](
    [Id] [int] NOT NULL,
    [Value] [text] NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

INSERT INTO Test VALUES (1, 'test')
INSERT INTO Test VALUES (2, '')
INSERT INTO Test VALUES (3, NULL)
INSERT INTO Test VALUES (4, '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789')
INSERT INTO Test VALUES (5, 'short string')
GO

update test SET value = null where ID = 4
update test SET value = null where ID = 5
GO

ALTER TABLE test ALTER COLUMN value varchar(max)
GO

select id, value, len(value) as length
from test
where value is not null
GO
Run Code Online (Sandbox Code Playgroud)

结果是:

1   test    4
2           0
4   NULL    NULL
5   NULL    NULL
Run Code Online (Sandbox Code Playgroud)

解决此问题的一个简单方法是重新分配VARCHAR(MAX)列中的值.

UPDATE Test SET value = value
Run Code Online (Sandbox Code Playgroud)

这似乎将值放在先前存储在外部页面中的行中.(参见参考:SQL 2005中的NTEXT与NVARCHAR(MAX))

  • +1 提供回购。显式插入“NULL”的行是该列中唯一将“NULL_BITMAP”设置为“1”的行。对于“text”数据类型,我之前注意到更新为“NULL”不会更新位图,但似乎在指针或指向结构的其他位置设置了某种标志。如果您在转换为“max”之前执行“select [Id], [Value] from [Test] where [Value] is not null”,则会返回正确的结果,但“NULL_BITMAP”仍然显示为零,因此它必须查找其他地方来确定这一点。 (2认同)

Mar*_*ith 6

这只是McSim使用SQL Server Internals Viewer查看各个阶段的答案的补充.

CREATE TABLE [dbo].[Test](
    [Id] [int] NOT NULL PRIMARY KEY ,
    [Value] [text] NULL)


INSERT INTO Test VALUES (1, '')
Run Code Online (Sandbox Code Playgroud)

初始插入后排

插入主行后

初始插入后的文本值

插入文本值后

update [Test] SET [Value] = null 
Run Code Online (Sandbox Code Playgroud)

更新后的行 NULL

这与前面显示的行相同,所以我没有重复截图.具体的NULL_BITMAP没有得到更新,以反映新的NULL价值.

更新后的文本值 NULL

更新后的文本值

这些Type位已更改,Internals Viewer将其显示为不再包含该Data列的值.

此时正确运行以下命令不会返回任何行

SET STATISTICS IO ON
select [Id]
from [Test]
where [Value] is not null
Run Code Online (Sandbox Code Playgroud)

因此,SQL Server必须遵循文本指针并查看其中的值以确定NULL-ability.

ALTER TABLE [Test] ALTER COLUMN [Value] varchar(max)
Run Code Online (Sandbox Code Playgroud)

这是仅元数据更改.inrow和out行数据都保持不变.

但是,此时运行以下错误返回行.

SET STATISTICS IO ON
select [Id]
from [Test]
where [Value] is not null
Run Code Online (Sandbox Code Playgroud)

的输出 STATISTICS IO

扫描计数1,逻辑读取2,... lob逻辑读取1

表明它仍然确实遵循文本指针,但可能在这种varchar(max)情况下必须有一个不同的代码路径,错误地最终NULL_BITMAP从不相关的值中获取值(其值自初始插入以来从未更新过).