类型无效,不能用作索引中的键列


178

我有一个错误

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)。一个快速的谷歌发现了这个。但是,它没有解释什么是解决方案。我该如何创建类似于Dictionary之类的东西,其中键和值都是字符串,并且显然键必须是唯一的且是单个的。我的sql语句是

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

16
您是否真的需要密钥(可能)为4GB大且唯一?SqlServer不允许这样做,因为检查唯一性可能是非常耗时的操作。
克劳斯·比斯科夫·皮德森

@KlausByskovPedersen一些更强大的DBMS,例如PostgreSQL,足够聪明,可以允许它并为摘要编制索引。但是你有一点。
Matthieu

Answers:


242

唯一约束不能超过每行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
对于varchar,限制是否仍为varchar(450)?
2013年

9
您有空间使用varchar(900)OR nvarchar(450)
Daniel Renshaw 2013年

我的理解是,varchar将占用4个字节来确定项目的长度,这意味着实际限制需要为varchar(896)。这样对吗?
mrmillsy 2014年

2
@mrmillsy声明的最大大小不包括开销(2个字节,不是4个字节),并且开销字节不包括在最大索引行大小的限制中。technet.microsoft.com/zh-CN/library/ms176089(v=sql.100).aspx
Daniel Renshaw 2014年

1
@mrmillsy您正在收到该消息,因为您将ID1 intin 包含在索引中。这int需要4个字节,除了900个字节的varchar
Daniel Renshaw

33

在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

但是请注意,本机索引比检查约束更具性能,因此,除非您真的不能指定长度,否则不要使用检查约束。


聪明-我觉得比触发器更好。
尼尔·莫斯,2010年

14

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

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

MSDN上阅读更多内容


对于varchar,限制是否仍为varchar(450)?
2013年


2

注意到klaisbyskov关于您的密钥长度需要为千兆字节大小的评论,并且假设您实际上确实需要这样做,那么我认为您唯一的选择是:

  1. 使用键值的哈希
    • 在nchar(40)上创建一列(例如,用于sha1哈希),
    • 在哈希列上放置一个唯一键。
    • 保存或更新记录时生成哈希
  2. 触发查询表以查找插入或更新时的现有匹配项。

警告:有一天,您可能会遇到碰撞。

触发器将扫描整个表。

交给你...

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.