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

时间:2012-04-24 10:04:10

标签: sql-server sql-server-2005

This is the query:

  1. 看起来列表中出现了一些NULL值。
  2. 查询过滤掉了某些NULL值 。我查过了。
  3. 如果我添加AND AdditionalFields = '',则仍会返回这两个结果
  4. AdditionalFields是varchar(max)
  5. 数据库是SQL Server 10,兼容级别= Sql Server 2005(90)
  6. 我正在使用Management Studio 2008
  7. 我似乎有空字符串,其长度为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
    

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

    UPDATE Grants SET AdditionalFields = NULL
    WHERE AdditionalFields IS NOT NULL AND LEN(AdditionalFields) IS NULL
    

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

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

    另一个例子: enter image description here

    转换为varbinary enter image description here

    执行计划: Execution plan 编辑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
    

5 个答案:

答案 0 :(得分:17)

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

大值存储在单独的页面中。然后将此字段的值设置为NULL。如果现在将此列转换为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

结果是:

1   test    4
2           0
4   NULL    NULL
5   NULL    NULL

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

UPDATE Test SET value = value

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

答案 1 :(得分:6)

这只是使用SQL Server Internals Viewer查看各个阶段的McSim's answer的补充。

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


INSERT INTO Test VALUES (1, '')

初始插入后的行

After Insert Main Row

初始插入后的文本值

After Insert Text Value

update [Test] SET [Value] = null 

更新到NULL

后的行

这与前面显示的行相同,所以我没有重复截图。具体而言,NULL_BITMAP会更新以反映新的NULL值。

更新为NULL

后的文本值

Text value after Update

Type位已更改,Internals Viewer会将其显示为不再包含Data列的值。

此时正确运行以下命令

SET STATISTICS IO ON
select [Id]
from [Test]
where [Value] is not null

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

ALTER TABLE [Test] ALTER COLUMN [Value] varchar(max)

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

但是,此时运行以下命令会错误地返回该行。

SET STATISTICS IO ON
select [Id]
from [Test]
where [Value] is not null

STATISTICS IO

的输出
  

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

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

答案 2 :(得分:0)

正如其他人所指出的那样,这个结果是完全不可能的。

  1. 请发布实际执行计划的屏幕截图。
  2. 请运行dbcc checkdb并发布错误消息(如果有)。
  3. (2)现在是我最喜欢的。

答案 3 :(得分:0)

科林:

由于数据库转换,我很确定这一切都在发生。由于您需要尽快解决这个问题,我的建议是首先保证您的AdditionalFields数据没问题,并尝试理解为什么会发生这种情况:

  1. 做一个备份;
  2. 运行此T-SQL:

    update grants
    set AdditionalFields = ltrim(rtrim(isnull(AdditionalFields,'')))
    
  3. isnull函数将在空字符串中转换空值,左/右修剪应保证具有多个空格的偶数字段之后具有相同的值。

    你可以运行这个并稍后用结果反馈我们吗?

    祝你好运

答案 4 :(得分:0)

我怀疑在数据库中存储了NULL这个词,使用select * from blah where mycolumn =&#39; NULL&#39;