1
votes

Comment puis-je créer une vérification pour m'assurer qu'une seule entrée dans la colonne peut avoir une valeur spécifique basée sur un identifiant d'une colonne différente dans SQL?

J'essaye de créer une nouvelle table dans SQL Developer qui a quatre colonnes. Dans une colonne, il y a une valeur numérique appelée ORG_ID, cet ORG_ID peut être le même dans plusieurs entrées de la table. Une autre colonne s'appelle DEFAULT_FLAG, cette colonne ne contient qu'un caractère Y ou N indiquant s'il s'agit de l'entrée par défaut de la table pour cet ORG_ID.

J'essaie de créer un CHECK dans la colonne DEFAULT_FLAG qui m'assure qu'il n'y en a qu'un entrée avec un Y pour toutes les entrées avec le même ORG_ID. Voici un exemple de ce à quoi cela ressemblerait:

default_flag varchar(1)
constraint  one_default Check(ORG_ID AND DEFAULT_FLAG != "Y"),

Dans le tableau ci-dessus, la deuxième entrée pour ORG_ID 123456 devrait être rejetée si Y était inséré comme DEFAULT_FLAG.

Je suis un peu nouveau dans SQL, j'ai donc fait mes recherches sur la nécessité d'utiliser une contrainte et de vérifier la colonne. J'ai essayé d'écrire le mien mais cela n'a pas fonctionné, le code est ci-dessous.

xxxx|xxxx|ORG_ID|DEFAULT_FLAG
xxxx|xxxx|123456| Y
xxxx|xxxx|123456| N
xxxx|xxxx|987654| Y
xxxx|xxxx|567495| Y


0 commentaires

3 Réponses :


0
votes

C'est trop long pour un commentaire.

Vous essayez d'utiliser une contrainte de vérification pour quelque chose pour laquelle elle n'est pas conçue. Vous avez un org_id . Vous devriez avoir une table organisations qui utilise cet identifiant comme clé primaire.

Ensuite, l'indicateur que vous souhaitez stocker doit être dans le tableau organisations . Voila! L'indicateur n'est stocké qu'une seule fois. Vous n'avez pas à vous soucier de le synchroniser entre les différentes lignes.


6 commentaires

Comment un indicateur dans la table des organisations vous dirait-il laquelle des lignes de la table existante est celle par défaut pour un org_id ?


@ThorstenKettner. . . La table des organisations a une seule ligne par org_id . Ce serait la clé primaire.


Oui, mais la table existante a plusieurs entrées par org_id . L'un d'eux par org_id est la valeur par défaut, les autres ne le sont pas. Un simple indicateur dans la table organisations ne peut pas nous dire quelles lignes de la table existante sont les lignes par défaut.


@ThorstenKettner. . . Au fur et à mesure que je lis la question, il n'y a qu'une seule valeur par défaut: "Dans le tableau ci-dessus, la deuxième entrée pour ORG_ID 123456 devrait être rejetée si Y a été inséré comme DEFAULT_FLAG.".


Je suis un peu confus quant à la façon dont le stockage du drapeau dans le tableau des organisations aidera. Pour élaborer un peu sur la question, le tableau actuel est pour une liste des entrepôts. Une organisation peut avoir plusieurs entrepôts, mais un seul entrepôt est la valeur par défaut. Alors, dites-vous de stocker l'entrepôt par défaut dans la table d'organisation, plutôt que de conserver un indicateur dans la table d'entrepôt pour l'entrepôt par défaut qui appartient à une organisation?


@sdj. . . Oui, stocker l'entrepôt par défaut dans la table des organisations aurait du sens.



0
votes

Créez un index unique pour toutes les entrées ORG_ID avec un 'Y', de sorte que chaque ORG_ID ne puisse avoir qu'une seule ligne avec un 'Y':

create unique index idx on mytable(case when default_flag = 'Y' then org_id end)


7 commentaires

Je ne pense pas que cela fonctionnera, car il y aura des entrées répétées, non uniques, NULL pour tous les endroits où default_flag n'est pas «Y».


@Andrew Lazarus: Je pense que l'exigence est qu'il n'y ait pas plus d'une ligne par défaut par org_id . C'est ce que garantit l'index. Ai-je mal lu la demande?


Qu'est-ce qui entre dans l'index pour les lignes où default_flag est «N»?


@Andrew Lazarus: Rien. Les valeurs nulles ne font pas partie de l'index.


Testé. Les NULL vont dans l'index, au moins dans Postgres, mais comme ce n'est pas le cas où NULL = NULL ils ne violent pas unicité. (Ils vont dans l'index pour les tris.)


@Andrew Lazarus: Dans Oracle, lorsque tous les champs indexés sont nuls, aucune entrée n'est faite dans l'index.


continuons cette discussion dans le chat .



0
votes

Je pense qu'une solution techniquement meilleure que celle de Thorsten Kettner, mais en utilisant la même idée, est

CREATE UNIQUE INDEX ON mytable(org_id)
WHERE default_flag = 'Y';

Mais permettez-moi aussi de suggérer un tableau organization_defaults avec deux colonnes, l'une l'ID d'une organisation et l'autre l'ID de mytable est une meilleure approche, comme suggéré dans les commentaires du PO.


2 commentaires

Oracle prend-il en charge les index partiels? Ce serait une nouvelle pour moi. Je les connais depuis PostgreSQL, mais je ne les ai jamais vus dans Oracle.


Je ne sais pas. Je suis resté avec Postgresql, avec un bref voyage forcé vers MySQL. J'apprends maintenant MonetDB [columnar], qui ne prend pas vraiment en charge les index sauf dans le nom, partiel ou autre. Vous pouvez deviner à partir de cette liste combien mes employeurs étaient prêts à dépenser pour une base de données.