CHECK CONSTRAINT on multiple columns - sql

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 )

Related

SQL - How do you use a user defined function to constrain a value between 2 tables

First here's the relevant code:
create table customer(
customer_mail_address varchar(255) not null,
subscription_start date not null,
subscription_end date, check (subscription_end !< subcription start)
constraint pk_customer primary key (customer_mail_address)
)
create table watchhistory(
customer_mail_address varchar(255) not null,
watch_date date not null,
constraint pk_watchhistory primary key (movie_id, customer_mail_address, watch_date)
)
alter table watchhistory
add constraint fk_watchhistory_ref_customer foreign key (customer_mail_address)
references customer (customer_mail_address)
on update cascade
on delete no action
go
So i want to use a UDF to constrain the watch_date in watchhistory between the subscription_start and subscription_end in customer. I can't seem to figure it out.
Check constraints can't validate data against other tables, the docs say (emphasis mine):
[ CONSTRAINT constraint_name ]
{
...
CHECK [ NOT FOR REPLICATION ] ( logical_expression )
}
logical_expression
Is a logical expression used in a CHECK constraint and returns TRUE or
FALSE. logical_expression used with CHECK constraints cannot
reference another table but can reference other columns in the same
table for the same row. The expression cannot reference an alias data
type.
That being said, you can create a scalar function that validates your date, and use the scalar function on the check condition instead:
CREATE FUNCTION dbo.ufnValidateWatchDate (
#WatchDate DATE,
#CustomerMailAddress VARCHAR(255))
RETURNS BIT
AS
BEGIN
IF EXISTS (
SELECT
'supplied watch date is between subscription start and end'
FROM
customer AS C
WHERE
C.customer_mail_address = #CustomerMailAddress AND
#WatchDate BETWEEN C.subscription_start AND C.subscription_end)
BEGIN
RETURN 1
END
RETURN 0
END
Now add your check constraint so it validates that the result of the function is 1:
ALTER TABLE watchhistory
ADD CONSTRAINT CHK_watchhistory_ValidWatchDate
CHECK (dbo.ufnValidateWatchDate(watch_date, customer_mail_address) = 1)
This is not a direct link to the other table, but a workaround you can do to validate the date. Keep in mind that if you update the customer dates after the watchdate insert, dates will be inconsistent. The only way to ensure full consistency in this case would be with a few triggers.

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
);

Multiple constraints on a single column

I want to ensure that only the values 'Expert', 'Average' or 'Adequate' are entered into the levelOfExpertise column of this table, however whenever I do try an enter one of those values, it returns an error saying the value entered is too short. Here is the create table query for this particular table. The the column I am referring to is levelOfExpertise:
CREATE TABLE MusicianInstrument
(
musicianNo varchar(5) not null
CONSTRAINT MI_PK1 REFERENCES Musician(musicianNo),
instrumentName varchar(50) not null
CONSTRAINT MI_PK2 REFERENCES Instrument(instrumentName),
levelOfExpertise varchar(50),
CONSTRAINT levelOfExpertise CHECK (levelOfExpertise = 'Expert', 'Adequate', 'Avergage'),
PRIMARY KEY(musicianNo,instrumentName)
);
Any ideas how I can ensure only those three values (Expert, Adequate or Average) can be entered?
Thanks
Use the IN operator
CHECK (levelOfExpertise IN ('Expert','Adequate','Avergage'))
Try to change your CHECK constraint as following:
CONSTRAINT levelOfExpertise CHECK (levelOfExpertise IN ('Expert','Adequate','Avergage'))
I suppose that you use sql server as RDBMS.

SQL Server Create Table With Column Unique Not Null and Not Empty(Check)

How to create a table with a column which is unique, not null and not empty(Check)?
I tried below Query
CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
LastName nvarchar(255) NOT NULL,
FirstName nvarchar(255),
Address nvarchar(255),
City nvarchar(255),
CHECK (P_Id>0)
)
When i try to create a table with both UNIQUE and CHECK constraint its throwing following error. Is it possible to use two constraint in a single query?
Major Error 0x80040E14, Minor Error 25501
> CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
LastName nvarchar(255) NOT NULL,
FirstName nvarchar(255),
Address nvarchar(255),
City nvarchar(255),
CHECK (P_Id>0)
)
There was an error parsing the query. [ Token line number = 8,Token line offset = 1,Token in error = CHECK ]. I am using SQL Server 2008.
CREATE TABLE tab
(
id INT,
notnullandnotemptystr VARCHAR(10) NOT NULL UNIQUE CHECK (DATALENGTH(notnullandnotemptystr) > 0)
)
It should be some thing like this.
CREATE TABLE [dbo].[TABLE1](
[COL1] [nvarchar](50) NOT NULL UNIQUE
)
ALTER TABLE [dbo].[TABLE1] WITH CHECK
ADD CONSTRAINT [CK_TABLE1] CHECK (([COL1]<>N''))
for this problem you can use Constraint in sql server
ALTER TABLE TBL WITH CHECK ADD CONSTRAINT [CK_TBL] CHECK
(([dbo].[TBLCheckCustomeUnique](ID)=(1)))
TBLCheckCustomeUnique is a user define function that check this conditions
You can controll the uniqueness of a column or column set by the UNIQUE constraint.
The data stored in the column or column set could be checked/controlled (and forced with various rules) by the CHECK constraint.
The CHECK constraint to achieve your goal is the following:
ALTER TABLE [YourTable]
ADD CONSTRAINT CK_CheckConstraintName
CHECK (LEN([YourColumn]) >= {MinimumColumnWidth})
You can add the constraints in the CREATE TABLE statement or if the table already exists you can add it with the ALTER TABLE .. ADD CONSTRAINT statement.

In SQL Server 2005, how do I set a column of integers to ensure values are greater than 0?

This is probably a simple answer but I can't find it. I have a table with a column of integers and I want to ensure that when a row is inserted that the value in this column is greater than zero. I could do this on the code side but thought it would be best to enforce it on the table.
Thanks!
I was in error with my last comment all is good now.
You can use a check constraint on the column. IIRC the syntax for this looks like:
create table foo (
[...]
,Foobar int not null check (Foobar > 0)
[...]
)
As the poster below says (thanks Constantin), you should create the check constraint outside the table definition and give it a meaningful name so it is obvious which column it applies to.
alter table foo
add constraint Foobar_NonNegative
check (Foobar > 0)
You can get out the text of check constraints from the system data dictionary in sys.check_constraints:
select name
,description
from sys.check_constraints
where name = 'Foobar_NonNegative'
Create a database constraint:
ALTER TABLE Table1 ADD CONSTRAINT Constraint1 CHECK (YourCol > 0)
You can have pretty sophisticated constraints, too, involving multiple columns. For example:
ALTER TABLE Table1 ADD CONSTRAINT Constraint2 CHECK (StartDate<EndDate OR EndDate IS NULL)
I believe you want to add a CONSTRAINT to the table field:
ALTER TABLE tableName WITH NOCHECK
ADD CONSTRAINT constraintName CHECK (columnName > 0)
That optional NOCHECK is used to keep the constraint from being applied to existing rows of data (which could contain invalid data) & to allow the constraint to be added.
Add a CHECK constraint when creating your table
CREATE TABLE Test(
[ID] [int] NOT NULL,
[MyCol] [int] NOT NULL CHECK (MyCol > 1)
)
you can alter your table and add new constraint like bellow.
BEGIN TRANSACTION
GO
ALTER TABLE dbo.table1 ADD CONSTRAINT
CK_table1_field1 CHECK (field1>0)
GO
ALTER TABLE dbo.table1 SET (LOCK_ESCALATION = TABLE)
GO
COMMIT