Champ booléen dans Oracle

145

Hier, je voulais ajouter un champ booléen à une table Oracle. Cependant, il n'y a pas réellement de type de données booléen dans Oracle. Quelqu'un ici connaît-il la meilleure façon de simuler un booléen? Googler le sujet a découvert plusieurs approches

  1. Utilisez un entier et ne vous souciez pas de lui attribuer autre chose que 0 ou 1.

  2. Utilisez un champ de caractère avec «Y» ou «N» comme deux seules valeurs.

  3. Utilisez une énumération avec la contrainte CHECK.

Les développeurs Oracle expérimentés savent-ils quelle approche est préférée / canonique?

Eli Courtwright
la source
195
Je souhaite qu'Oracle ait un walltype de données pour que je puisse me casser la tête contre lui lorsque j'utilise des booléens.
Greg

Réponses:

82

J'ai trouvé ce lien utile.

Voici le paragraphe mettant en évidence certains des avantages / inconvénients de chaque approche.

La conception la plus courante consiste à imiter les nombreux indicateurs de type booléen que les vues du dictionnaire de données d'Oracle utilisent, en sélectionnant «Y» pour vrai et «N» pour faux. Cependant, pour interagir correctement avec les environnements hôtes, tels que JDBC, OCCI et d'autres environnements de programmation, il est préférable de sélectionner 0 pour false et 1 pour true afin qu'il puisse fonctionner correctement avec les fonctions getBoolean et setBoolean.

Fondamentalement, ils préconisent la méthode numéro 2, par souci d'efficacité, en utilisant

  • valeurs de 0/1 (en raison de l'interopérabilité avec les JDBC, getBoolean()etc.) avec une contrainte de vérification
  • un type de CHAR (car il utilise moins d'espace que NUMBER).

Leur exemple:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`
ColinYounger
la source
31
Je déconseille d'utiliser «N» et «Y» car il dépend de la langue. Les anglophones oublient parfois que la plupart des pays du monde ne représentent pas le concept de vérité avec la lettre Y. En revanche, la signification de 0 et 1 est constante à travers les barrières linguistiques.
Andrew Spencer
7
0 et 1 en tant que valeurs booléennes ne sont pas cohérents en informatique - les langages de type script shell ont tendance à avoir 0 comme succès, et non nul comme échec, tandis que les langages de type C ont tendance à avoir 0 comme échec et non nul comme succès.
Phil
41
En tant que valeurs booléennes , elles sont sans ambiguïté. Les codes de retour de processus ne sont pas des valeurs booléennes.
Andrew Spencer
13
Pourquoi tout ce paragraphe du lien fourni a-t-il été ignoré dans cette réponse? "La conception la plus courante consiste à imiter les nombreux indicateurs de type booléen utilisés par les vues du dictionnaire de données d'Oracle, en sélectionnant« Y »pour vrai et« N »pour faux. Cependant, pour interagir correctement avec les environnements hôtes, tels que JDBC, OCCI, et d'autres environnements de programmation, il est préférable de sélectionner 0 pour false et 1 pour true afin de pouvoir fonctionner correctement avec les fonctions getBoolean et setBoolean. " Ils déclarent que si «O / N» est courant, il est recommandé d'utiliser «0/1» pour augmenter la compatibilité avec les environnements hôtes.
justin.hughey
28

Oracle lui-même utilise Y / N pour les valeurs booléennes. Pour être complet, il convient de noter que pl / sql a un type booléen, ce ne sont que les tables qui n'en ont pas.

Si vous utilisez le champ pour indiquer si l'enregistrement doit être traité ou non, vous pouvez envisager d'utiliser Y et NULL comme valeurs. Cela fait un très petit index (lecture rapide) qui prend très peu de place.

Leigh Riffel
la source
7
+1 Bon point sur les vues internes d'Oracle et les tables utilisant Y / N. Si Oracle le fait de cette façon, il doit être juste! :)
Jeffrey Kemp
Pouvez-vous expliquer comment Y et NULL forment un petit indice par rapport à Y et N?
styfle
6
Les NULL ne sont pas indexés dans Oracle, donc si votre index contient quelques caractères Y, mais surtout des NULL, vous aurez un très petit index.
Leigh Riffel
25

Pour utiliser le moins d'espace, vous devez utiliser un champ CHAR contraint à «Y» ou «N». Oracle ne prend pas en charge les types de données BOOLEAN, BIT ou TINYINT, donc un octet de CHAR est aussi petit que possible.

Bill le lézard
la source
19

La meilleure option est 0 et 1 (sous forme de nombres - une autre réponse suggère 0 et 1 comme CHAR pour l'efficacité de l'espace mais c'est un peu trop tordu pour moi), en utilisant NOT NULL et une contrainte de vérification pour limiter le contenu à ces valeurs. (Si vous avez besoin que la colonne soit nullable, alors ce n'est pas un booléen que vous traitez mais une énumération avec trois valeurs ...)

Avantages de 0/1:

  • Indépendant de la langue. «Y» et «N» conviendraient si tout le monde l'utilisait. Mais ils ne le font pas. En France, ils utilisent «O» et «N» (j'ai vu cela de mes propres yeux). Je n'ai pas programmé en Finlande pour voir s'ils utilisent «E» et «K» là-bas - ils sont sans aucun doute plus intelligents que cela, mais vous ne pouvez pas en être sûr.
  • Conforme à la pratique des langages de programmation largement utilisés (C, C ++, Perl, Javascript)
  • Joue mieux avec la couche d'application, par exemple Hibernate
  • Mène à SQL plus succinct, par exemple, pour savoir combien de bananes sont prêtes à manger select sum(is_ripe) from bananasau lieu de select count(*) from bananas where is_ripe = 'Y'ou même (yuk)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Avantages de 'Y' / 'N':

  • Prend moins de place que 0/1
  • C'est ce que suggère Oracle, c'est peut-être ce à quoi certaines personnes sont plus habituées

Une autre affiche a suggéré «Y» / null pour les gains de performance. Si vous avez prouvé que vous avez besoin des performances, alors c'est juste, mais sinon évitez car cela rend les requêtes moins naturelles ( some_column is nullau lieu de some_column = 0) et dans une jointure gauche, vous confondez la fausseté avec des enregistrements inexistants.

Andrew Spencer
la source
3
Vous trouvez que ces jours-ci, beaucoup de booléens sont TriState c'est à dire vrai, faux et inconnu. ce qui correspond parfaitement à l'idée nulle de base de données. simplement parce que beaucoup de fois ne sachant qu'aucune réponse n'a été donnée est d'une importance vitale
MikeT
1
Oui, vrai-faux-inconnu peut être requis, mais si j'étais pointilleux (ce que je suis), je dirais que cela ne devrait pas vraiment être décrit comme un booléen, car ce n'est pas le cas.
Andrew Spencer
2
si vous allez être aussi pointilleux, vous pouvez faire le même argument pour chaque type de données. comme sous une définition stricte entier, double (je suppose que je devrais dire double longueur twos complément virgule flottante), binaire, chaîne, etc. tous supposent qu'une valeur est fournie mais les implémentations de base de données ajoutent toujours une option de valeur nulle Boolean n'est pas différente
MikeT
1
vrai, sur une note positive pour votre méthode si vous configurez correctement votre numéro, il peut également être stocké dans le même octet qu'un champ de caractère, ce qui annule l'argument de taille contre l'utilisation de 0/1, je ne trouve pas le lien actuellement mais le stockage pour un nombre varie de 1 à 22 octets selon la configuration
MikeT
4
Je soupçonne que les votes négatifs sont dus à un point de vue hérité sur le choix de l'implémentation la plus efficace en mémoire. Cette efficacité de la mémoire courante est beaucoup moins prioritaire et doit être prise en compte après utilisabilité et compatibilité. À tous ceux qui pourraient répondre à ce commentaire, je recommande de lire sur l'optimisation prématurée. C'est exactement ce qui se produit en choisissant «Y / N» uniquement en fonction de l'efficacité de la mémoire. Vous perdez la compatibilité native avec un ensemble de frameworks couramment utilisés à cause de cette décision.
justin.hughey
5

Soit 1/0, soit Y / N avec une contrainte de vérification dessus. la manière éther est très bien. Personnellement, je préfère 1/0 car je fais beaucoup de travail en perl, et il est vraiment facile de faire des opérations booléennes perl sur les champs de base de données.

Si vous voulez une discussion vraiment approfondie de cette question avec l'un des honchos à la tête d'Oracles, découvrez ce que Tom Kyte a à dire à ce sujet ici

Matthew Watson
la source
1/0 est dit "moins efficace en mémoire" mais ... je l'aime plus aussi (et hibernate nécessite apparemment 1/0 pour un booléen)
rogerdpack
1/0 est la valeur par défaut d'Hibernate pour un booléen, mais vous pouvez définir n'importe quel mappage personnalisé de votre choix.
Andrew Spencer
@rogerdpack c'est parce qu'un champ char est de 1 octet, ou 2 octets pour nchar, où selon la façon dont il est défini un nombre peut être de 1 à 22 octets
MikeT
4

La base de données sur laquelle j'ai effectué la plupart de mes travaux utilisait «Y» / «N» comme booléen. Avec cette implémentation, vous pouvez réaliser quelques astuces comme:

  1. Comptez les lignes qui sont vraies:
    SELECT SUM (CASE WHEN BOOLEAN_FLAG = 'Y' THEN 1 ELSE 0) FROM X

  2. Lors du regroupement de lignes, appliquez la logique «Si une ligne est vraie, alors tout est vrai»:
    SELECT MAX (BOOLEAN_FLAG) FROM Y
    Inversement, utilisez MIN pour forcer le regroupement à faux si une ligne est fausse.

Erick B
la source
4
en fait, les exemples présentés sont également utiles pour l'approche 0/1 - et, à mon humble avis, plus rapide.
igorsantos07
2

Un exemple de travail pour implémenter la réponse acceptée en ajoutant une colonne "Boolean" à une table existante dans une base de données oracle (en utilisant numbertype):

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

Cela crée une nouvelle colonne dans my_table_name appelée my_new_boolean_columnavec les valeurs par défaut de 0. La colonne n'acceptera pas les NULLvaleurs et restreint les valeurs acceptées à 0ou 1.

Ben.12
la source
1

Dans nos bases de données, nous utilisons une énumération qui garantit que nous la transmettons TRUE ou FALSE. Si vous le faites de l'une des deux premières façons, il est trop facile de commencer à ajouter une nouvelle signification à l'entier sans passer par une conception appropriée, ou de finir avec ce champ de caractères ayant Y, y, N, n, T, t, F, f et avoir à se souvenir quelle section de code utilise quelle table et quelle version de true elle utilise.

Ryan Ahearn
la source