ejemplos - sql select condicional
Sql Condicional No Nulo Restricción (4)
Tengo curiosidad por saber si es posible crear una restricción condicional no nula en sql? En otras palabras, ¿es posible crear una restricción tal que una columna B pueda ser nula mientras la columna A contenga, digamos ''NUEVO'' pero si el contenido de la columna A cambia a otra cosa, entonces la columna B ya no puede ser nula?
Y para ampliar eso, entonces es posible hacerlo de modo que la columna B deba estar nula o vacía siempre que la columna A diga "NUEVO".
Gracias a todos: D
Creo que su primer requisito declarado es:
IF ( B IS NULL ) THEN ( A = ''NEW'' )
Aplicar la regla de reescritura de implicación:
IF ( X ) THEN ( Y ) <=> ( NOT ( X ) OR ( Y ) )
En tu caso;
( NOT ( B IS NULL ) OR ( A = ''NEW'' ) )
Reescritura menor para aprovechar la sintaxis de SQL:
( B IS NOT NULL OR A = ''NEW'' )
Su segundo requisito establecido ("extender"):
IF ( A = ''NEW'' ) THEN ( B IS NULL )
Aplicar regla de reescritura:
( NOT ( A = ''NEW'' ) OR ( B IS NULL ) )
Reescritura menor:
( A <> ''NEW'' OR B IS NULL )
De vez en cuando , esta respuesta es criminalmente errónea y es una abominación. Puede utilizar una restricción CHECK . http://msdn.microsoft.com/en-us/library/ms188258.aspx
No hay una manera de hacer restricciones condicionales. Sin embargo, deberías poder hacer el trabajo usando un disparador. Para eso están.
http://msdn.microsoft.com/en-us/library/ms189799.aspx
CREATE TRIGGER MyTable.ConditionalNullConstraint ON MyTable.ColumnB
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM inserted
WHERE A <> ''NEW'' AND B IS NULL
)
BEGIN
RAISERROR (''if A is ''''NEW'''' then B cannot be NULL'', 16, 1);
ROLLBACK TRANSACTION;
END;
GO
Tenga en cuenta que en la consulta querrá hacer referencia al insertado, que es un objeto especial que se comporta como una tabla, y le permite hacer referencia a las filas que causaron el disparo.
Por supuesto, en este ejemplo necesitaría manejar DESPUÉS DE ACTUALIZAR también para hacer cumplir la restricción, pero esa es la idea general.
Edición: como se mencionó en las otras respuestas, un CHECK es el mejor método, no el desencadenante que sugerí originalmente. El texto original sigue:
Como sugiere dbaseman, los desencadenantes son el camino a seguir (no es así). Intenta algo como esto (no probado):
CREATE OR REPLACE TRIGGER test
BEFORE UPDATE ON table1
FOR EACH ROW
WHEN (new.A = ''NEW'' and new.B IS NOT NULL)
RAISE_APPLICATION_ERROR (
num=> -20001,
msg=> ''B must be NULL for new rows (A = NEW)''
);
Esto está perfectamente bien para CONSTRAINT CHECK. Solo haz esto:
Requisito:
¿es posible crear una restricción tal que una columna B pueda ser nula mientras la columna A larga contenga digamos ''NUEVO'' pero si el contenido de la columna A cambia a otra cosa, entonces la columna B ya no puede ser nula?
Note la frase: la columna B puede ser nula
Solución:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A = ''NEW'' -- B can be null or not null: no need to add AND here
OR (A <> ''NEW'' AND B IS NOT NULL)
)
);
Puedes simplificarlo aún más:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A = ''NEW''
OR B IS NOT NULL
)
);
Requisito mutuamente incompatible con el requisito anterior:
Y para ampliar eso, entonces es posible hacerlo de modo que la columna B deba estar nula o vacía siempre que la columna A diga "NUEVO".
Note la frase: la columna B debe ser nula
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
(A = ''NEW'' AND B IS NULL)
OR A <> ''NEW''
)
);
Sin embargo, podría simplificarse con esto, pero podría no ser tan fácil de leer como antes:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A <> ''NEW''
OR B IS NULL
)
);