J'ai une table appelée countries
et je définis la colonne country_name
comme unique en créant un «Index/Clé» de type «Clé unique» sur SQL Server 2008 R2.
Mais j'ai les questions suivantes:
IsUnique
comme étant «oui», y aura-t-il des différences?Une contrainte unique est implémentée en coulisse en tant qu'index unique. Par conséquent, la façon dont vous la spécifiez importe peu. J'ai tendance à l'appliquer simplement comme:
ALTER TABLE dbo.foo ADD CONSTRAINT UQ_bar UNIQUE(bar);
Certaines personnes créent un index unique à la place, par exemple.
CREATE UNIQUE INDEX IX_UQ_Bar ON dbo.foo(bar);
La différence réside dans l'intention: si vous créez la contrainte pour appliquer des règles commerciales/uniques, vous créez une contrainte. Si vous le faites pour améliorer les performances des requêtes, il peut être plus logique de créer un index unique. Encore une fois, sous les couvertures, c'est la même mise en œuvre, mais le chemin que vous prenez pour y arriver peut aider à documenter votre intention.
Je pense qu'il existe de nombreuses options pour adhérer à la fois aux fonctionnalités précédentes de Sybase et au standard ANSI (même si les contraintes uniques ne respectent pas la norme 100%, car elles n'autorisent qu'une valeur NULL, un index unique D'autre part, vous pouvez contourner ce problème en ajoutant une clause WHERE
(WHERE col IS NOT NULL
) sur SQL Server 2008 et versions ultérieures).
Une autre chose à mentionner est que si vous créez un index, vous pouvez spécifier les colonnes incluses, cela peut aider votre code SQL à fonctionner plus rapidement s'il y a une recherche par nom de pays.
CREATE UNIQUE NONCLUSTERED INDEX IX_UQ_Bar
ON dbo.foo (
bar
)
INCLUDE (foo_other_column)
GO
SELECT foo_other_column FROM Foo WHERE bar = 'test'
Le serveur SQL stockera "foo_other_column" dans l'index même. Dans le cas d'une contrainte unique, il trouvera d'abord l'index de 'test', puis recherchera une ligne dans la table foo et seulement là, il faudra "foo_other_column".
Si vous utilisez SqlMetal.exe pour générer des entités DBML ou LinqToSql:
La raison est dans la mise en œuvre de SqlMetal. Il interroge le schéma d'informations de base de données, en particulier l'utilisation des colonnes de clé. Les clés uniques y sont représentées, mais pas les index uniques.
SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
Il n'y a pas de différence entre un index unique ou une contrainte unique et il n'y a pas non plus de différence de performances. Cependant, il existe certaines différences pour la création, certaines options de création d'index n'étant pas disponibles pour des contraintes uniques.
Un des points les plus importants est de supposer que vous voulez conserver la valeur de colonne à null avec le maintien de l’unicité, ce que vous ne pouvez pas faire avec une contrainte de clé unique, mais avec l’index de clé unique, vous pouvez conserver la valeur de la colonne à null avec l’unicité. donc, si vous avez besoin d'une colonne unique avec le type Null-capable, Index unique est requis, sinon, si vous avez besoin d'une colonne non NULL-capable, puis d'une contrainte de clé unique, requise.
Outre les excellentes réponses ci-dessus, j'ajouterais mes 2 centimes ici.
La clé unique est une contrainte et utilise un index unique pour s’appliquer. Tout comme la clé primaire est généralement appliquée par un index unique en cluster. Logiquement, une contrainte et un index sont deux choses différentes. Mais dans le SGBDR, une contrainte peut être implémentée physiquement via un index.
Si une table est créée avec une contrainte unique dans le serveur SQL, vous verrez un objet de contrainte et un index unique.
create table dbo.t (id int constraint my_unique_constraint unique (id));
select [Constraint]=name from sys.key_constraints
where parent_object_id = object_id('dbo.t');
select name, index_id, type_desc from sys.indexes
where object_id = object_id('dbo.t')
and index_id > 0;
nous aurons ce qui suit (une contrainte et un index)
Cependant, si nous ne créons pas une contrainte mais juste un index unique comme suit:
create table dbo.t2 (id int );
create unique index my_unique_constraint on dbo.t2 (id);
select [Constraint]=name from sys.key_constraints
where parent_object_id = object_id('dbo.t2');
select name, index_id, type_desc from sys.indexes
where object_id = object_id('dbo.t2')
and index_id > 0
Vous verrez qu'aucun objet de contrainte n'a été créé (seul un index a été créé).
Du point de vue "théorique", dans SQL Server, une contrainte est un objet avec une valeur id_objet et est liée au schéma, alors qu'un index n'est pas un objet et n'a pas de valeur id_objet ni de schéma.
Une troisième option pour imposer l'unicité consiste à utiliser un Filtered Unique-Index pour autoriser un index unique nullable.
Ceci pas fonctionnera avec Unique-Constraints.
Par exemple, supposons que vous ayez une colonne dans laquelle vous voulez uniquement autoriser des valeurs uniques,
Mais vous souhaitez toujours prendre en charge plusieurs valeurs NULL
quand elles n'existent pas.
Seulement un Filtered Unique-Index fonctionnerait:
CREATE UNIQUE NONCLUSTERED INDEX [UF_Employee_UserID] ON [dbo].[Employee]
(
[UserID] ASC--Not all Employees have a UserID to log into the System.
)
WHERE ([UserID] IS NOT NULL)--Enforce Uniqueness when not null.
À l'heure actuelle, vous ne pouvez toujours pas créer d'index filtré dans SSMS lors de la modification d'une table à l'aide de l'interface graphique.
Cependant, vous pouvez fermer tous vos concepteurs de table ouverts, puis ouvrir les propriétés de l'index lui-même dans l'explorateur d'objets, si vous souhaitez parcourir l'interface graphique au lieu de créer l'index manuellement (comme ci-dessus). .