2011-11-04 9 views
10

Tengo dos columnas (entre otras) en una tabla de base de datos: ExitDate y ExitReason. Nuestra lógica comercial requiere que se especifique ExitReason si se especifica ExitDate. La columna ExitDate debe permitir nulos ya que el valor no siempre se conoce en el momento de la inserción. ¿Hay alguna manera de hacer que la columna ExitReason permita valores nulos solo si el valor de ExitDate es nulo? Pude lograr el efecto dividiendo estas dos columnas en una tabla separada de 'fechas de salida' y haciendo que ambas no sean nulables, pero estaría bien si no fuera necesario.¿Hay alguna manera de hacer que la nulabilidad de una columna dependa de la capacidad de anulación de otra columna?

Ideas? ¡Gracias!

+0

Tienes ¿Intentó escribir disparador? – mishadoff

Respuesta

12

Suponiendo que está en SQL Server o algo similar, puede hacerlo con un CHECK constraint en su tabla. (Por desgracia, MySQL parses but ignoresCHECK limitaciones, por lo que tendrían que utilizar un disparador para esa plataforma.)

Si la tabla ya existe:

ALTER TABLE ADD CONSTRAINT CK_ExitDateReason 
CHECK (
     (ExitDate IS NULL AND ExitReason IS NULL) 
    OR (ExitDate IS NOT NULL AND ExitReason IS NOT NULL) 
); 

Si va a crear la tabla a sí mismo:

CREATE TABLE dbo.Exit (
    ... 

    , CONSTRAINT CK_ExitDateReason CHECK ... 
); 

uso de una restricción de comprobación es preferible al uso de un disparador porque:

  • restricciones de comprobación son más visibles que desencadena
  • la restricción es parte de la definición de la tabla, a diferencia de código que se ejecuta por separado, por lo que es lógicamente más limpio
  • Estoy dispuesto a apostar que es más rápido que un disparador demasiado
+0

+1, una restricción de verificación es definitivamente el camino a seguir. –

+2

+1 Una buena respuesta para "alguien tan joven" (en términos de reputación de todos modos). Sigan con el buen trabajo :) – Bohemian

+1

@Bohemian - ¡Gracias! Tengo una pequeña experiencia aquí en [teh stacks] (http://dba.stackexchange.com/users/2660/nick?tab=stats). :) –

0

Podría aplicar esto con un desencadenante: si está configurando ExitDate en algo distinto de null y ExitReason se deja nulo o se establece en nulo, se produce un error.

3

Pude lograr el efecto dividiendo estas dos columnas en una tabla de 'fechas de salida' separada y haciendo que ambas no sean nulas, pero sería bueno si no fuera necesario.

Parece una muy buena solución. Y si está utilizando MySQL, probablemente sea la mejor solución ya que las restricciones CHECK no son compatibles.

1

MS Access ofrece otro método para lograr su objetivo. Con la tabla en la Vista de diseño, abra la hoja de propiedades. A diferencia de una regla de validación para un campo , la regla de la tabla puede hacer referencia a otros campos en la tabla.

Agregue esto como una sola línea para la propiedad Regla de validación de la tabla.

([ExitDate] IS NULL AND [ExitReason] IS NULL) 
OR ([ExitDate] IS NOT NULL AND [ExitReason] IS NOT NULL) 

Es similar al CHECK CONSTRAINT @NickChammas suministrado. Pongo corchetes alrededor de ExitDate y ExitReason porque sin los corchetes Access tiende a interpretarlos como valores literales de texto, por lo que agrega citas como esta ...que no funcionará:

("ExitDate" IS NULL AND "ExitReason" IS NULL) 
OR ("ExitDate" IS NOT NULL AND "ExitReason" IS NOT NULL) 

Usted puede encontrar este método más conveniente si desea incluir un mensaje fácil de usar como propiedad Texto de validación de la tabla para mostrar cuando la regla de validación es violada:

"Provide values for both ExitDate and ExitReason, or leave both blank." 

Editar: La sugerencia de @AndriyM trabaja como MS Access tabla de regla de validación:

([ExitDate] Is Null) = ([ExitReason] Is Null) 
1

es posible utilizar ch Ecks con MS Access, pero solo a través de ADO.

sSQL = "ALTER TABLE customer ADD CONSTRAINT CK_ExitDateReason " _ 
& "CHECK ((ExitDate IS NULL) = (ExitReason IS NULL))" 

CurrentProject.Connection.Execute sSQL 

La restricción solo se puede eliminar a través de ADO. Sin embargo, puede agregar y borrar columnas (campos) sin afectar el cheque.

También es posible agregar una marca que haga referencia a otra tabla.

Si está utilizando la tabla con una forma, el error devuelto será 3317. Puede aceptar el mensaje predeterminado o suministrar su propio modo:

Private Sub Form_Error(DataErr As Integer, Response As Integer) 
    If DataErr = 3317 And IsNull(Me.ExitReason) Then 
     MsgBox "Please fill in a reason" 
     Response = acDataErrContinue 
    End If 
End Sub 

Más información: Intermediate Microsoft Jet SQL for Access 2000

Cuestiones relacionadas