miércoles, 21 de marzo de 2012

Restricciones CHECK en Microsoft Sql Server

Las restricciones CHECK exigen la integridad del dominio mediante la limitación de los valores que puede aceptar una columna. Son similares a las restricciones FOREIGN KEY porque controlan los valores que se colocan en una columna. La diferencia reside en la forma en que determinan qué valores son válidos: las restricciones FOREIGN KEY obtienen la lista de valores válidos de otra tabla, mientras que las restricciones CHECK determinan los valores válidos a partir de una expresión lógica que no se basa en datos de otra columna. Por ejemplo, es posible limitar el intervalo de valores para una columna salary creando una restricción CHECK que sólo permita datos entre 15.000 y 100.000 dólares. De este modo se impide que se escriban salarios superiores al intervalo de salario normal.

Sintaxis básica:

alter table NOMBRETABLA
      add constraint NOMBRECONSTRAINT
      check CONDICION;


Puede crear una restricción CHECK con cualquier expresión lógica (booleana) que devuelva TRUE (verdadero) o FALSE (falso) basándose en operadores lógicos.
Para el ejemplo anterior, la expresión lógica sería:
Puede aplicar varias restricciones CHECK a una sola columna. También puede aplicar una sola restricción CHECK a varias columnas si se crea en el nivel de la tabla. Por ejemplo, una restricción CHECK para varias columnas se puede utilizar para confirmar que cualquier fila con un valor USA en la columna country/region tiene también un valor de dos caracteres en la columna state. Así se pueden comprobar varias condiciones en un mismo sitio.


Advertencia :

Las restricciones que incluyen la conversión de tipos de datos implícitos o explícitos pueden impedir la correcta ejecución de determinadas operaciones. Por ejemplo, las restricciones definidas en tablas que son orígenes de un cambio de partición pueden impedir que una operación ALTER TABLE...SWITCH se realice correctamente. Evite la conversión de tipos de datos en las definiciones de las restricciones. 


Limitaciones de las restricciones CHECK

Las restricciones CHECK rechazan los valores que se evalúan como FALSE. Puesto que los valores nulos se evalúan como UNKNOWN, su presencia en las expresiones puede reemplazar una restricción. Por ejemplo, supongamos que coloca una restricción en una columna intMyColumn que especifica que MyColumn sólo puede contener el valor 10 (MyColumn=10). Si inserta el valor NULL en MyColumn, Motor de base de datos inserta NULL y no devuelve un error.

Una restricción CHECK devuelve TRUE cuando la condición que está comprobando no es FALSE para ninguna fila de la tabla. Si una tabla recién creada no tiene filas, cualquier restricción CHECK en esta tabla se considerará válida. Esta situación puede generar resultados inesperados, como en el siguiente ejemplo.

CREATE TABLE CheckTbl (col1 int, col2 int);
GO
CREATE FUNCTION CheckFnctn()
RETURNS int
AS
BEGIN
   DECLARE @retval int
   SELECT @retval = COUNT(*) FROM CheckTbl
   RETURN @retval
END;
GO
ALTER TABLE CheckTbl
ADD CONSTRAINT chkRowCount CHECK (dbo.CheckFnctn() >= 1 );
GO

EJEMPLOS:

Suponiendo que tenemos la tabla "libros" de una librería que tiene los siguientes campos: codigo, titulo, autor, editorial, preciomin (que indica el precio para los minoristas) y preciomay (que indica el precio para los mayoristas).

Los campos correspondientes a los precios (minorista y mayorista) se definen de tipo decimal(5,2), es decir, aceptan valores entre -999.99 y 999.99. 

a) Podemos controlar que no se ingresen valores negativos para dichos campos agregando una restricción "check":

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

NOTA: Este tipo de restricción verifica los datos cada vez que se ejecuta una sentencia "insert" o "update", es decir, actúa en inserciones y actualizaciones.


Si la tabla contiene registros que no cumplen con la restricción que se va a establecer, la restricción no se puede establecer, hasta que todos los registros cumplan con dicha restricción.

La condición puede hacer referencia a otros campos de la misma tabla.
Por ejemplo, 
b) Podemos controlar que el precio mayorista no sea mayor al precio minorista:

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


Por convención, cuando demos el nombre a las restricciones "check" seguiremos la misma estructura: comenzamos con "CK", seguido del nombre de la tabla, del campo y alguna palabra con la cual podamos identificar fácilmente de qué se trata la restricción, por si tenemos varias restricciones "check" para el mismo campo.

Un campo puede tener varias restricciones restricciones "check" y una restricción "check" puede incluir varios campos.

Las condiciones para restricciones "check" también pueden pueden incluir un patrón o una lista de valores. 
Por ejemplo: 
c) Establecer que cierto campo conste de 4 caracteres, 2 letras y 2 dígitos:

 ...
 check (CAMPO like '[A-Z][A-Z][0-9][0-9]');
O establecer que cierto campo asuma sólo los valores que se listan:

 ...
 check (CAMPO in ('lunes','miercoles','viernes'));
No se puede aplicar esta restricción junto con la propiedad "identity".


OBSERVACIONES IMPORTANTES: 
  • Si un campo permite valores nulos, "null" es un valor aceptado aunque no esté incluido en la condición de restricción.


  • Si intentamos establecer una restricción "check" para un campo que entra en conflicto con otra restricción "check" establecida al mismo campo, SQL Server no lo permite.


  • Pero si establecemos una restricción "check" para un campo que entra en conflicto con una restricción "default" establecida para el mismo campo, SQL Server lo permite; pero al intentar ingresar un registro, aparece un mensaje de error.


  • La restricción CHECK que se agrega especifica que como mínimo debe existir una fila en la tabla CheckTbl. Sin embargo, puesto que no hay filas en la tabla contra la que se comprueba la condición de esta restricción, la instrucción ALTER TABLE será correcta.


  • Las restricciones CHECK no se validan durante las instrucciones DELETE. Por lo tanto, la ejecución de instrucciones DELETE en las tablas con ciertos tipos de restricciones CHECK puede generar resultados inesperados. Por ejemplo, imaginemos que las siguientes instrucciones se ejecutan en la tabla CheckTbl.






2 comentarios: