2010-10-07 22 views
21

Digamos que tengo una tabla llamada ProjectTimeSpan (que no he, al igual que el ejemplo!) Que contiene las columnas StartDate y EndDate.¿Puede una restricción Check relacionarse con otra tabla?

y que tengo otra tabla llamada SubProjectTimeSpan, que también contiene columnas llamadas StartDate y EndDate, donde me gustaría establecer una restricción de comprobación que hace que sea imposible establecer StartDate y EndDate a los valores " fuera" de la ProjectTimeSpan.StartDate a ProjectTimeSpan.EndDate

Tipo de una restricción de comprobación que sabe acerca otro tablas valores ...

¿Esto es posible?

Respuesta

14

Puede crear un user-defined function que haga la comprobación y devuelva 1 o 0, luego cree una restricción check, proporcionando la identificación del proyecto y las fechas como parámetros.

+1

¿Y cómo sería esa restricción de verificación? –

+0

@Jack 'check (dbo.IsValidRange (project_id, start_date, end_date) = 1)' – GSerg

+0

Muy bueno de hecho. ¡Gracias! –

34

En respuesta a sus comentarios sobre la respuesta de GSerg, aquí hay una restricción ejemplo, controlar el uso de una función:

alter table YourTable 
add constraint chk_CheckFunction 
check (dbo.CheckFunction() = 1) 

Donde se puede definir la función como:

create function dbo.CheckFunction() 
returns int 
as begin 
    return (select 1) 
end 

La función se permite a la referencia otras tablas

+0

y si yo en la función quiere para relacionarse con una tabla existente como "ProjectTimeSpan.StartDate", lo pondría como ...? –

+0

@Jack Johnstone: ¿Solo cambia la parte 'select 1'? Puede pasar parámetros a la función – Andomar

+0

Ok, ya veo, ¡gracias! –

4

hacer una llave compuesto de clave de la tabla ProjectTimeSpan combinado con los StartDate y EndDate columnas, a continuación, utilizar esta clave compuesta para su referencia clave externa de la tabla SubProjectTimeSpan. Esto le dará la capacidad de escribir las restricciones de nivel de fila necesarias CHECK en la tabla SubProjectTimeSpan, p.

CREATE TABLE ProjectTimeSpan 
(
project_ID INTEGER NOT NULL UNIQUE, -- key 
StartDate DATE NOT NULL, 
EndDate DATE NOT NULL, 
CHECK (StartDate < EndDate), 
UNIQUE (project_ID, StartDate, EndDate) -- compound key 
-- other project columns here... 
); 

CREATE TABLE SubProjectTimeSpan 
(
project_ID INTEGER NOT NULL, 
StartDate DATE NOT NULL, 
EndDate DATE NOT NULL, 
FOREIGN KEY (project_ID, StartDate, EndDate) 
    REFERENCES ProjectTimeSpan (project_ID, StartDate, EndDate) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
sub_StartDate DATE NOT NULL, 
sub_EndDate DATE NOT NULL, 
CHECK (sub_StartDate < sub_EndDate), 
CHECK (StartDate <= sub_StartDate), -- sub project can't start before main project 
CHECK (sub_EndDate <= EndDate)  -- sub project can't end after main project 
-- other sub project columns here... 
); 
+0

Sí, esto parece muy sencillo. Creo que en realidad estaba buscando algo como "REFERENCIAS". Verificará esto. ¡Gracias! –

+3

Esto solo tiene sentido si quiere permitir cambiar las fechas del proyecto principal ... lo cual no tiene sentido. Considere: un proyecto principal, que toma 1 mes para completar. Debido a la crisis financiera (sic), tuvo que retrasarlo (tanto 'startdate' como' enddate' deben obtener +1 mes). Pero no puede hacerlo, porque entonces la comprobación de un proyecto hijo fallará (las fechas hijo ahora están fuera de las fechas principales). Y no puede cambiar las fechas del proyecto hijo antes de cambiar las fechas de sus padres. Punto muerto. – GSerg

+0

este compuesto permitirá diferentes –

0

es necesario agregar restricción sobre el padre y la mesa de los niños porque el subproyecto no puede estar fuera del rango de proyecto, pero la gama de proyectos no puede moverse fuera de todo el subproyecto también.

En este tipo de situaciones, debe aplazar la comprobación de la restricción en un nivel superior (servicio web, aplicación) con una transacción para garantizar que sus datos estén en un estado válido después de consultas múltiples en ambas tablas.

Cuestiones relacionadas