40 - Restriccion check


Problema:

Trabajamos con la tabla "libros" de una librería.
Eliminamos la tabla:

  drop table libros;

La creamos e ingresamos algunos registros:

 create table libros(
  codigo number(5),
  titulo varchar2(40),
  autor varchar2(30),
  editorial varchar2(15),
  preciomin number(5,2),
  preciomay number(5,2)
 );

 insert into libros values (1,'Uno','Bach','Planeta',22,20);
 insert into libros values (2,'El quijote','Cervantes','Emece',15,13);
 insert into libros values (3,'Aprenda PHP','Mario Molina','Siglo XXI',53,48);
 insert into libros values (4,'Java en 10 minutos','Garcia','Siglo XXI',35,40);

Agregamos una restricción "primary key" para el campo "codigo":

 alter table libros
 add constraint PK_libros_codigo
 primary key (codigo);

Agregamos una restricción única, la clave única consta de 3 campos, "titulo", "autor" y "editorial":

 alter table libros
 add constraint UQ_libros
 unique (titulo,codigo,editorial);

Agregamos una restricción "check" para asegurar que los valores de los campos correspondientes a precios no puedan ser negativos:

 alter table libros
 add constraint CK_libros_precios_positivo
 check (preciomin>=0 and preciomay>=0);

Intentamos ingresar un valor inválido para algún campo correspondiente al precio, que vaya en contra de la restricción (por ejemplo el valor "-15"):

 insert into libros values (5,'Matematica estas ahi','Paenza','Siglo XXI',-15,30);

aparecerá un mensaje de error indicando que hay conflicto con la restricción de control creada anteriormente y la inserción no se realiza.

Igualmente si intentamos actualizar un precio, que vaya en contra de la restricción:

 update libros set preciomay=-20 where titulo='Uno';

Si intentamos agregar una restricción que no permita que el precio mayorista supere el precio minorista:

 alter table libros
 add constraint CK_libros_preciominmay
 check (preciomay<=preciomin);

aparece un mensaje de error y la sentencia no se ejecuta, porque hay un registro que no cumple con la restricción que intentamos establecer. Podemos modificar los datos que no cumplen la condición de la restricción:

 update libros set preciomay=30
  where titulo='Java en 10 minutos';

Ahora Oracle si nos permite agregar la restricción "check" que impida que se ingresen valores para "preciomay" superiores a "preciomin":

 alter table libros
 add constraint CK_libros_preciominmay
 check (preciomay<=preciomin);

Veamos las restricciones de la tabla:

 select *from user_constraints where table_name='LIBROS';

Aparece la siguiente tabla (simplificada) resultado:

OWNER	CONSTRAINT_NAME			CONSTRAINT_TYPE		TABLE_NAME	SEARCH_CONDITION
--------------------------------------------------------------------------------------------------
SYSTEM	PK_LIBROS_CODIGO		P               	LIBROS
SYSTEM	UQ_LIBROS			U			LIBROS
SYSTEM	CK_LIBROS_PRECIOS_POSITIVO	C			LIBROS		preciomin>=0 and preciomay>=0
SYSTEM	CK_LIBROS_PRECIOMINMAY		C			LIBROS		preciomay<=preciomin

Note que en el caso de las restricciones de control, en las cuales muestra "C" en el tipo de constraint, la columna "SEARCH_CONDITION" muestra la regla que debe cumplirse; en caso de ser una restricción "primary key" o unique", esa columna queda vacía.

Intentamos ingresar un registro que infrinja la restricción "CK_libros_preciominmax":

 insert into libros values (6,'El gato con botas',null,'Planeta',25,30);

Mensaje de error.

Consultamos "user_cons_columns":

 select *from user_cons_columns where table_name='LIBROS';

Aparece la siguiente información simplificada:

OWNER		CONSTRAINT_NAME			TABLE_NAME	COLUMN_NAME	POSITION
-----------------------------------------------------------------------------------------
SYSTEM		PK_LIBROS_CODIGO		LIBROS		CODIGO		1
SYSTEM		UQ_LIBROS			LIBROS		EDITORIAL	3
SYSTEM		UQ_LIBROS			LIBROS		CODIGO		2
SYSTEM		UQ_LIBROS			LIBROS		TITULO		1
SYSTEM		CK_LIBROS_PRECIOS_POSITIVO	LIBROS		PRECIOMAY
SYSTEM		CK_LIBROS_PRECIOS_POSITIVO	LIBROS		PRECIOMIN
SYSTEM		CK_LIBROS_PRECIOMINMAY		LIBROS		PRECIOMAY
SYSTEM		CK_LIBROS_PRECIOMINMAY		LIBROS		PRECIOMIN

Analizamos la información: la tabla tiene 4 restricciones, 1 "primary key", 1 "unique" y 2 "check". La restricción "primarykey" ocupa una sola fila porque fue definida para 1 solo campo, por ello, en la columna "POSITION" aparece "1". La restricción única ocupa tres filas porque fue definida con 3 campos cuyo orden está indicado en la columna "POSITION". La columna "POSITION" muestra información si la restricción es "primary key" o "unique" indicando el orden de los campos. La restricción de control "CK_libros_precios_positivo" ocupa 2 filas porque en su definición se nombran 2 campos (indicados en "COLUMN_NAME"). La restricción de control "CK_libros_preciominmax" ocupa 2 filas porque en su definición se nombran 2 campos (indicados en "COLUMN_NAME").

Ingresemos el siguiente lote de comandos en el Oracle SQL Developer:

 drop table libros;

 create table libros(
  codigo number(5),
  titulo varchar2(40),
  autor varchar2(30),
  editorial varchar2(15),
  preciomin number(5,2),
  preciomay number(5,2)
 );

 insert into libros values (1,'Uno','Bach','Planeta',22,20);
 insert into libros values (2,'El quijote','Cervantes','Emece',15,13);
 insert into libros values (3,'Aprenda PHP','Mario Molina','Siglo XXI',53,48);
 insert into libros values (4,'Java en 10 minutos','Garcia','Siglo XXI',35,40);

 alter table libros
   add constraint PK_libros_codigo
   primary key (codigo);

 alter table libros
   add constraint UQ_libros
   unique (titulo,codigo,editorial);

 alter table libros
   add constraint CK_libros_precios_positivo
   check (preciomin>=0 and preciomay>=0);

 insert into libros values (5,'Matematica estas ahi','Paenza','Siglo XXI',-15,30);

 update libros set preciomay=-20 where titulo='Uno';

 alter table libros
   add constraint CK_libros_preciominmay
   check (preciomay<=preciomin);

 update libros set preciomay=30
  where titulo='Java en 10 minutos';

 alter table libros
   add constraint CK_libros_preciominmay
   check (preciomay<=preciomin);

 select *from user_constraints where table_name='LIBROS';

 insert into libros values (6,'El gato con botas',null,'Planeta',25,30);

 select *from user_cons_columns where table_name='LIBROS';

Retornar