, bir dizinde anahtar sütun olarak kullanım için geçersiz bir türde


180

Konumunda bir hata var

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

burada anahtar bir nvarchar'dır (maks.). Hızlı bir google bunu buldu . Ancak çözümün ne olduğunu açıklamaz. Nasıl anahtar ve değer her iki dize ve açıkçası anahtar benzersiz ve tek olmalıdır Sözlük gibi bir şey nasıl oluştururum. Sql ifadem

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

16
Gerçekten 4GB büyüklüğünde VE benzersiz olması için anahtarınıza gerçekten ihtiyacınız var mı? SqlServer buna izin vermez, çünkü benzersizliği kontrol etmek çok zaman alan bir işlem olabilir.
Klaus Byskov Pedersen

@KlausByskovPedersen PostgreSQL gibi bazı daha güçlü DBMS buna izin verecek kadar akıllı ve bunun yerine bir özeti indeksleyecek. Ama bir noktan var.
Matthieu

Yanıtlar:


244

Benzersiz bir kısıtlama satır başına 8000 baytın üzerinde olamaz ve o zaman bile yalnızca ilk 900 baytı kullanır, böylece anahtarlarınız için en güvenli maksimum boyut:

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

yani anahtar 450 karakterden fazla olamaz. Geçmek Eğer varcharyerine nvarchar(eğer birden fazla codepage mağaza karakter gerekmiyorsa örneğin) daha sonra bu 900 karakterle artabilir.


1
Varchar için limit hala varchar (450) olur mu?
Buhar

9
Ya kullanmak alana sahip varchar(900)VEYA nvarchar(450).
Daniel Renshaw

Anladığım kadarıyla, bir varchar öğenin uzunluğunu belirlemek için 4 bayt sürecek, yani gerçek sınırın varchar olması gerekiyor (896). Bu doğru mu?
mrmillsy

2
@mrmillsy Bildirilen maksimum boyut, ek yükü (4 değil 2 bayt) içermez ve ek yükler, maksimum dizin satırı boyutu sınırına dahil edilmez. technet.microsoft.com/tr-tr/library/ms176089(v=sql.100).aspx
Daniel Renshaw

1
@mrmillsy Bu mesajı alıyorsunuz çünkü dizine ekliyorsunuz ID1 int. Bunun intiçin 4 bayt gerekir varchar.
Daniel Renshaw

33

SQL Server'da (2008 R2'ye kadar) varchar (MAX) ve nvarchar (MAX) (ve metin, ntext gibi diğer bazı türlerin) dizinlerde kullanılamayacağı bir sınırlama vardır. 2 seçeneğiniz vardır:
1. Örn. nvarchar (100)
2. Değeri tablodaki tüm tuşlarla karşılaştıran bir kontrol kısıtlaması oluşturun. Durum:

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

ve [dbo]. [CheckKey] şu şekilde tanımlanan bir skaler işlevdir:

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

Ancak, yerel bir dizinin bir kontrol kısıtlamasından daha performanslı olduğunu unutmayın, bu nedenle gerçekten bir uzunluk belirleyemezseniz, kontrol kısıtlamasını kullanmayın.


Zeki - tetikleyicilerden daha güzel, hissediyorum.
Neil Moss

14

Tek çözüm Benzersiz Dizininizde daha az veri kullanmaktır. Anahtarınız en fazla NVARCHAR (450) olabilir.

"SQL Server, tüm dizin anahtar sütunlarının maksimum toplam boyutu için 900 bayt sınırını korur."

MSDN'de daha fazlasını okuyun


Varchar için limit hala varchar (450) olur mu?
Buhar


2

Klaisbyskov'un anahtar uzunluğunuzda gigabayt olması gereken yorumuna dikkat çekiyor ve aslında buna ihtiyacınız olduğunu varsayarak, sadece seçeneklerinizin olduğunu düşünüyorum:

  1. anahtar / değer çiftini kullan
    • Nchar (40) üzerinde bir sütun oluşturun (örneğin sha1 karması için),
    • karma sütununa benzersiz bir anahtar koyun.
    • kaydı kaydederken veya güncellerken karma oluştur
  2. ekleme veya güncelleme sırasında var olan bir eşleşme için tabloyu sorgulamayı tetikler.

Hashing, bir gün bir çarpışma yaşayabileceğiniz uyarısı ile birlikte gelir .

Tetikleyiciler tüm tabloyu tarar.

Sana doğru...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.