column check constraint cannot reference other columns in oracle database - sql

I have been looking into this error for quite a while and read other articles on this but can't seem to find the answer on why it gives the error
column check constraint cannot reference other columns
CREATE TABLE reservations
(member_id CHAR(7)
CONSTRAINT res_memberid_pk PRIMARY KEY
CONSTRAINT res_memberid_fk REFERENCES members(member_id)
,date_sh DATE DEFAULT SYSDATE
CONSTRAINT res_datesh_ck CHECK(date_sh < TO_DATE ("23:00","hh24:mi"))
,terrain NUMBER(2)
CONSTRAINT res_ter_nn NOT NULL
,opponent_id CHAR(7)
CONSTRAINT res_opid_fk REFERENCES members(member_id)
);

Double quotes signifies an identifier. Single quotes are for text literals.
You want:
TO_DATE ('23:00','hh24:mi')
and TO_DATE ('23:00','hh24:mi') will be the 23:00 on the 1st day of the current month (which may or may not be what you want). However, it would not work in a check constraint as it does not specify the year, month and day components and will throw:
ORA-02436: date or system variable wrongly specified in CHECK constraint
If you want to constrain it so that the time component of the date is less than 23:00 then:
CONSTRAINT res_datesh_ck CHECK(EXTRACT(HOUR FROM CAST(date_sh AS TIMESTAMP)) < 23)
db<>fiddle here

Yes a constraint can reference another column, it is called a "FOREIGN KEY CONSTRAINT". There are plenty of examples of the web on the syntax - it's a bit different from what you have written... you need to define the column and then set a constraint on that column indicating it is a foreign key and references the other table. For example (simplified, just a members table and a reservations table with a foreign key constraint to members):
create table members (
member_id number generated by default on null as identity
constraint members_member_id_pk primary key
)
;
create table reservations (
reserveration_id number generated by default on null as identity
constraint reservations_reserveration_pk primary key,
member_id number
constraint reservations_member_id_fk
references members on delete cascade
)
;
Note that naming your primary key column "member_id" in a table called "reservations" is very confusing.

Related

PostreSql: ERROR: column referenced in foreign key constraint does not exist

What might possibly gone wrong?
ERROR: column "parameter_id" referenced in foreign key constraint does not exist
1 statement failed.
So i created 2 tables(parameters and periods) with the commands;
create table parameters(
parameter_id serial primary key,
temperature real,
feels_good_temperature int,
humidity int,
max_uv_index int
);
and
create table periods(
period_id serial primary key,
time_stamp text
);
...and now i want to have a column, fk_paramter_id in periods table, as a foreign key to the parameters table
I tried achieving it with;
ALTER TABLE periods
ADD CONSTRAINT fk_parameter_id FOREIGN KEY (parameter_id)
REFERENCES parameters(parameter_id);
You first have to create and populate the column:
ALTER TABLE periods ADD parameter_id integer;
Then use UPDATEs to set the correct values.
Now you can define the constraint.
Note: the constraint (fk_paramter_id) is not a column; it is defined on a column (parameter_id).

Foreign key referencing primary key of multiple values

Im using ms sql server. I get this msg when I reference a primary key that is a composite key of 3 values in the foreign key.
"number of referencing columns in foreign key differs from the number of reference columns". The problem lies in second last line of code in member booking. Any ideas? Thanks in advance.
CREATE TABLE room
(
Block CHAR (1),
Lvl INT,
rNum INT,
RmType VARCHAR (15),
Condition VARCHAR (15),
CONSTRAINT room_PK PRIMARY KEY (Block, Lvl, rNum),
)
CREATE TABLE booking
(
BookingID INT,
BStartDate DATE,
BEndDate DATE,
Fee DECIMAL (8,2) NOT NULL CHECK (fee >= 0),
Memberbooking INT NOT NULL,
MemberID INT NOT NULL,
CONSTRAINT booking_pk PRIMARY KEY (BookingID),
CONSTRAINT FK_Booking FOREIGN KEY (Memberbooking) references room (Block, Lvl, rNum),
CONSTRAINT FK_MemberID FOREIGN KEY (MemberID) references member (ID)
)
You are getting an error because you are trying to map 1 column (FOREIGN KEY (Memberbooking)) with 3 columns room (Block, Lvl, rNum)
it's possible to create a foreign key relationship to a compound (more
than one column) primary key, make sure to specify the same number of columns in your FOREIGN KEY
You define this constraint in the table booking:
CONSTRAINT FK_Booking FOREIGN KEY (Memberbooking) references room (Block, Lvl, rNum)
meaning that you want the column Memberbooking to reference 3 columns (!!) in the table room.
Each column from a table can reference one column from another table, not multiple ones.
You can define the same column to reference more than 1 columns in another table, but with different constraints, and always 1 to 1.
Read more here: Create Foreign Key Relationships
Since I see from the comments you are intent to implement this type of check, I would propose a check constraint:
CONSTRAINT CK_MemberID CHECK (EXISTS(SELECT 1 FROM room where Memberbooking=room.Block+convert(nchar,room.Lvl)+convert(nchar,room.rNum)))
However, this design is not very good. The lack of seperators in the Membermooking field might cause collisions.
Eg, consider you have a Memberbooking: 'A1101'
Is that Block A, Lvl 11, rNum 01? Or is it Block A, Lvl 1, rNum 101?
On table "room", you currently have a compound natural key. This is a valid design decision. The alternative would be to add a single column artificial id, such as an int Identity. That would lead to two keys on the same table (one of them Primary Key, the other one Unique constraint).
In a foreign key constraint, you can reference any Unique constraint or Primary Key. If you want to keep the "room" table the way it is, then you need to mirror those key fields in the referencing table. So that would mean your "booking" table would need a Block char(1), Lvl int and rNum int column.
That is why an artificial key (on room) can be useful, because then your foreign key constraint (on booking) can be single column and reference that Unique constaint.

Oracle 12c - Column check constraint cannot reference other column

I have to modify my table and I try do it as following:
ALTER TABLE projects
MODIFY (
id_proj NUMBER(4) CONSTRAINT pk_proj PRIMARY KEY,
desc VARCHAR2(40) NOT NULL CONSTRAINT uk_proj UNIQUE,
end_date CONSTRAINT chk_date CHECK(end_date > start_date),
fund CHECK (fund > 0)
);
And when I try execute this query I get an error:
ORA-02438: Column check constraint cannot reference other columns
02438. 00000 - "Column check constraint cannot reference other columns"
*Cause: attempted to define a column check constraint that references
another column.
*Action: define it as a table check constraint.
Additionally I want the column to accept values greater than 0 or NULL values.
This is just a syntax quirk. Do this:
ALTER TABLE projects
MODIFY (
id_proj NUMBER(4) CONSTRAINT pk_proj PRIMARY KEY,
desc VARCHAR2(40) NOT NULL CONSTRAINT uk_proj UNIQUE,
end_date DATE, -- I'm guessing this is the type
CONSTRAINT chk_date CHECK (end_date > start_date),
fund CHECK (fund > 0)
);
As the error suggests, you cannot have an in-line check constraint that references other columns. You can still have a check constraint; it just needs to be declared by itself as a constraint.
While we are commenting:
desc is a really bad name for a column, because it is a SQL key word. Use descr or spell the whole thing out, description.
CONSTRAINT uk_proj UNIQUE seems verbose to me. It can be replaced with a simple UNIQUE. Admittedly, this doesn't allow you to name unique constraints. Is that important for your database?
The same is true of the primary key constraint. (If you have a reason to name them, then leave it as it is; I just don't often find such a reason.)

Can't add foreign key constraint to table

CREATE TABLE CUSTOMER
(
CNUM VARCHAR(25) NOT NULL,
CNAME VARCHAR(75) NOT NULL,
CTYPE VARCHAR(20) NOT NULL,
CONSTRAINT CUSTOMER_PK PRIMARY KEY(CNUM),
CONSTRAINT CHECK_CTYPE CHECK(CTYPE IN('INDIVIDUAL', 'INSTITUTION'))
);
CREATE TABLE CREDIT_TERM
(
CREDITSTATUS VARCHAR(20) NOT NULL,
STARTDATE DATE NOT NULL,
ENDDATE DATE NOT NULL,
CONSTRAINT CREDIT_TERM_PK PRIMARY KEY(CREDITSTATUS)
);
insert into CREDIT_TERM values('ONE-MONTH','15-05-2015','15-06-2015');
insert into CREDIT_TERM values('TWO-MONTH','15-05-2015','15-06-2015');
insert into CREDIT_TERM values('THREE-MONTH','15-05-2015','15-06-2015');
ALTER TABLE CUSTOMER
ADD CONSTRAINT CUSTOMER_FK_CREDITSTATUS
FOREIGN KEY(CREDITSTATUS) REFERENCES CREDIT_TERM(CREDITSTATUS);
I am trying to add a foreign key constraint, but I don't understand why I get this error:
ERROR at last line :
ORA-00904: "CREDITSTATUS": invalid identifier
As I noted in the comments, your customer table does not have a creditstatus column. You'd first have to add it:
ALTER TABLE customer ADD creditstatus VARCHAR2(20);
And then make it a foreign key, with the statement you already have.
You're trying to add a foreign key constraint for a foreign key named CREDITSTATUS on the CUSTOMER table. However, the CUSTOMER table doesn't have a foreign key for CREDITSTATUS.
You'll have to create a foreign key in CUSTOMER for CREDITSTATUS, then rerun the last line to add the constraint.
EDIT
Use ALTER TABLE to add the column to CUSTOMER:
ALTER TABLE CUSTOMER ADD CREDITSTATUS VARCHAR(20);
Docs:
http://www.techonthenet.com/oracle/tables/alter_table.php
You can add the column and the foreign key constraint in one statement:
alter table customer add (
creditstatus varchar2(20) constraint customer_fk_creditstatus references credit_term
);
A few notes. First, I enclosed the column definition in parentheses. It may work without them, but the official syntax seems to require them. http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_3001.htm#i2103924
Second, in an in-line constraint (defined at the column level, not at the table level), you may not use the words FOREIGN KEY. The word REFERENCES already identifies the constraint type. Third, if you reference the PRIMARY KEY of the referenced table, you are not required to (but you may if you wish) name the referenced column in the referenced table. If you don't name the column, the PRIMARY KEY of the referenced table will be used by default - which is what you want anyway, in the vast majority of cases.

How to make a UNIQUE constraint on a Date type column without taking year in regard?

I have a "trips" table with date column (date of trip),but I need not to repeat the day of trip, so I want to know if I could do a unique constraint on a part of the date using sql server 2014.
I create this table
CREATE TABLE trips
(
ID int IDENTITY(1,1) PRIMARY KEY not null ,
day_of_trip date not null,
time_of_trip time not null,
cost money not null,
passengers int not null,
bus_id int not null,
trans_comp_id int not null,
route_id int not null,
CONSTRAINT UK_time UNIQUE (day_of_trip,time_of_trip,bus_id),
FOREIGN KEY (bus_id) REFERENCES bus(id),
FOREIGN KEY (trans_comp_id) REFERENCES trans_comp(id),
FOREIGN KEY (route_id) REFERENCES routes_(id)
)
but when inserting data in day_of_trip just like
first trip: 1/2/2015
second trip: 5/8/2015
it gives an error because of
Msg 2627, Level 14, State 1, Line 7
Violation of UNIQUE KEY constraint 'UK_time'. Cannot insert duplicate key in object 'dbo.trips'. The duplicate key value is (2015-01-02, 06:20:00.0000000, 2).
I want to have more than one trip in 2015 but not on 1/2/2015.
"I want to know if I could do a constraint on a part of the date using sql server 2014."
I assume you mean "unique constraint" given the title. If this is your question, then the answer is "yes". You do so by created computed columns and then building a unique index on those.
Here is one way:
alter table <table> add mmdd as (month(date)*100 + day(date) );
create unique index idx_table_mmdd on <table>(mmdd);