在计算字段上创建索引:字符串或二进制数据将被截断


8

我有一个Foo包含以下字段的表:

ID bigint not null identity(1,1),
SerializedValue nvarchar(max),
LongValue as TRY_CAST(SerializedValue as bigint)

现在,我想在LongValue上创建一个索引,以便可以轻松地查找表示数字的序列化值。

create nonclustered index IX_Foo on Foo(LongValue);

这会向我吐出以下错误:

字符串或二进制数据将被截断。

是的,SerializedValue中有现有数据。但是,祈祷可以通过在计算字段上创建索引来截断什么呢?

Answers:


8

该错误不是由创建索引引起的。该错误是由于TRY_CAST在创建索引时对计算的列值进行评估时引起的。

如果我运行此命令:

SELECT TRY_CAST(REPLICATE(CONVERT(nvarchar(MAX), N'a'), 4001) AS bigint)

我犯了同样的错误。

文件说,(重点煤矿):

如果转换成功,则TRY_CAST返回该值作为指定的data_type;否则,返回0。如果发生错误,则返回null。但是,如果您请求明确不允许的转换,则TRY_CAST失败,并显示错误。

现在,还不清楚在哪种情况下它会因错误而失败(给定函数的整个,看起来有点像asinine ,但是无论如何……),因此我们可以通过转换输入值(使用一些方法)来修复代码。对于您表中的数据而言是合理的),因为在无论如何都不适合bigint的情况下无需处理巨大的字符串:

SELECT TRY_CAST(LEFT(REPLICATE(CONVERT(nvarchar(MAX), N'1'), 4001), 100) AS bigint)

NULL由于值无效而返回,但不会因错误而炸弹。


-1

如果您的字符串值太长,则索引创建将失败。我使用SQL Server 2012尝试了一些测试代码。

CREATE TABLE dbo.foo 
(ID bigint not null identity(1,1),
SerializedValue nvarchar(max),
LongValue as TRY_CAST(SerializedValue as bigint));

INSERT INTO dbo.foo (serializedvalue) VALUES(REPLICATE(' ', 4000)+'1');

CREATE INDEX GotToTry ON foo(LongValue);

DROP TABLE dbo.foo;
GO

我的快速实验表明,只要nvarchar(max)值不超过4000个字符,该代码就可以工作。(当然,最后没有任何内容的所有空格都折叠为没有字符,因此可以正常工作。)第4001个字符触发String or binary data would be truncated消息。因此,您可以检查数据以获取长度超过4000个字符的SerializedValue。

编辑:是的,转换为BIGINT。问题不是问题BIGINT,而是问题NVARCHAR(MAX)。例如:

  1. 如果一行包含“ 1111111111111111111”,它将同时CREATE INDEX将值转换为BIGINT
  2. 如果一行是0到4000'1's,则可以CREATE INDEX,但是该值可能是NULL因为它溢出了BIGINT
  3. 如果一行的长度超过4000个字符,则CREATE INDEX失败。

因此,似乎NVARCHAR(MAX)的实际内容对CREATE INDEX至关重要。

编辑:乔恩·西格尔(Jon Seigel)确定,当字符串长于nvarchar(4000)时,TRY_CAST会触发创建索引失败。


2
这并不能真正回答问题。索引位于bigint上。除了bigint之外,别无其他。问题是,当bigint处于索引的大小允许范围内时,为什么会截断数据
马克·辛金森

1
@MarkSinkinson编辑以提供更多详细信息。问题是NVARCHAR(MAX)的内容。
RLF 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.