Alter Table add check for nulls and not nulls - sql

I am using Oracle Express, and I'd like to make a statement to add a check constraint to my Invoices table that allows Payment_Date to be NULL if Payment_Total = 0, AND Payment_Date to be NOT NULL if Payment_Total > 0.
I only understand how to alter a table to add a constraint that checks that a column's value. I don't understand how to make constraints that Allow null values or disallow null values if a certain condition (ColumnValue > SomeValue) is met.

Here is how you can express the check constraint:
alter table t add constraint ck_values
check ((payment_date is null and payment_total = 0) or
(payment_date is not null and payment_total > 0)
);

Related

How can I ensure that Column_A can only have a value if Column_B is NULL? And vice versa

I'm attempting to create a table that has three columns:
id
paid_at
failed_at
How can I make sure that paid_at can only have a value if failed_at is NULL?
Here is my current code:
CREATE TABLE charges(
id TEXT NOT NULL PRIMARY KEY,
paid_at TEXT,
failed_at TEXT
);
ALTER TABLE charges
ADD CONSTRAINT paid_at CHECK (failed_at IS NULL);
ALTER TABLE charges
ADD CONSTRAINT failed_at CHECK (paid_at IS NULL);
I also want to make sure that BOTH cannot be null.
How can I do this?
Thanks!
You can use num_nonnulls() in the check constraint:
alter table charges
add constraint only_one_not_null
check (num_nonnulls(paid_at, failed_at) = 1);
That ensure that exactly one of the columns is not null and the other is null.
If you consider a string with only spaces to be "null" as well, you could extend that to:
alter table charges
add constraint only_one_not_null
check (num_nonnulls(nullif(trim(paid_at),''), nullif(trim(failed_at),'')) = 1);
I am inclined to do this with addition. To check that one of a group of columns is not null, count the number of not-null values:
check ( (paid_at is not null)::int + (failed_at is not null)::int) > 0 )
You can use the following predicate:
alter table charges add constraint exclusive_rule check (
paid_at is null and failed_at is not null or
paid_at is not null and failed_at is null
);

check constraint that references multiple columns in the same table

I am attempting to add a constraint to a DB2 database that will check three columns. I am using a table that is an invoice table that includes start date end date quantity item price etc. for each line item on an invoice. I want to prevent allowing start and end date from being null when a column linestatus = RELELASED. Here is the alter statement that I have so far. My question is why won't this work? I have verified that this table does not have any current instances of all three of these checks.
alter table pluspgbtrans
add constraint start_end_notnull
Check (eip_linestatus = 'RELEASED' AND eip_endate is not null AND eip_startdate is not null)
Your SQL statement is valid.
However, your logic has an error: this check does not apply only if eip_linestatus = 'RELEASED'.
As written, your constraint is asserting that all rows must have eip_linestatus = 'RELEASED' AND eip_endate is not null AND eip_startdate is not null.
So, if any rows in your table have eip_linestatus with a value of anything other than RELEASED, you'll get the SQL0544N error when you try to add the constraint.
To create the constraint you're looking for, you need to handle the other state(s) for eip_linestatus. I can't guess what they are, so here's a potential generic option:
alter table pluspgbtrans
add constraint start_end_notnull check (
(eip_linestatus <> 'RELEASED')
OR
(
eip_linestatus = 'RELEASED'
AND eip_endate is not null
AND eip_startdate is not null
)
);

Oracle constraint / unique index: check if the query has no result - then you can insert the line

I did something similar in the past for the purpose of limiting the range of cells:
ALTER TABLE "CES"."NS_CES" ADD CONSTRAINT "CHECK_OVER_DIAPAZON" CHECK (
(ID_NS_WORK != 1835 AND ID_NS_WORK != 1833) OR
(ID_NS_WORK = 1835 and PNS BETWEEN 0 AND 100 and QNS BETWEEN -200 AND 10) OR
(ID_NS_WORK = 1833 and PNS BETWEEN 0 AND 100 and QNS BETWEEN -200 AND 10)
);
But now I've got different task: add constraint, which will check the result of the query does not return any value.
This is my select, which must return no value, and which I want to create as check constraint for the table Training_rule:
select type, training_list_id, element_id, request_code
from training_rule
where after_rule is null and after_group is null
group by type, training_list_id, element_id, request_code
having count(*) > 1;
Something like this:
ALTER TABLE "CES"."TRAINING_RULE" ADD CONSTRAINT "CHEK_SELECT_HAS_NO_RESULT" CHECK (
^HAS NO RESULT^:
[
select type, training_list_id, element_id, request_code
from training_rule
where after_rule is null and after_group is null
group by type, training_list_id, element_id, request_code
having count(*) > 1;
]
)
Thanks
Edit 1
It works, thanks to Gordon Linoff
create unique index idx_trainingrule_4 on TRAINING_RULE (
type, training_list_id, element_id, request_code,
(case when after_rule is null and after_group is null then null
else name
end)
);
I think you can do what you want with a conditional unique index. This assumes that you have a unique id column in the table (trainingrule_id) that is never negative:
create unique index idx_trainingrule_4 on (
type, training_list_id, element_id, request_code,
(case when after_rule is null and after_group is null then -1
else trainingrule_id
end)
);
You cannot do it like that. The ADD CHECK CONSTRAINT:
A check constraint can NOT be defined on a SQL View.
The check constraint defined on a table must refer to only columns in that table. It can not refer to columns in other tables.
A check constraint can NOT include a SQL Subquery.
A check constraint can be defined in either a SQL CREATE TABLE statement or a SQL ALTER TABLE statement.
The reason why it was working previously was because you were applying the constraint on a column value which is syntactically correct. But the latter is not the correct syntax and is not allowed.

SQL check with an if statement

Quick question on SQL how can I make a check such as:
Alter Table Invoices WITH NOCHECK
ADD CHECK
Now this is the part where I want to add a check so that the column PaymentDate can be null if another column Payment Total is equal to 0 and also that PaymentDate is not null if Payment Total is greater than 0.
Here is a way to do it :
Alter Table Invoices WITH NOCHECK
ADD CHECK ( (PaymentTotal > 0 AND PaymentDate IS NOT NULL)
OR (PaymentTotal = 0 ) )

CHECK CONSTRAINT on multiple columns

I use SQL Server 2008
I use a CHECK CONSTRAINT on multiple columns in the same table to try to validate data input.
I receive an error:
Column CHECK constraint for column
'AAAA' references another column,
table 'XXXX'.
CHECK CONSTRAINT does not work in this way.
Any other way to implement this on a single table without using FK?
Thanks
Here an example of my code
CREATE TABLE dbo.Test
(
EffectiveStartDate dateTime2(2) NOT NULL,
EffectiveEndDate dateTime2(2) NOT NULL
CONSTRAINT CK_CmsSponsoredContents_EffectiveEndDate CHECK (EffectiveEndDate > EffectiveStartDate),
);
Yes, define the CHECK CONSTRAINT at the table level
CREATE TABLE foo (
bar int NOT NULL,
fred varchar(50) NOT NULL,
CONSTRAINT CK_foo_stuff CHECK (bar = 1 AND fred ='fish')
)
You are declaring it inline as a column constraint
...
fred varchar(50) NOT NULL CONSTRAINT CK_foo_fred CHECK (...)
...
Edit, easier to post than describe. Fixed your commas.
CREATE TABLE dbo.Test
(
EffectiveStartDate dateTime2(2) NOT NULL,
EffectiveEndDate dateTime2(2) NOT NULL, --need comma
CONSTRAINT CK_CmsSponsoredContents_EffectiveEndDate CHECK (EffectiveEndDate > EffectiveStartDate) --no comma
);
Of course, the question remains are you using a CHECK constraint where it should be an FK constraint...?
Check constraints can refer to a single column or to the whole record.
Use this syntax for record-level constraints:
ALTER TABLE MyTable
ADD CONSTRAINT MyCheck
CHECK (...your check expression...)
You can simply apply your validation in a trigger on the table especially that either way the operation will be rolled back if the check failed.
I found it more useful for CONSTRAINT using case statements.
ALTER TABLE dbo.ProductStock
ADD
CONSTRAINT CHK_Cost_Sales
CHECK ( CASE WHEN (IS_NOT_FOR_SALE=0 and SAL_CPU <= SAL_PRICE) THEN 1
WHEN (IS_NOT_FOR_SALE=1 ) THEN 1 ELSE 0 END =1 )