Sono curioso di sapere che è possibile creare un vincolo condizionale non nullo in sql? In altre parole è possibile creare un vincolo in modo tale che una colonna B possa essere nullo poiché la colonna lunga A contiene diciamo "NEW" ma se il contenuto della colonna A cambia in qualcos'altro, la colonna B non può più essere null?
E per estenderlo, è quindi possibile farlo in modo che la colonna B debba essere nullo o vuota fintanto che la colonna A dice "NUOVO"?
ringrazia tutti: D
Sql Conditional Not Null Constraint
risposta
Questo è perfettamente bene per CONSTRAINT CHECK. Basta fare questo:
Requisito:
E 'possibile creare un vincolo tale che una colonna B può essere nullo finché colonna A contiene consente di dire 'NOVITA', ma se il contenuto della colonna A cambia in qualcos'altro, quindi la colonna B non può più essere null?
Nota la frase: colonna B può essere nullo
Soluzione:
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)
)
);
è possibile semplificare ulteriormente:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A = 'NEW'
OR B IS NOT NULL
)
);
requisito reciprocamente incompatibili al requisito di cui sopra:
E di estendere su questo, è quindi possibile per fare in modo che la colonna B deve essere nullo o vuoto finché la colonna A dice 'NUOVO'?
Nota la frase: colonna B must essere nullo
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
(A = 'NEW' AND B IS NULL)
OR A <> 'NEW'
)
);
potrebbe essere semplificato con questo, più semplice, ma potrebbe non essere così leggibile come sopra però:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A <> 'NEW'
OR B IS NULL
)
);
Credo che l'unico dbms SQL moderno su cui * * non funziona sia MySQL. MySQL non impone vincoli CHECK(). (La domanda è contrassegnata come "SQL", quindi un commento sembrava pertinente). –
Ho appena supposto che stia usando Sql Server, ho controllato alcune delle sue domande. La maggior parte delle domande del database non sono contrassegnate in modo specifico e devono essere. Se possibile, voglio che stackoverflow non accetti il tag sql, quindi tutti potrebbero essere più specifici su quale RDBMS stanno usando –
Questo controllo dei vincoli sta già funzionando su Sql Server dal primo giorno, anche su Postgresql. Ho provato DDL su SQL Server e Postgresql, entrambi lo accettano –
Per onedaywhen, questa risposta è criminalmente sbagliato, e un abominio. È possibile utilizzare un vincolo CHECK. http://msdn.microsoft.com/en-us/library/ms188258.aspx
Non c'è un modo per creare vincoli condizionali. Dovresti, comunque, essere in grado di fare il lavoro usando un trigger. Ecco a cosa servono.
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
Si noti che nella query si vorrà fare riferimento inserito che è un oggetto speciale che si comporta come un tavolo, e consente di fare riferimento la riga (s) che ha causato il grilletto .
Naturalmente, in questo esempio è necessario gestire AFTER UPDATE anche per applicare il vincolo, ma questa è l'idea generale.
"Non c'è un modo per creare vincoli condizionali" Huh? Questo può essere gestito da un vincolo di tupla ('CHECK') e in questo caso dovrebbe essere preferito a un trigger. – onedaywhen
@onedaywhen wow, mi sento molto corretto, grazie. Verifica vincolo: http://msdn.microsoft.com/en-us/library/ms188258.aspx – McGarnagle
Modifica: come indicato nelle altre risposte, un CHECK è il metodo migliore, non il trigger che ho suggerito in origine. Testo originale segue:
Come suggerisce dbaseman, trigger sono la strada da percorrere (non così). Prova qualcosa del genere (non testata):
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)'
);
Per chiarezza, questa soluzione è per Oracle. dbaseman fornisce una soluzione per quello che presumo è MSSQL :) – dwurf
Oracle supporta i vincoli di tupla ('CHECK'): i vincoli dichiarativi devono essere scelti sopra il codice procedurale (inclusi i trigger). – onedaywhen
penso il tuo primo requisito dichiarato è:
IF (B IS NULL) THEN (A = 'NEW')
applicare la regola implicazione riscrittura:
IF (X) THEN (Y) <=> (NOT (X) OR (Y))
Nel tuo caso;
(NOT (B IS NULL) OR (A = 'NEW'))
riscrittura minore per approfittare della sintassi SQL:
(B IS NOT NULL OR A = 'NEW')
La tua seconda dichiarato ("estendere") requisito:
IF (A = 'NEW') THEN (B IS NULL)
Applica regola di riscrittura:
(NOT (A = 'NEW') OR (B IS NULL))
riscrittura Minore:
(A <> 'NEW' OR B IS NULL)
FWIW, non credo che la maggior parte dei progettisti di database chiamerebbe questo un vincolo condizionale. * Probabilmente * chiamerei semplicemente un vincolo, ma se dovessi qualificarlo di più, potrei chiamarlo un vincolo a più colonne o un vincolo CHECK() a più colonne. È standard SQL. –
@Catcall: Chris Data citazione: "tali vincoli vengono talvolta definiti, in modo informale, come vincoli di tupla o vincoli di riga in SQL, sebbene quest'ultimo termine sia utilizzato anche in SQL per indicare, in particolare, un vincolo di riga che non può essere formulati come un vincolo di colonna ... Tutti questi usi sono deprecati, tuttavia, poiché i vincoli limitano gli aggiornamenti e ... non esiste un aggiornamento di tuple o di riga nel mondo relazionale. " – onedaywhen
@onedaywhen: Non ho l'edizione corrente. Nella settima edizione, quello che vedo qui (a parte NULL) assomiglia a quello che definisce un vincolo relvar (p253).Ospita più colonne, e dice che può essere arbitrariamente complesso (nel senso, suppongo, che potrebbe riferirsi ad altre relazioni, viste, aggregati e fasi della luna). –