Case-Insensitive Check Constraint - sql

Created the following table:
CREATE TABLE VEHICLES
(vehicleVIN VARCHAR(30) PRIMARY KEY,
vehicleType VARCHAR(30) NOT NULL CHECK (vehicleType IN ('compact', 'midsize', 'fullsize', 'suv', 'truck')),
vehicleWhereFrom VARCHAR(30) NOT NULL CHECK (vehicleWhereFrom IN ('maryland','virginia','washington, d.c.'));
When running the insert commands, entries that have capital letters (ex: Compact, COMPACT, Maryland, VIRGINIA, etc.) violate the check constraint (error ORA-02290). How do I make the check constraint case-insensitive? Desired results would be that data inserted is accepted, regardless of case used, as long as the word is spelled correctly. Using Oracle database via NOVA. Thanks!

Use lower to check the lower case version of the column.
CHECK vehicleType VARCHAR(30) NOT NULL CHECK (lower(vehicleType) IN ('compact', 'midsize', 'fullsize', 'suv', 'truck')),
CHECK vehicleWhereFrom VARCHAR(30) NOT NULL CHECK (lower(vehicleWhereFrom) IN ('maryland','virginia','washington, d.c.'));

You may use
CHECK (REGEXP_LIKE(vehicleType,'compact|midsize|fullsize|suv|truck','i'))

Related

CHECK with ^[A-Z]{3}[0-9]{6}$ - SQL Server

CREATE TABLE PARTICIPANTE(
pasaporte NVARCHAR(9) NOT NULL,
nombre NVARCHAR(50) NOT NULL,
sexo CHAR(1) NOT NULL,
fecNac DATE NOT NULL,
codPais NVARCHAR(3) NOT NULL,
CONSTRAINT PK_PARTICIPANTE PRIMARY KEY (pasaporte),
CONSTRAINT FK_PAIS_PARTICIPANTE FOREIGN KEY (codPais) REFERENCES PAIS(codigo),
CONSTRAINT CHK_PASAPORTE CHECK (pasaporte like '^\[A-Z\]{3}\[0-9\]{6}$')
)
The CONSTRAINT CHK_PASAPORTE doesn't work when I try to insert the data.
The INSERT statement conflicted with the CHECK constraint "CHK_PASAPORTE". The conflict occurred in database "OMA", table "dbo.PARTICIPANTE", column 'pasaporte'.
Example
insert into PARTICIPANTE (pasaporte,nombre,sexo,fecNac,codPais) value ('JPN865653','Noguchi','F','20000104','JPN');
Can someone explain to me why this doesn't work and how can I fix it?
As I mention in the comments, SQL Server has no (in built) support for Regex, it only has basic pattern matching, which is explained in the documentation.
Fortunately, the logic you are after appears to be quite simple; 3 letters followed by 6 digits. This can be achieved with the following constraint:
ALTER TABLE dbo.PARTICIPANTE ADD CONSTRAINT CHK_PASAPORTE CHECK (pasaporte LIKE '[A-Z][A-Z][A-Z][0-9][0-9][0-9][0-9][0-9][0-9]');
Note that if you require the value to only contain uppercase values, you'll need to COLLATE the value to a collation that is case sensitive and orders upper case letters first, then lowercase, and finally alphabetically (Binary collations are one such one that does this).

How do I create a IF statement creating a table in Postgres?

I'm creating a table and I need a check constraint to validate the posibles values given a string value. I'm creating this table:
CREATE TABLE cat_accident (
acc_type VARCHAR(30) NOT NULL CHECK(acc_type = 'Home accident' OR acc_type = 'Work accident'),
acc_descrip VARCHAR(30) NOT NULL
);
So basically I want to validate if acc_type is equal to Home accident, then acc_descrip can be or 'Intoxication' OR 'burns' OR 'Kitchen wound', OR if acc_type is equal to Work Accident, then acc_descrip can be OR 'freezing' OR 'electrocution'.
How do I write that constraint?
Use a CHECK constraint with a CASE expression:
CREATE TABLE cat_accident (
acc_type VARCHAR(30) NOT NULL,
acc_descrip VARCHAR(30) NOT NULL
CHECK(
CASE acc_type
WHEN 'Home accident' THEN acc_descrip IN ('Intoxication', 'burns', 'Kitchen wound')
WHEN 'Work accident' THEN acc_descrip IN ('freezing', 'electrocution')
END
)
);
See the demo.
I'd suggest implementing this with a lookup table:
CREATE TABLE l_accident_description(
description_id VARCHAR(5) PRIMARY KEY,
description_full VARCHAR(30) NOT NULL UNIQUE,
location VARCHAR(30)
);
INSERT INTO l_accident_description
(description_id,description_full,location)
VALUES
('INTOX','Intoxication','Home Accident'),
('BURNS','Burns','Home Accident'),
('K_WND','Kitchen wound','Home Accident'),
('FREEZ','Freezing','Work Accident'),
('ELECT','Electrocution','Work Accident');
That way you can encode the relationship you want to encode into cat_accident, but if the details ever change, it's only a matter of inserting/deleting/updating rows in your lookup table. This implementation has the added benefit that you're not storing as much data repetitively in your table (just a VARCHAR(5) code rather than a VARCHAR(30) string). The table construction then becomes (with added primary key):
CREATE TABLE cat_accident (
cat_accident_id PRIMARY KEY,
acc_descrip VARCHAR(5) NOT NULL REFERENCES l_accident_description(description_id)
);
Any time you wanted to know whether the accident Home/Work, this could be accomplished with a query joining the lookup table. Joining lookup tables is more in the spirit of good database construction, rather than hard-coding checks to tables that may easily change or grow more complex as the database grows.
In fact, the ideal solution might be to create two lookup tables here, with l_accident_description in turn referencing a location lookup, but for simplicity's sake I've shown how it might be accomplished with one.

How to prevent a input of certain letters using Oracle

The code is the category of the video, it is represented by one upper case character, excluding I, O,
Q, V, Y and Z, followed by a numeric character.
So far, I took a guess and got this. Any suggestions on how to fix it?
create table channelTable (
channelID number NOT NULL,
ChannelName varchar(100) NOT NULL,
ChannelDate date NOT NULL,
UserName varchar(100) NOT NULL UNIQUE,
TopicCode varchar(4) NOT NULL);
CONSTRAINT channelID_pk PRIMARY KEY (channelID)
CONSTRAINT c_topicCode LIKE '[A-Za-z][0-9] NOT (I,O,Q,N,Y,Z)
);
Some comments:
NOT NULL is not needed for PRIMARY KEY columns.
In Oracle, use VARCHAR2().
Then, I would suggests regular expressions. If the value is supposed to be exactly two characters, then declare it as such:
create table channelTable (
channelID number,
ChannelName varchar(100) NOT NULL,
ChannelDate date NOT NULL,
UserName varchar2(100) NOT NULL UNIQUE,
TopicCode char(2) NOT NULL;
CONSTRAINT channelID_pk PRIMARY KEY (channelID)
CONSTRAINT check (REGEXP_LIKE(c_topicCode, '^[A-HJ-NPR-UYZ][0-9]$')
);
Or perhaps more simply:
CONSTRAINT REGEXP_LIKE(c_topicCode, '^[A-Z][0-9]$') AND NOT REGEXP_LIKE(c_topicCode, '^[IOQNYZ]'))
All that said, I would rather see a table of TopicCodes that is populated with the correct values. Then you can just use a foreign key relationship to define the appropriate codes.
Use the regular expression ^[A-HJ-MPR-X]\d$ to match an upper-case character excluding I,O,Q,N,Y,Z followed by a digit:
CREATE TABLE channels (
id number CONSTRAINT channel__id__pk PRIMARY KEY,
Name varchar(100) CONSTRAINT channel__name__nn NOT NULL,
DateTime date CONSTRAINT channel__date__nn NOT NULL,
UserName varchar(100) CONSTRAINT channel__username__NN NOT NULL
CONSTRAINT channel__username__U UNIQUE,
TopicCode varchar(4),
CONSTRAINT channel__topiccode__chk CHECK ( REGEXP_LIKE( topiccode, '^[A-HJ-MPR-X]\d$' ) )
);
db<>fiddle
Also, you don't need to call the table channeltable just call it channels and you don't need to prefix the column names with the table name and you can name all the constraints (rather than relying on system generated constraint names which makes it much harder to track down issues when you are debugging).
Consider the following check constrait:
create table channelTable (
...
topicCode varchar(4) not null
check(
substr(c_topicCode, 1, 1) not in ('I', 'O', 'Q', 'V', 'Y', 'Z')
and regexp_like(topicCode, '^[A-Z]\d')
),
...
);
The first condition ensures that the code does not start with one of the forbidden characters, the second valides that it stats with an upper alphabetic character, followed by a number.
To avoid using two conditions, an alternative would be to list all allowed characters in the first position:
check(regexp_like(topicCode, '^[ABCDEFGHJKLMNPRSTUVWX]\d'))
This works in Oracle, and in very recent versions of MySQL.

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.

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.