2010-03-11 9 views
23

trabajo como desarrollador de un pequeño equipo de desarrollo, y algo me ha molestado hasta el punto en que he decidido actuar ...falta de Oracle de un tipo de datos de bit para las columnas de la tabla

Oracle no admite un Bit tipo de datos, o cualquier otra cosa que tenga sentido en escenarios verdaderos/falsos. Sin embargo, sin inmutarse, antes de unirme al equipo mis antepasados ​​decidieron usar campos char (1) en su lugar, usando una letra específica para denotar sí/verdad. Desafortunadamente, nuestra aplicación está acostumbrada a personas de todo el mundo, y por razones que francamente desafían todos mis intentos de comprensión, el valor utilizado varía a través de la localización.

Sí, sé que es totalmente innecesario para los valores en el back-end que el usuario nunca ve - Sin embargo ...

me he dado cuenta de que esta práctica parece ser cada vez llevado adelante en nuevos desarrollos, que me parece una locura, así que estoy pensando en proponer el número (1,0) para esto en su lugar - 0 se considera falso/no, todo lo demás se interpreta como verdadero/sí ...

Pregunta simple: ¿Alguien puede pensar ¿Por qué esto podría ser una mala idea?

Mientras lo hacemos, ¿alguien sabe por qué Oracle no admite un tipo booleano simple? ¿No es una omisión GLARING?

Saludos en anticipación,

Martin.

+0

Bajo toda reserva, ¿Oracle no ofrece un tipo de datos BOOL o BOOLEAN (quizás solo con las últimas versiones ...)? Realmente no puedo recordar claramente. No he hecho Oracle por más de dos años. De todos modos, NUMBER (1) está bien, dice lo que necesita, al igual que un BIT - 0 o 1, un NÚMERO (1) - 0 o 1, ¿cuál es la diferencia? –

+4

@Will: Number (1, 0) puede ser cualquier número de un solo dígito (0-9), no solo 0 o 1. – Cameron

+0

¡Sí, por supuesto! ¿Pero no tiene control sobre los valores de columna de su tabla de datos? –

Respuesta

10

Prefiero char (1) sobre el número (1), ya que con una selección razonable de caracteres, es obvio qué carácter tiene qué significado booleano.

Por supuesto, deberías luchar contra las diferentes variaciones, elige una y asegúrate de que se usa poniendo restricciones de verificación en las columnas.

Aunque probablemente sea demasiado tarde en su caso, generar el esquema a partir de otra herramienta a menudo cuida al menos el problema de consistencia. Yo personalmente prefiero hibernar para este propósito, pero eso es muy específico de la situación.

Y, por supuesto, esta es una obvia excepción. Para empeorar las cosas, PL/SQL tiene un valor booleano, pero no se puede usar en las sentencias de SQL.

+0

Tanto ésta como las respuestas de Thilo son buenos -. Pero he aceptado éste por el consejo para hacer cumplir las restricciones de comprobación a través ... parece que la verdadera respuesta es "Todo el mundo hace lo suyo, no hay un estándar ... " –

+0

También puede nombrar la columna en consecuencia, como UPDATE_ALLOWED_YN –

2

Número (1) no es mejor que char (1). Especialmente si será además del char existente (1). Eso solo aumentará la confusión.

FWIW, Oracle en vistas internas (como USER_TAB_COLUMNS) utiliza varchar2 (3) (SÍ y NO). Sin embargo, no estoy seguro si son 100% consistentes aquí.

+0

Mi razón para pensar en número (1,0) era que si nada más un valor tendría un significado definido definido. Considero que cualquier cosa que hagamos tiene que coexistir con el código del pasado, pero eso es inevitable, y no tan indeseable como simplemente dejar la situación como está actualmente ... También esperaba que el la naturaleza numérica sería más fácil de procesar para el servidor y, por lo tanto, tal vez (por descuido) más rápida. ¿Le importaría ofrecer un tipo de datos candidato? –

+1

número (1) podría ser un poco más pequeño en el espacio del disco, pero a excepción de las tablas enormes que consisten casi exclusivamente en 'boolean', esto debería ser inaceptable. También siempre tienes las opciones de compresión e índices de mapa de bits que pueden resolver algunos de los efectos negativos relacionados con el espacio. –

+2

@Jens: En realidad, el número (1) es más grande. Ver mi respuesta – DCookie

13

No soy nativo del inglés, así que tiendo a usar 1 y 0 o '1' y '0'. Usar 'S' y 'N' tiene poco sentido si no está codificando en inglés (sí, la codificación en el idioma nativo sí existe). Usar 'SI' y 'NO' o 'S' y 'N' no parece profesional (como nombrar variables con letras acentuadas). Uno y ceros, por el contrario, son bastante estándar si ha codificado en C, PHP o JavaScript. En cualquier caso, siempre agrego la restricción apropiada para deshabilitar cualquier otro carácter. Además de los problemas subjetivos, no creo que haya un aumento notable en el rendimiento al elegir CHAR o NUMBER. Me gustan los números un poco más porque no necesito citarlos :)

Acepto que es una omisión flagrante, pero he leído discusiones muy acaloradas sobre el tema en algunos foros de Oracle; es un tipo de problema religioso. Algunos afirman que los booleanos pertenecen a tipos de datos de aplicaciones y no tienen lugar en el núcleo de la base de datos.Honestamente, creo que es uno de esos que llevamos tanto tiempo sin eso, que es mejor que digamos que fue en cosas de propósito.

Por cierto, MySQL tiene un tipo BOOLEAN pero es un sinónimo de TINYINT (1) por lo que finalmente equivale a 1 y 0; lo cual está bien, porque también tiene las constantes TRUE y FALSE que evalúan a 1 y 0.

+0

Estoy tentado de estar de acuerdo con usted, y sí, he hecho algo de C/PHP en mi pasado. Definitivamente prefiero los números, pero me sorprende descubrir que ocupan más espacio (ver arriba) –

+5

+1 para "Hemos-Hemos-Hemos-Tan-Largo-Sin-eso-que-tuvimos-Mejor-Dígalo" -Was-On-Purpose "Deberíamos acuñar esa frase: WHBSLWITWHBSIWOP. – Baodad

8

Aquí hay una discusión sobre el tema de Ask Tom. Ofrece una vista centrada en Oracle sobre el problema.

En cuanto al almacenamiento, char (1) es en realidad un poco (sin doble sentido) más eficiente:

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

Eso es muy interesante, y no es lo que esperaba. Siento personalmente que los numéricos tienen más claridad ... Leí el debate Ask Tom antes de ver tu publicación (busqué en Google), pero no estoy de acuerdo con su justificación por no tener un booleano/bit ... –

+1

@ Martin: Vea esta discusión de SO para mayor ilustración, prestando particular atención a la respuesta de Quassnoi: http://stackoverflow.com/questions/1087210/oracle-number-comparisons/1087873#1087873 – DCookie

+4

@Martin: Estoy de acuerdo, no hay ninguna razón lógica para excluir el tipo BOOLEAN en la base de datos, solo los pragmáticos. Oracle es un poco esquizofrénico sobre el tema, ya que tienen un tipo BOOLEAN en su lenguaje PL/SQL. Eso solo es la fuente de una gran confusión para los programadores de Oracle la primera vez que se tropiezan con él. – DCookie

23

uso CHAR (1), y una restricción para permitir sólo '1' y '0 '.

...

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

Ahora esta es la respuesta que realmente me gusta ... –

+0

Eso es lo que iba a escribir después de investigar un poco más sobre el caso. De todos modos, aquí hay un enlace que debería ayudar. http://thinkoracle.blogspot.com/2005/07/oracle-boolean.html Además, puede definir un tipo de usuario que sería BIT, por ejemplo, y luego aceptar solo esos valores restringidos. Otro enlace útil: http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#i45441 –

+0

No se olvide de "Predeterminado 0 No nulo", si es necesario. Probé la necesidad - para evitar la inserción nula –

0

La pregunta es antiguo, pero hasta que se utilice la última versión de Oracle sigue siendo una pregunta válida.

Resolvería el problema de esta manera: Cree una tabla que contenga los valores posibles para el texto de visualización verdadero/falso más localizado, es decir, T $ PALABRAS CLAVE itemNo itemText ITEMTEXT_DE ITEMTEXT_FE ... 0 Falso Falsch 1 Verdadero Wahr

En lugar de verdadero/falso que esto podría ser también seleccionada, no se selecciona, etc.

Y a continuación, agregar una clave foreigh a tu columna a esta tabla. De esta forma, solo tiene valores válidos y no cambian con la localización.

Otra buena solución, yo estoy usando una restricción de verificación en su columna de datos. This ofc no funciona si sus valores pueden ser diferentes en la misma base de datos/columna dependiendo de la localización de los clientes.

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

Como dijo DCookie, char (1) es más eficiente. Porque VARCHAR2 (VARCHAR) vacío contiene 1 byte, pero cuando almacenamos 1 caracter y luego vaciar tamaño de 1 byte + con carácter tamaño de 1 byte -> 2 byte necesita almacenar 1 carácter en varchar

0

Oracle internamente usa "bits" (no un tipo de datos per se) en diferentes vistas de Diccionario de datos.

Por ejemplo, dba_users vista tiene:

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

que muestra una manera de solucionar esto de una manera. Si no tiene que modificar bits "booleanos" a menudo, podría utilizar el mismo enfoque que Oracle tenía desde Oracle 6 (al menos). Cree una tabla con una columna NÚMERO y una VISTA además de la que oculta la complejidad de las operaciones BITAND.

ps.En una nota lateral, Oracle JDBC tiene un tipo de datos "Bit" https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html#BIT, así como usted ya sabe que PL/SQL tiene Boolean. Aunque probablemente no te sirva de mucho. Vea el enfoque BITAND arriba si se adapta a su caso.

Cuestiones relacionadas