是一种无效的类型,可用作索引中的键列

时间:2010-05-19 08:46:33

标签: sql sql-server-2008

我在

时遇到错误
Column 'key' in table 'misc_info' is of a type that is invalid for use as a key column in an index.

其中key是nvarchar(max)。快速谷歌found this。然而,它并没有解释什么是解决方案。我如何创建像Dictionary这样的键,其中键和值都是字符串,显然键必须是唯一的并且是单一的。我的sql语句是

create table [misc_info] (
[id] INTEGER PRIMARY KEY IDENTITY NOT NULL,
[key] nvarchar(max) UNIQUE NOT NULL,
[value] nvarchar(max) NOT NULL);

5 个答案:

答案 0 :(得分:215)

唯一约束不能超过每行8000字节,即使这样也只能使用前900个字节,所以最安全的最大大小是:

create table [misc_info]
( 
    [id] INTEGER PRIMARY KEY IDENTITY NOT NULL, 
    [key] nvarchar(450) UNIQUE NOT NULL, 
    [value] nvarchar(max) NOT NULL
)

即。密钥不能超过450个字符。如果可以切换到varchar而不是nvarchar(例如,如果您不需要存储来自多个代码页的字符),则可以增加到900个字符。

答案 1 :(得分:30)

SQL Server(直到2008 R2)存在一个限制,即varchar(MAX)和nvarchar(MAX)(以及其他几种类型,如text,ntext)不能在索引中使用。您有2个选择:
1.在关键字段ex上设置有限的大小。为nvarchar(100)
2.创建一个检查约束,将值与表中的所有键进行比较。 条件是:

([dbo].[CheckKey]([key])=(1))

和[dbo]。[CheckKey]是一个定义为:

的标量函数
CREATE FUNCTION [dbo].[CheckKey]
(
    @key nvarchar(max)
)
RETURNS bit
AS
BEGIN
    declare @res bit
    if exists(select * from key_value where [key] = @key)
        set @res = 0
    else
        set @res = 1

    return @res
END

但请注意,本机索引比检查约束更高效,因此除非您确实无法指定长度,否则请不要使用检查约束。

答案 2 :(得分:12)

唯一的解决方案是在您的唯一索引中使用更少的数据。你的密钥最多可以是NVARCHAR(450)。

“SQL Server保留所有索引键列的最大总大小的900字节限制。”

MSDN

了解详情

答案 3 :(得分:6)

解决方案是将您的密钥声明为nvarchar(20)

答案 4 :(得分:2)

注意到klaisbyskov关于你的密钥长度需要为千兆字节的评论,并假设你确实需要这个,那么我认为你唯一的选择是:

  1. 使用键值的哈希值
    • 在nchar(40)上创建一个列(例如,对于sha1哈希),
    • 在哈希列上放置一个唯一键。
    • 在保存或更新记录时生成哈希
  2. 触发器在插入或更新时查询表中的现有匹配。
  3. Hashing伴随着警告,有一天,你可能会发生碰撞。

    触发器将扫描整个表格。

    告诉你......