2011-07-07 10 views
6

Sé que las restricciones de SQL pueden obligar a los datos a cumplir los criterios de validez. Sin embargo, ¿qué pasa con los criterios tales como "La calificación del alumno solo se puede actualizar cuando la bandera 'finalizada' es falsa"? ¿Los criterios de actualización deben ser manejados por la aplicación?¿Se puede usar una restricción SQL para evitar que se cambie un valor en particular cuando se cumple una condición?

+5

Dependiendo de su RDBMS, podría aplicar esto con un disparador "antes" o "en vez de" en la mesa. –

+0

Justo lo que dijo Joe, aunque las restricciones de verificación también se pueden usar, dependiendo de la base de datos. – Oded

Respuesta

3

Respuesta corta: No, las restricciones de SQL no pueden por sí mismas evitar un cambio a la columna Grade cuando Finalized es 'verdadero' (pero permite un cambio en caso contrario).

Hay several kinds of SQL constraints: CHECK, DEFAULT, NOT NULL, UNIQUE, clave principal y clave externa.

Cada uno de estos puede limitar o afectar los valores de las columnas, ya sea individualmente o en combinación, pero no puede evitar que ACTUALICE los valores permitidos. En particular, ninguna de estas restricciones puede evitar que una ACTUALIZACIÓN a Grado y/o Finalizada se base en los valores previos de Grado y Finalizado.

un disparador de actualización se puede hacer esto: compara los nuevos y viejos valores de grado, y si éstas difieren definitivo y aprobado = 'verdadero', deshacer la actualización con un mensaje de error explicativo.

Sin embargo, la aplicación puede y debe aplicar dicha "regla de negocios" con más elegancia. La regla en sí misma podría usar un poco de aclaración sobre cuándo se puede cambiar el valor Finalizado. P.ej., ¿está permitido cambiar Grade y establecer Finalized = 'false' al mismo tiempo? La lógica del disparador puede manejar tales detalles, y sería razonable instalar eso como una protección contra fallas, al mismo tiempo que hace que las reglas sean explícitas en algún lugar de la aplicación (frontend/middleware/backend) también.

-2

IMO, diría que debe hacerse en la aplicación o en el procedimiento almacenado (posiblemente ambos), en lugar de como una restricción real (entre otras cosas, en su ejemplo específico, una calificación es "finalizada" no no siempre significa que sea realmente final).

Sin embargo, si estuviera implementando esto como una limitación, que haría uso de una restricción CHECK (de nuevo, usando el ejemplo)

CONSTRAINT chk_grade CHECK(grade between 0 AND 100 and finalized = 0) 

Comprobar la sintaxis específica sobre eso, pero es donde me gustaría empezar .

+1

¿Cómo evitaría que las actualizaciones se clasifiquen cuando se establezca el indicador finalizado? ¿No impide que se establezca el indicador finalizado? No creo que eso sea lo que OP tiene en mente. – hardmath

+0

Tendría que verificar dos veces la sintaxis (como mencioné), pero lo que debo/debo hacer es verificar que 'finalizado' = 0 (es decir, es" Falso ") antes de que permita un rango de 0 - 100 para colocarse en 'grado' – AllenG

+0

Esto no funciona (en SQL Server, de todos modos) porque la comprobación falla cuando intenta convertir 'finalizado' en 1. – atheaos

3

Un disparador, una restricción y una columna adicional.

partir de finales:

  1. La columna adicional almacena el valor que se va a 'fijo':

    ALTER TABLE ADD SavedGrade int 
    
  2. La restricción restringe el cambio de la columna de Grade:

    ALTER TABLE Students 
    ADD CONSTRAINT CK_Grade CHECK (Finalised = 'false' OR Grade = SavedGrade) 
    
  3. El gatillo actualiza la co adicional lumna cuando la columna se actualiza Grade (lo siguiente es para SQL Server):

    CREATE TRIGGER StudentsFinaliseGrade 
    ON Students AFTER INSERT, UPDATE 
    AS 
    IF UPDATE(Grade) 
        UPDATE Students 
        SET SavedGrade = i.Grade 
        FROM inserted i 
        WHERE i.ID = Students.ID 
        AND i.Grade <> i.SavedGrade 
    

Por lo tanto, siempre y cuando Finalised = 'false', la columna de la Grade puede ser cambiado. Cuando se cambia , el valor se almacena inmediatamente en la columna SavedGrade. (Estamos actualizando SavedGrade directamente, porque de lo contrario la restricción no nos permitiría establecer Finalised en 'true'). Tan pronto como se configura Finalised, ya no puede cambiar la columna Grade debido a la restricción.

Cuestiones relacionadas