Concepts
Vous avez mal compris certains concepts de base, et les difficultés en découlent. Nous devons d'abord aborder les concepts, pas le problème tel que vous le percevez, et par conséquent, votre problème disparaîtra.
ID incrémentés automatiquement, qui sont bien sûr des clés primaires.
Non ils ne sont pas. C'est une idée fausse courante. Et les problèmes sont garantis.
Un ID
le champ ne peut pas être une clé primaire au sens anglais ou technique ou relationnel.
-
Bien sûr, en SQL, vous pouvez déclarer tout le champ doit être une
PRIMARY KEY
, mais cela ne la transforme pas comme par magie en clé primaire au sens anglais, technique ou relationnel. Vous pouvez nommer un chihuahua "Rottweiller", mais cela ne le transforme pas en Rottweiller, il reste un chihuahua. Comme tout langage, SQL exécute simplement les commandes que vous lui donnez, il ne comprend pas laPRIMARY KEY
pour signifier quelque chose de relationnel, cela frappe simplement un index unique sur la colonne (ou le champ). -
Le problème est que puisque vous avez déclaré l'
ID
être unePRIMARY KEY
, vous pensez en tant que clé primaire, et vous pouvez attendre qu'il a certaines des qualités d'une clé primaire. À l'exception de l'unicité de l'ID valeur , il n'offre aucun avantage. Il n'a aucune des qualités d'une clé primaire, ni aucune sorte de clé relationnelle d'ailleurs. Ce n'est pas une clé au sens anglais, technique ou relationnel. En déclarant qu'une non-clé est une clé, vous ne ferez que vous confondre et vous découvrirez qu'il y a quelque chose de terriblement faux uniquement lorsque l'utilisateur se plaint de doublons dans la table.
Les tables relationnelles doivent avoir une ligne unicité
Une PRIMARY KEY
sur un ID
le champ ne fournit pas de ligne unicité. Ce n'est donc pas une table relationnelle contenant des lignes, et si ce n'est pas cela, alors c'est un fichier contenant des enregistrements. Il n'a ni l'intégrité, ni la puissance (à ce stade, vous ne serez conscient que de la puissance de jointure) ni la vitesse d'une table dans une base de données relationnelle.
Exécutez ce code (MS SQL 2008) et prouvez-le vous-même. Veuillez ne pas simplement lire ceci et le comprendre, puis continuer à lire le reste de cette réponse, ce code doit être exécuté avant de continuer . Il a une valeur curative.
CREATE TABLE dumb_file (
id INT NOT NULL IDENTITY PRIMARY KEY,
name_first CHAR(30) NOT NULL,
name_last CHAR(30) NOT NULL
)
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds, but not intended
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds, but not intended
SELECT * FROM dumb_file
Notez que vous avez des lignes en double . Les tables relationnelles doivent avoir des lignes uniques . Une preuve supplémentaire que vous n'avez pas de table relationnelle, ou aucune des qualités d'une table.
Notez que dans votre rapport, la seule chose qui est unique est l'ID
champ, dont aucun utilisateur ne se soucie, aucun utilisateur ne voit, car ce ne sont pas des données, c'est un non-sens supplémentaire qu'un "professeur" très stupide vous a dit de mettre dans chaque fichier. Vous avez enregistrement unicité mais pas ligne unicité.
En termes de données (les données réelles moins les ajouts superflus), les données name_last
et name_first
peut exister sans l'ID
domaine. Une personne a un prénom et un nom de famille sans qu'une pièce d'identité ne soit estampée sur son front.
La deuxième chose que vous utilisez qui vous déroute est le AUTOINCREMENT.
Si vous implémentez un système de classement d'enregistrements sans capacité relationnelle, bien sûr, c'est utile, vous n'avez pas à coder l'incrément lors de l'insertion d'enregistrements. Mais si vous implémentez une base de données relationnelle, cela ne sert à rien, car vous ne l'utiliserez jamais. Il existe de nombreuses fonctionnalités dans SQL que la plupart des gens n'utilisent jamais.
Mesure corrective
Alors, comment mettre à niveau, élever, ce dumb_file plein de lignes en double vers une table relationnelle, afin d'obtenir certaines des qualités et des avantages d'une table relationnelle ? Il y a trois étapes pour cela.
-
Vous devez comprendre les clés
- Et depuis que nous sommes passés des fichiers ISAM des années 1970 au modèle relationnel , vous devez comprendre les clés relationnelles . C'est-à-dire si vous souhaitez bénéficier des avantages (intégrité, puissance, rapidité) d'une base de données relationnelle.
Dr E F Cood, dans son MR , a déclaré que :
une clé est constituée à partir des données
et
les lignes d'un tableau doivent être uniques
Votre "clé" n'est pas constituée à partir des données. Il s'agit d'un parasite supplémentaire, non lié aux données, causé par votre infection par la maladie de votre "professeur". Reconnaissez-le comme tel et accordez-vous la pleine capacité mentale que Dieu vous a donnée (notez que je ne vous demande pas de penser en termes isolés ou fragmentés ou abstraits, tous les éléments d'une base de données doivent être intégrés les uns aux autres). Construire une vraie clé à partir des données, et uniquement à partir des données. Dans ce cas, il n'y a qu'une seule clé possible :
(name_last, name_first).
-
Essayez ce code , déclarer une contrainte unique sur les données :
CREATE TABLE dumb_table ( id INT NOT NULL IDENTITY PRIMARY KEY, name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT UK UNIQUE ( name_last, name_first ) ) INSERT dumb_table VALUES ( "Mickey", "Mouse" ) -- succeeds INSERT dumb_table VALUES ( "Mickey", "Mouse" ) -- fails, as intended INSERT dumb_table VALUES ( "Minnie", "Mouse" ) -- succeeds SELECT * FROM dumb_table
Nous avons maintenant unicité de ligne . C'est la séquence qui arrive à la plupart des gens :ils créent un fichier qui autorise les dupes; ils n'ont aucune idée de la raison pour laquelle les dupes apparaissent dans les listes déroulantes ; l'utilisateur crie ; ils modifient le fichier et ajoutent un index pour éviter les doublons ; ils passent au correctif de bogue suivant. (Ils peuvent le faire correctement ou non, c'est une autre histoire.)
-
Le deuxième niveau. Pour les personnes réfléchies qui pensent au-delà des solutions. Puisque nous avons maintenant l'unicité des lignes, quel est le but de l'
ID
champ, pourquoi l'avons-nous même ??? Oh, parce que le chihuahua s'appelle Rotty et qu'on a peur de le toucher.La déclaration qu'il s'agit d'une
PRIMARY KEY
est faux, mais il demeure, causant de la confusion et de fausses attentes. La seule véritable clé qui existe est le(name_last, name_fist),
et c'est une clé alternative à ce stade.Donc l'
ID
le champ est totalement superflu ; et il en va de même pour l'index qui le supporte ; et le stupideAUTOINCREMENT
aussi; ainsi que la fausse déclaration selon laquelle il s'agit d'unePRIMARY KEY
; et toutes les attentes que vous pourriez en avoir sont fausses.Supprimez donc le superflu
ID
domaine. Essayez ce code :CREATE TABLE honest_table ( name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT PK PRIMARY KEY ( name_last, name_first ) ) INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- succeeds INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- fails, as intended INSERT honest_table VALUES ( "Minnie", "Mouse" ) -- succeeds SELECT * FROM honest_table
Fonctionne très bien, fonctionne comme prévu, sans les champs et index superflus.
S'il vous plaît rappelez-vous ceci, et faites-le correctement, à chaque fois.
Faux enseignants
En ces derniers temps, comme conseillé, nous en aurons beaucoup. Notez bien, les "enseignants" qui propagent ID
les colonnes, en vertu des preuves détaillées de cet article, ne comprennent tout simplement pas le modèle relationnel ou bases de données relationnelles. Surtout ceux qui écrivent des livres à ce sujet.
Comme on le voit, ils sont bloqués dans la technologie ISAM d'avant 1970. C'est tout ce qu'ils comprennent et c'est tout ce qu'ils peuvent enseigner. Ils utilisent un conteneur de base de données SQL, pour la facilité d'accès, de récupération, de sauvegarde, etc., mais le contenu est un pur système de classement d'enregistrements sans intégrité relationnelle, puissance ou vitesse. AFAIC, c'est une fraude grave.
En plus de ID
domaines, bien sûr, il y a plusieurs éléments qui sont des concepts clés relationnels ou non, qui, pris ensemble, m'amènent à tirer une conclusion aussi grave. Ces autres éléments dépassent le cadre de cet article.
Une paire d'idiots en particulier monte actuellement un assaut sur First Normal Form. Ils appartiennent à l'asile.
Répondre
Maintenant pour le reste de votre question.
Existe-t-il un moyen de créer une table relationnelle sans perdre les fonctionnalités d'incrémentation automatique ?
C'est une phrase qui se contredit. J'espère que vous comprendrez d'après mon explication, les tables relationnelles n'ont pas besoin pour AUTOINCREMENT
"fonctionnalités"; si le fichier a AUTOINCREMENT
, ce n'est pas une table relationnelle.
AUTOINCREMENT
n'est bon que pour une chose :si, et seulement si, vous souhaitez créer une feuille de calcul Excel dans le conteneur de la base de données SQL, remplie de champs nommés A,
B,
et C,
en haut et enregistrez les numéros en bas à gauche. En termes de base de données, c'est le résultat d'un SELECT, une vue aplatie des données, qui n'est pas la source de données, qui est organisé (Normalisé).
Une autre solution possible (mais non préférée) peut être qu'il y a une autre clé primaire dans la première table, qui est le nom d'utilisateur de l'utilisateur, pas avec une instruction d'incrémentation automatique, bien sûr. Est-ce inévitable ?
Dans le travail technique, nous ne nous soucions pas des préférences, car c'est subjectif et cela change tout le temps. Nous nous soucions de l'exactitude technique, car c'est objectif et cela ne change pas.
Oui, c'est inévitable. Parce que ce n'est qu'une question de temps; nombre de bogues ; nombre de "ne peut pas faire" ; nombre de cris d'utilisateurs, jusqu'à ce que vous fassiez face aux faits, surmontiez vos fausses déclarations et réalisiez que :
-
le seul moyen de s'assurer que l'utilisateur lignes sont uniques, que les user_names sont uniques, est de déclarer un
UNIQUE
contrainte sur elle -
et se débarrasser de
user_id
ouid
dans la fiche utilisateur -
qui promeut
user_name
àPRIMARY KEY
Oui, car tout votre problème avec la troisième table, pas par hasard, est alors éliminé.
Cette troisième table est une table associative . La seule clé requise (clé primaire) est un composé des deux clés primaires parentes. Cela garantit l'unicité des lignes , qui sont identifiés par leurs clés, et non par leurs IDs.
Je vous mets en garde à ce sujet parce que les mêmes "professeurs" qui vous ont appris l'erreur d'implémenter ID
champs, enseignez l'erreur d'implémentation de ID
champs de la table associative, où, tout comme avec une table ordinaire, il est superflu, ne sert à rien, introduit des doublons et prête à confusion. Et c'est doublement superflu car les deux clés qui fournissent sont déjà là, nous regardant en face.
Puisqu'ils ne comprennent pas le RM , ou termes relationnels, ils appellent les tables associatives des tables de "lien" ou de "carte". S'ils ont un ID
champ, ce sont en fait des fichiers.
Tableaux de recherche
ID
les champs sont particulièrement Chose stupide à faire pour les tables de recherche ou de référence. La plupart d'entre eux ont des codes reconnaissables, il n'est pas nécessaire d'énumérer la liste des codes qu'ils contiennent, car les codes sont (devraient être) uniques.
De plus, avoir les codes dans les tables enfants en tant que FK est une bonne chose :le code est beaucoup plus significatif et évite souvent une jointure inutile :
SELECT ...
FROM child_table -- not the lookup table
WHERE gender_code = "M" -- FK in the child, PK in the lookup
au lieu de :
SELECT ...
FROM child_table
WHERE gender_id = 6 -- meaningless to the maintainer
ou pire :
SELECT ...
FROM child_table C -- that you are trying to determine
JOIN lookup_table L
ON C.gender_id = L.gender_id
WHERE L.gender_code = "M" -- meaningful, known
Notez que c'est quelque chose que l'on ne peut pas éviter :vous avez besoin d'unicité sur le code de recherche et unicité sur la description. C'est la seule méthode pour éviter les doublons dans chaque des deux colonnes :
CREATE TABLE gender (
gender_code CHAR(2) NOT NULL,
name CHAR(30) NOT NULL
CONSTRAINT PK
PRIMARY KEY ( gender_code )
CONSTRAINT AK
UNIQUE ( name )
)
Exemple complet
D'après les détails de votre question, je soupçonne que vous avez des problèmes de syntaxe SQL et de définition FK, je vais donc donner la solution complète dont vous avez besoin à titre d'exemple (puisque vous n'avez pas donné de définitions de fichiers) :
CREATE TABLE user ( -- Typical Identifying Table
user_name CHAR(16) NOT NULL, -- Short PK
name_first CHAR(30) NOT NULL, -- Alt Key.1
name_last CHAR(30) NOT NULL, -- Alt Key.2
birth_date DATE NOT NULL -- Alt Key.3
CONSTRAINT PK -- unique user_name
PRIMARY KEY ( user_name )
CONSTRAINT AK -- unique person identification
PRIMARY KEY ( name_last, name_first, birth_date )
)
CREATE TABLE sport ( -- Typical Lookup Table
sport_code CHAR(4) NOT NULL, -- PK Short code
name CHAR(30) NOT NULL -- AK
CONSTRAINT PK
PRIMARY KEY ( sport_code )
CONSTRAINT AK
PRIMARY KEY ( name )
)
CREATE TABLE user_sport ( -- Typical Associative Table
user_name CHAR(16) NOT NULL, -- PK.1, FK
sport_code CHAR(4) NOT NULL, -- PK.2, FK
start_date DATE NOT NULL
CONSTRAINT PK
PRIMARY KEY ( user_name, sport_code )
CONSTRAINT user_plays_sport_fk
FOREIGN KEY ( user_name )
REFERENCES user ( user_name )
CONSTRAINT sport_occupies_user_fk
FOREIGN KEY ( sport_code )
REFERENCES sport ( sport_code )
)
Là, la PRIMARY KEY
déclaration est honnête, c'est une clé primaire ; pas d'ID;
non AUTOINCREMENT;
pas d'indices supplémentaires ; pas de lignes en double; pas d'attentes erronées ; aucun problème consécutif.
Modèle de données
Voici le modèle de données pour aller avec les définitions.
-
Si vous n'êtes pas habitué à la notation, sachez que chaque petite coche, encoche et marque, les lignes pleines par rapport aux pointillés, les coins carrés par rapport aux coins ronds, signifient quelque chose de très spécifique. Reportez-vous à la Notation IDEF1X .
-
Une image vaut mieux que mille mots; dans ce cas, une image de plainte standard vaut plus que cela; un mauvais ne vaut pas le papier sur lequel il est dessiné.
-
Veuillez vérifier attentivement les phrases verbales, elles comprennent un ensemble de prédicats. Le reste des prédicats peut être déterminé directement à partir du modèle. Si ce n'est pas clair, veuillez demander.