I will try to present the situation as a minimal example:
Say we have a table of tickets, defined as follows:
CREATE TABLE ticket_id_list (
ticket_id NUMBER,
issued_to VARCHAR2(100),
CONSTRAINT ticket_id_list_pk PRIMARY KEY (ticket_id)
);
The system is used for some time and data is added to the table:
INSERT INTO ticket_id_list (ticket_id, issued_to)
VALUES (1, 'Arthur');
INSERT INTO ticket_id_list (ticket_id, issued_to)
VALUES (2, 'Ford');
Later, following requirement pops up:
We need to store a reference number to some other thing in the ticket table this point onwards. The reference needs to be non null. But old records must have
NULL
values.
(Stupid as though this sound, this is a real requirement.)
Now if we do this:
ALTER TABLE ticket_id_list
ADD ref_no VARCHAR2(6) NOT NULL;
the constraint will be violated immediately and we will get: ORA-01758: table must be empty to add mandatory (NOT NULL) column
.
We can of course add a check in the business logic, but that is cumbersome. And because of unexplainable reasons, we cannot use a default value. Is there a way to add a NOT NULL contraint that is only applicable to new records?
It is possible to add a NOT NULL constraint to an existing table by using the ALTER TABLE statement. In this case, the column_name must not contain any NULL value before applying the NOT NULL constraint.
1. "I want to have a not null constraint on all 3 name columns" - simply run "alter table employee modify (<column name> not null)" for each column. 2. Instead of using "NVL(FIRST_NAME,NVL(MIDDLE_NAME,LAST_NAME))", you could just do "COALESCE(FIRST_NAME,MIDDLE_NAME,LAST_NAME)".
By default, a column can hold NULL values. The NOT NULL constraint enforces a column to NOT accept NULL values. This enforces a field to always contain a value, which means that you cannot insert a new record, or update a record without adding a value to this field.
You could add a check constraint where values after a certain date cannot be null; something like:
alter table ticket_id_list
add constraint nul_ref
check (ticket_id < 123456 or ref is not null);
This does presume that ticket_id's only go up over time, if you happen to have a date field in your table it maybe clearer to use that.
I found a neat trick: NOVALIDATE
.
Add a nullable column:
ALTER TABLE ticket_id_list
ADD ref_no VARCHAR2(6);
And then add a table contraint, but make sure to specify NOVALIDATE
:
ALTER TABLE ticket_id_list
ADD CONSTRAINT new_ref_nonull CHECK(ref_no IS NOT NULL) NOVALIDATE;
Now let's check it:
INSERT INTO ticket_id_list (ticket_id, issued_to, ref_no)
VALUES (3, 'Zaphod', '2A4252');
1 row inserted
INSERT INTO ticket_id_list (ticket_id, issued_to, ref_no)
VALUES (4, 'Marvin', NULL);
ORA-02290: check constraint (NEW_REF_NONULL) violated
Just as expected.
Edit: NOVALIDATE
will work only if you need not to update the old rows. If you updated the old rows the constraint will fail. For this instance though, this is not an issue.
You will have to consider this requirement as a business logic since in you case it is.
Then implement this business logic in a trigger.
CREATE TRIGGER t_ticket_id_list
BEFORE INSERT ON ticket_id_list
FOR EACH ROW
BEGIN
IF (:NEW is null) THEN
RAISE_APPLICATION_ERROR(-20001, 'Cannot Insert 1 in this table');
END IF;
END;
Note - Same can be done for SQL Server as well MSDN Create trigger documentations
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With