CHECK constraint failed - sql

I'm using sqlite3
I have created a table of a class like this
CREATE TABLE Class (
ClassID char(5) PRIMARY KEY CHECK (ClassID LIKE 'CT[1-9][A-Z]' OR 'AT[1-9][1-9][A-Z]'),
ClassQuantity int NOT NULL CHECK (ClassQuantity > 0)
);
And when I insert some values to this table
INSERT INTO Class
VALUES ('CT2D', 50);
It shows me an error message
'CHECK constraint failed'.
I have written the values based on the condition in the check. Can someone help me with this problem.

You miss to write the OR condition there OR ClassID LIKE 'AT[1-9][1-9][A-Z]'
CREATE TABLE Class (
ClassID char(5) PRIMARY KEY
CHECK (ClassID LIKE 'CT[1-9][A-Z]' OR ClassID LIKE 'AT[1-9][1-9][A-Z]'),
ClassQuantity int NOT NULL CHECK (ClassQuantity > 0)
);
INSERT INTO Class
VALUES ('CT2D', 50);

The LIKE expression in your check constraint is trying to use the extended syntax supported by databases like SQL Server and Sybase. However, I don't think this syntax is supported by SQLite. As a workaround, if your version of SQLite has REGEXP, we can use that instead:
CREATE TABLE Class (
ClassID char(5) PRIMARY KEY CHECK (ClassID REGEXP 'CT[1-9][A-Z]|AT[1-9][1-9][A-Z]'),
ClassQuantity int NOT NULL CHECK (ClassQuantity > 0)
);

use GLOB(). as mentioned here
CREATE TABLE Class (
ClassID char(5) PRIMARY KEY
CHECK (ClassID GLOB 'CT[1-9][A-Z]' OR ClassID GLOB 'AT[1-9][1-9][A-Z]'),
ClassQuantity int NOT NULL CHECK (ClassQuantity > 0)
);
INSERT INTO Class
VALUES ('CT2D', 50);
sqlite dbfiddle

Related

Why does the zipcode fail the check constraint?

I feel like I am probably missing something really simple, but I really can't figure out what I'm doing wrong. I'm trying to use a check constraint to make sure zipcodes are 5 digit numbers, but the check restraint keeps failing. Here is the table creating with the constraint:
Create Table Students (
StudentID Int Primary Key Identity(1,1)
StudentNumber nVarchar(100) Unique Not Null,
...
StudentZipCode nChar(10) Not Null
)
Go
Alter Table Students Add Constraint chZipCode
CHECK (StudentZipCode LIKE '[0-9][0-9][0-9][0-9][0-9]' OR StudentZipCode
Like '[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]')
Go
Codes like 12345-6789 work, but when I try to insert the values like '12345' or '01234' it gives me this error:
The INSERT statement conflicted with the CHECK constraint "chZipCode". The conflict occurred in database ..., table "dbo.Students", column 'StudentZipCode'.
It fails because you defined the zip code as a char() instead of a varchar(). Hence, it has a bunch of spaces padding it out.
So, define it as:
Create Table Students (
StudentID Int Primary Key Identity(1,1),
StudentNumber nVarchar(100) Unique Not Null,
StudentZipCode nVarChar(10) Not Null,
CHECK (StudentZipCode LIKE '[0-9][0-9][0-9][0-9][0-9]' OR
StudentZipCode LIKE '[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]')
);
Then '12345' works, because it matches the first of the LIKE patterns.
'012344' does not work, because no pattern has six digits in a row.
Here is a SQL Fiddle.

Use a condition while creating a table in SQL

I'd like to create a table with a condition
create table TOTO
(
Id int not null,
zip as (if(zip > '00999' and zip < '96000') then zip) ,
PRIMARY KEY (Id)
);
All I get is an error message.
Do you know how to do that with the "zip" in type char ?
Thank you for your help !
You may want to use CHECK constraint instead
CREATE TABLE TOTO
(
Id int NOT NULL,
zip char,
PRIMARY KEY (Id),
CHECK (zip > '00999' AND zip < '96000')
);
You can get this done either using a CHECK CONSTRAINT or using a BEFORE INSERT or INSTEAD OF trigger
An example:
CREATE TRIGGER ChkZip
ON TOTO
INSTEAD OF INSERT
AS
BEGIN
IF (inserted.zip > '00999' and inserted.zip < '96000')
BEGIN
INSERT INTO TOTO (id,zip) VALUES (insered.id, inserted.zip)
END
ELSE
BEGIN
RAISERROR ('The entered zip code doesn't match criteria.' ,10,1)
ROLLBACK TRANSACTION
END
END
CREATE TABLE TOTO
(
Id INT NOT NULL,
zip VARCHAR2(10),
PRIMARY KEY (Id),
CONSTRAINT CHK_zip CHECK (zip > to_number('00999') AND zip < to_number('96000'))
);
You could use check constraint - the above script is based on Oracle Sql function
You need to create a new CHECK constraint so that your field is guaranteed to comply with this constraint each time it is set or modified (insert or update).
Here is an example adapted to SQL server (as you seem to be using that dbms) where the constraint is named so you can identify it more easily (better for maintainability)
create table TOTO
(
Id int not null,
zip char ,
PRIMARY KEY (Id),
CONSTRAINT CHK_zip CHECK(zip > '00999' and zip < '96000')
);
Note that you could formulate it using patterns as in the link I provided.

MSSQL function in check constraint

I would like to create table with CHECK constraint, where CHECK calls an user defined scalar function. I have read on multiple sites that it is possible, also that it has bad performance. Even though I would like to do it.
I have this table
CREATE TABLE [book_history] (
id int NOT NULL IDENTITY PRIMARY KEY,
user_id int NOT NULL,
library_id int NOT NULL,
book_id int NOT NULL,
borrow_time datetime DEFAULT GETDATE(),
return_policy datetime DEFAULT DATEADD(DAY, 30, GETDATE()),
return_time datetime,
CHECK (dbo.fn_check_duplicate(user_id, library_id, book_id) = 0)
);
and function
DROP FUNCTION IF EXISTS fn_check_duplicate
GO
CREATE FUNCTION fn_check_duplicate (#user_id int, #library_id int, #book_id int)
RETURNS int
BEGIN
RETURN (SELECT COUNT(*) FROM [book_history] WHERE user_id = #user_id AND library_id = #library_id AND book_id = #book_id AND return_time IS NULL)
END
GO
When I try to insert new row into this book_history table (which is empty), I get an error saying The INSERT statement conflicted with the CHECK constraint "CK__book_history__267ABA7A". The conflict occurred in database "library", table "dbo.book_history".
COUNT is supposed to return int data type based on MSDN documentation.
I am owner of both, the table and the function.
Can anyone tell me what am I doing wrong?
Change it to check (dbo.fn_check_duplicate(user_id, library_id, book_id) = 1)
The check is going to look at the state of the table after the insert, so you want the count to be 1.
Test it on rextester: http://rextester.com/AWDNP40594 by uncommenting the second insert.
You can also replace this slow check constraint with a filtered unique index like so:
create unique nonclustered index uix_book_history_user_library_book
on dbo.book_history (user_id, library_id, book_id)
where return_time is null
This might be more of what you are trying to do, if each book_id is an individual book:
create unique nonclustered index uix_book_history_library_book
on dbo.book_history (library_id, book_id)
where return_time is null
Because this would allow a book to only be checked out by one user at a time.

Create table with attribute which must be in range of 1-10 (Postgres)

How can i constrain an attribute in a table to only allow the value to be between 1-10?
This is the statement so far.. Have no idea how to make the OfficeNumber only accept values in that interval
CREATE TABLE OfficeStaff(
EID INT PRIMARY KEY,
OfficeNumber INT NOT NULL
);
Use a check constraint:
CREATE TABLE OfficeStaff (
EID INT PRIMARY KEY,
OfficeNumber INT NOT NULL,
CHECK (OfficeNumber BETWEEN 1 AND 10)
);
Note, though, that there is another, perhaps better approach. You should have an OfficeNumbers table with the valid office numbers. Then you can use a foreign key relationship to enforce the numbering, without having to hard-code the numbers.
You can use domains for this purpose:
create domain mydomain as integer check(value between 1 and 10)
create table mytable(id serial primary key, md mydomain not null)
-- this two will succeed
insert into mytable(md) values(1)
insert into mytable(md) values(2)
-- that one will fail
insert into mytable(md) values(12)
ERROR: value for domain mydomain violates check constraint "mydomain_check"
********** Error **********
ERROR: value for domain mydomain violates check constraint "mydomain_check"
More information can be found here: http://www.postgresql.org/docs/9.1/static/sql-createdomain.html
You can add constraints for the definition. In this case you can add
CHECK (OfficeNumber BETWEEN 1 AND 10)

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 )