é de um tipo inválido para uso como coluna de chave em um índice

180

Eu tenho um erro em

Column 'key' in table 'misc_info' is of a type that is invalid for use as a key column in an index.

onde chave é um nvarchar (max). Um rápido google encontrou isso . No entanto, não explica o que é uma solução. Como faço para criar algo como Dictionary, onde a chave e o valor são ambos strings e, obviamente, a chave deve ser única e única. Minha instrução sql foi

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

fonte
16
Você realmente precisa que sua chave seja (potencialmente) 4GB grande E única? O SqlServer não permite isso porque verificar a exclusividade pode ser uma operação que consome muito tempo.
Klaus Byskov Pedersen
O @KlausByskovPedersen, um DBMS mais poderoso como o PostgreSQL, é inteligente o suficiente para permitir e indexar um resumo. Mas você tem razão.
Matthieu

Respostas:

244

Uma restrição exclusiva não pode ter mais de 8000 bytes por linha e só usará os primeiros 900 bytes, portanto o tamanho máximo mais seguro para suas chaves seria:

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

ou seja, a chave não pode ter mais de 450 caracteres. Se você pode mudar para em varcharvez de nvarchar(por exemplo, se você não precisar armazenar caracteres de mais de uma página de código), isso poderá aumentar para 900 caracteres.

Daniel Renshaw
fonte
1
Para varchar, o limite ainda seria varchar (450)?
Steam
9
Você tem espaço para usar varchar(900)OU nvarchar(450).
precisa
Meu entendimento é que um varchar precisará de 4 bytes para determinar o comprimento do item, o que significa que o limite real precisa ser varchar (896). Isso está correto?
Mrmillsy 15/05
2
@mrmillsy O tamanho máximo declarado não inclui a sobrecarga (que é de 2 bytes, não 4) e os bytes de sobrecarga não são incluídos no limite do tamanho máximo da linha de índice. technet.microsoft.com/en-us/library/ms176089(v=sql.100).aspx
Daniel Renshaw
1
@mrmillsy Você está recebendo essa mensagem porque está incluindo o ID1 intno índice. Isso intrequer 4 bytes, além dos 900 bytes para o arquivo varchar.
Daniel Renshaw
33

Há uma limitação no SQL Server (até 2008 R2) de que varchar (MAX) e nvarchar (MAX) (e vários outros tipos como texto, ntext) não podem ser usados ​​em índices. Você tem 2 opções:
1. Defina um tamanho limitado no campo chave ex. nvarchar (100)
2. Crie uma restrição de verificação que compare o valor com todas as chaves na tabela. A condição é:

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

e [dbo]. [CheckKey] é uma função escalar definida como:

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

Mas observe que um índice nativo tem mais desempenho do que uma restrição de verificação. Portanto, a menos que você não possa especificar um comprimento, não use a restrição de verificação.

Marwan
fonte
Inteligente - melhor do que gatilhos, eu sinto.
Neil Moss
14

A única solução é usar menos dados no seu Índice Único. Sua chave pode ser NVARCHAR (450) no máximo.

"O SQL Server mantém o limite de 900 bytes para o tamanho total máximo de todas as colunas de chave de índice."

Leia mais no MSDN

Don
fonte
Para varchar, o limite ainda seria varchar (450)?
Steam
7

Uma solução seria declarar sua chave como nvarchar(20).

Klaus Byskov Pedersen
fonte
2

Observando o comentário de klaisbyskov sobre o tamanho da sua chave que precisa ter gigabytes de tamanho e assumindo que você realmente precisa disso, acho que suas únicas opções são:

  1. use um hash do valor da chave
    • Crie uma coluna no nchar (40) (para um hash sha1, por exemplo),
    • coloque uma chave exclusiva na coluna de hash.
    • gerar o hash ao salvar ou atualizar o registro
  2. gatilhos para consultar a tabela em busca de uma correspondência existente na inserção ou atualização.

O hash vem com a ressalva de que um dia você poderá ter uma colisão.

Os gatilhos varrerão a tabela inteira.

Até você ...

Neil Moss
fonte