2010-03-11 6 views
23

Je travaille en tant que développeur sur une petite équipe de développement, et quelque chose m'a agacé au point où je l'ai décidé d'agir ...manque d'Oracle d'un bit type de données pour les colonnes de table

Oracle ne prend pas en charge un peu type de données - ou en fait toute autre chose qui a un sens évident dans les scénarios vrai/faux. Cependant, avant de rejoindre l'équipe, mes ancêtres ont décidé d'utiliser les champs char (1) à la place, en utilisant une lettre spécifique pour indiquer yes/true. Malheureusement, notre application est utilisée par des gens partout dans le monde, et pour des raisons qui défient franchement toutes mes tentatives de compréhension, la valeur utilisée varie à travers la localisation.

Oui, je sais que c'est totalement inutile pour les valeurs dans l'arrière-plan que l'utilisateur ne voit jamais - mais ...

J'ai remarqué que cette pratique semble se reporter dans le nouveau développement, ce qui me frappe comme un fou - alors je pense à proposer plutôt le Nombre (1,0) pour cela - 0 étant considéré comme faux/non, rien d'autre étant interprété comme vrai/oui ...

Simple question - Quelqu'un peut-il penser? d'une raison que cela pourrait être une mauvaise idée?

Pendant que nous y sommes, quelqu'un sait-il pourquoi Oracle ne supporte pas un type booléen simple? N'est-ce pas une ommission GLARING?

Bravo en prévision,

Martin.

+0

Sous toutes ses réserves, Oracle n'offre-t-il pas un type de données BOOL ou BOOLEAN (peut-être est-ce seulement avec les dernières versions ...)? Je ne peux pas vraiment me souvenir clairement. Je n'ai pas fait Oracle depuis plus de deux ans maintenant. Quoi qu'il en soit, NUMBER (1) est très bien, il dit ce qu'il faut, tout comme un BIT - 0 ou 1, un NUMBER (1) - 0 ou 1, quelle est la différence? –

+4

@Will: Number (1, 0) peut être n'importe quel nombre à un chiffre (0-9), pas seulement 0 ou 1. – Cameron

+0

Oui, bien sûr! Mais n'avez-vous aucun contrôle sur vos valeurs de colonne datatable? –

Répondre

10

Je préfère char (1) sur nombre (1), car avec un choix raisonnable de caractères, il est évident quel caractère a une signification booléenne.

Bien sûr, vous devriez combattre toutes les variantes, en choisir une et en assurer l'utilisation en mettant des contraintes de vérification sur les colonnes.

Bien qu'il soit probablement trop tard dans votre cas, la génération du schéma à partir d'un autre outil prend souvent soin au moins du problème de cohérence. Personnellement, je préfère hiberner à cette fin, mais c'est très spécifique à la situation.

Et bien sûr, c'est une obnégation flagrante. Pour empirer les choses, PL/SQL a un booléen, mais vous ne pouvez pas l'utiliser dans les instructions SQL.

+0

Les réponses de Thilo et celles-ci sont bonnes - mais j'ai accepté celle-ci à cause du conseil pour imposer la conformité en vérifiant les contraintes ... On dirait que la vraie réponse est "Tout le monde fait leur propre chose, il n'y a pas de norme ... " –

+0

Vous pouvez également nommer la colonne en conséquence, comme UPDATE_ALLOWED_YN –

2

Le nombre (1) n'est pas meilleur que char (1). Surtout si ce sera en plus du char existant (1). Cela ne fera qu'ajouter à la confusion. FWIW, Oracle dans les vues internes (telles que USER_TAB_COLUMNS) utilise varchar2 (3) (YES et NO). Je ne sais pas si elles sont 100% cohérentes ici, cependant.

+0

Ma raison de penser à Number (1,0) était que si rien d'autre une valeur aurait un sens défini défini. Je comprends ce que nous faisons de coexister avec le code du passé, mais c'est inévitable - et pas aussi indésirable que de simplement laisser la situation telle qu'elle est actuellement ... J'espérais aussi que le la nature numérique serait plus facile à traiter pour le serveur, et donc peut-être (de manière négligeable) plus rapide. Voulez-vous proposer un type de données candidat? –

+1

nombre (1) peut être un peu plus petit sur l'espace disque, mais à l'exception des énormes tables constituées presque uniquement de 'booléen' cela devrait être négligeable. De plus, vous avez toujours les options d'indices de compression et de bitmap qui pourraient résoudre certains des effets négatifs liés à l'espace. –

+2

@Jens: En fait, le nombre (1) est plus grand. Vois ma réponse. – DCookie

13

Je ne suis pas un natif anglais donc j'ai tendance à utiliser 1 et 0 ou '1' et '0'. Utiliser 'Y' et 'N' n'a pas beaucoup de sens si vous ne codez pas en anglais (oui, le codage en langue maternelle existe). Utiliser 'SI' et 'NON' ou 'S' et 'N' n'a pas l'air professionnel (tout comme nommer des variables avec des lettres accentuées). Les uns et les zéros, au contraire, sont assez standard si vous avez codé en C, PHP ou JavaScript. Dans tous les cas, j'ajoute toujours la contrainte appropriée pour interdire tout autre personnage. Mis à part les problèmes subjectifs, je ne pense pas qu'il y ait un gain de performance notable dans le choix de CHAR ou de NUMBER. J'aime les chiffres un peu plus parce que je n'ai pas besoin de les citer :)

Je suis d'accord c'est une omission flagrante mais j'ai lu des discussions sérieusement passionnées sur le sujet dans certains forums Oracle; c'est une sorte de problème religieux. Certains prétendent que les booléens appartiennent aux types de données d'application et n'ont pas leur place dans le noyau de base de données.Honnêtement, je crois que c'est l'un de ceux que nous avons été si longtemps sans que nous ayons mieux à dire que c'était sur les choses. A propos, MySQL a un type BOOLEAN mais c'est un synonyme de TINYINT (1) donc il est finalement égal à 1 et 0; ce qui est bien, car il a aussi les constantes VRAI et FAUX qui évaluent à 1 et 0.

+0

Je suis tenté d'être d'accord avec vous - et oui, j'ai fait du C/PHP dans mon passé. Je préfère nettement les numériques, mais je suis surpris de constater qu'ils prennent plus de place (voir ci-dessus) –

+5

+1 pour "Nous-Avons-Long-Sans-Ça-Ça-Nous-Avons-Mieux-Dit-It" -Was-But-Purpose "Nous devons frapper cette phrase: WHBSLWITWHBSIWOP. – Baodad

8

Voici une discussion Ask Tom sur le sujet. Donne une vue centrée sur Oracle sur le problème.

En ce qui concerne le stockage, char (1) est en fait un peu (sans jeu de mots) plus efficace:

SQL> CREATE TABLE xx (c CHAR(1), n NUMBER); 

Table created 

SQL> insert into xx values('T', 1); 

1 row inserted 

SQL> select dump(c), dump(n) from xx; 

DUMP(C)    DUMP(N) 
------------------- ------------- 
Typ=96 Len=1: 84 Typ=2 Len=2: 193,2 
+3

C'est très intéressant - et pas ce à quoi je m'attendais. Je persiste à penser personnellement que les numériques ont plus de clarté ... J'ai lu la discussion Ask Tom avant de voir votre message (googled around), mais je ne suis pas d'accord avec sa justification de ne pas avoir un booléen/bit ... –

+1

@ Martin: Voir cette discussion SO pour plus d'éclaircissement, en accordant une attention particulière à la réponse de Quassnoi: http://stackoverflow.com/questions/1087210/oracle-number-comparisons/1087873#1087873 – DCookie

+4

@Martin: Je suis d'accord, il n'y a pas de raison logique de exclure le type BOOLEAN dans la base de données, seulement les types pragmatiques. Oracle est un peu schizophrène sur le problème, car ils ont un type BOOLEAN dans leur langage PL/SQL. Cela seul est la source d'une grande confusion pour les programmeurs Oracle la première fois qu'ils s'y heurtent. – DCookie

23

Utilisez un CHAR (1), et une contrainte pour permettre que '1' et « 0 '.

...

col CHAR(1), 
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('1','0')) 
+0

Maintenant, cette réponse me plaît vraiment .. –

+0

C'est ce que j'allais écrire après avoir fait quelques recherches supplémentaires sur l'affaire. Quoi qu'il en soit, voici un lien qui devrait aider. http://thinkoracle.blogspot.com/2005/07/oracle-boolean.html En outre, vous pouvez définir vous-même un type d'utilisateur qui serait par exemple BIT, puis n'accepter que les valeurs contraintes. Un autre lien utile: http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#i45441 –

+0

N'oubliez pas "Default 0 Not Null", si nécessaire. J'ai testé la nécessité - pour éviter l'insertion nulle –

0

La question est ancienne, mais jusqu'à ce que la dernière version d'Oracle est utilisé, il est encore une question valable.

Je résoudrais le problème de cette façon: Créer une table qui contient les valeurs possibles pour vrai/faux plus le texte d'affichage localisé f.e. T $ KEYWORDS ITEMNO libelléLigne ITEMTEXT_DE ITEMTEXT_FE ... 0 Faux Falsch 1 Vrai Wahr

Au lieu de ce Vrai/Faux pourrait aussi être sélectionné, Non sélectionné, etc.

Et puis ajoutez une touche foreigh à votre colonne à cette table. De cette façon, vous n'avez que des valeurs valides et elles ne changent pas avec la localisation.

Une autre bonne solution imho utilise une contrainte de vérification sur votre colonne de données. Cela ne fonctionne pas si vos valeurs peuvent être différentes dans la même base de données/colonne en fonction de la localisation des clients.

alter table tblLocations add flag number CONSTRAINT <constraintname> CHECK (flag IN (1,0));

-1

https://docs.oracle.com/cd/E17952_01/refman-5.5-en/char.html enter image description here

Comme dit DCookie, car (1) est plus efficace. Parce que VARCHAR2 (VARCHAR) vide contient 1 octet, mais lorsque nous stockons 1 caractère puis vide 1 octet taille + avec caractère 1 octet taille -> 2 octets besoin de stocker 1 caractère dans varchar

0

Oracle utilise en interne "bits" (pas un type de données en soi) dans différentes vues du dictionnaire de données.

Par exemple, vue de dba_users a:

.. 
     , DECODE (BITAND (u.spare1, 128), 128, 'YES', 'NO') 
.. 
     , DECODE (BITAND (u.spare1, 256), 256, 'Y', 'N') 
.. 

qui montre un moyen de contourner cela d'une manière. Si vous n'avez pas besoin de modifier souvent les bits "booléens", vous pouvez utiliser la même approche qu'Oracle depuis Oracle 6 (au moins). Créez une table avec une colonne NUMBER et une vue en plus de celle qui cache la complexité des opérations BITAND.

ps.D'un autre côté, Oracle JDBC a un type de données "Bit" https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html#BIT et vous savez déjà que PL/SQL a une valeur booléenne. Bien que cela ne vous aide probablement pas beaucoup. Voir l'approche BITAND ci-dessus si cela convient à votre cas.

Questions connexes