2008-10-08 6 views
14

Usando Oracle, si el valor de una columna puede ser 'SÍ' o 'NO', ¿es posible restringir una tabla para que solo una fila pueda tener un valor 'SÍ'?¿Cómo restringir una tabla de base de datos para que solo una fila pueda tener un valor particular en una columna?

Preferiría rediseñar la estructura de la tabla, pero esto no es posible.

[UDPATE] Lamentablemente, los valores nulos no están permitidos en esta tabla.

+0

Oh querido - no se permiten nulos - eso cambia las cosas un poco - ahora tiene que ir con el índice basado en funciones (@Tony Andrews). Todavía evitar disparadores y transacciones autónomas. –

Respuesta

19

utiliza un índice basado en las funciones:

create unique index only_one_yes on mytable 
(case when col='YES' then 'YES' end); 

Oracle sólo indexa teclas que no son completamente nula, y la expresión CASE aquí se asegura de que todos los valores del 'no' se cambian a valores nulos y por tanto no indexados.

2

No funciona en la definición de la tabla.

Sin embargo, si actualiza la tabla utilizando un desencadenante que invoca un procedimiento almacenado, puede asegurarse de que solo una fila contenga "SÍ".

  1. Conjunto todas las filas a "NO"
  2. Establecer la fila que desea SÍ
+0

-1 para una solución basada en trigger0. Nunca funcionan bien para imponer restricciones a nivel de tabla –

6

Este es un truco kludgy, pero si la columna permite valores NULL, entonces usted podría usar NULL en lugar de "NO" y use "SÍ" igual que antes. Aplique una restricción de clave única a esa columna, y nunca obtendrá dos valores "SÍ", pero aún tendrá muchos NO.

Actualización: @Nick Pierpoint: sugirió agregar una restricción de verificación para que los valores de la columna estén restringidos a solo "SÍ" y NULO. La sintaxis está resuelta en su respuesta.

+0

No hay nada de malo en eso: ese es el camino a seguir.+1 –

+0

También deberá agregar una restricción de verificación en la tabla para que no permita nada que no sea "SÍ" o nulo. –

+0

si quieres que se vea bien, probablemente también puedas envolver una vista con NVL, entonces obtendrías tu Y/N –

1

¿Oracle admite algo así como índices filtrados (la semana pasada me enteré de que, por ejemplo, MSSQL2008 lo hace)? Tal vez pueda definir una clave única que se aplica solo a las filas con el valor "Sí" en su columna.

+0

No hay índices filtrados, pero los FBI ofrecen una manera más flexible (si bien podría decirse que menos concisa) de hacer lo mismo. – orbfish

-2

Supongo que usaría una segunda tabla para señalar la fila apropiada en su tabla actual. Esa otra tabla también podría usarse para almacenar valores de otras variables.

+0

difícil de mantener en un entorno coherente –

2

A raíz de mi comentario a una respuesta anterior por yukondude, me gustaría añadir un índice único y una restricción de comprobación:

create table mytest (
    yesorno varchar2(3 char) 
); 

create unique index uk_mytest_yesorno on mytest(yesorno); 

alter table mytest add constraint ck_mytest_yesorno check (yesorno is null or yesorno = 'YES'); 
+0

Creo que siempre que NULL sea adecuado como el valor "no sí", este método tiene la ventaja sobre el método FBI porque las restricciones pueden al menos ser aprovechadas por el optimizador. Creo que las consultas con predicados sobre yesorno = 'SÍ' y yesorno es nulo obtendrán mejores estimaciones de cardianidad. –

+0

Dado que solo va a haber una fila con "SÍ" y cada dos filas con un valor nulo, obtendrá el índice utilizado para encontrar la fila "SÍ" y una exploración completa (con bastante acierto) para obtener todo lo demás (los "NO" s). –

+0

Claro, solo se trata de si reemplazar "No" con Null es un compromiso que vale la pena para lograr este objetivo. –

4

Usted tendrá que comprobar un artículo de Tom Kyte con exactamente haciendo esta pregunta y su respuesta:

http://tkyte.blogspot.com/2008/05/another-of-day.html

Resumen: no utilizar disparadores, no utilizar transacciones autónomas, utilizar dos tablas.

Si utiliza una base de datos Oracle, entonces DEBE conocer AskTom y obtener sus libros.

+0

La pregunta que se hace es ligeramente diferente a esto, en la pregunta de Tom, la tabla podría tener varias "Y", pero solo 1 por país. Cuando lo leí, en este ejemplo, la tabla solo puede tener 1 Sí, en cuyo caso la solución de índice parece funcionar. Pero sí, AskTom es una necesidad para la base de datos Oracle. –

+0

Estoy de acuerdo. Si a Tom se le hiciera esta pregunta, supongo que definitivamente buscaría la solución de índice. –

Cuestiones relacionadas