Oracle 12c - Column check constraint cannot reference other column - sql

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

Related

column check constraint cannot reference other columns in oracle database

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.

Missing keyword in Oracle SQL

What's wrong with this query?
I am getting following error:
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
My SQL:
CREATE Table ORDERDET
(
ORDERID NUMBER,
CUSTID NUMBER,
PRODID NUMBER,
ORDPRIORITY VARCHAR2(15),
ORDDISCOUNT NUMBER(3,2),
ORDSHIPMODE VARCHAR2(15),
ORDDATE DATE,
ORDSHIPDATE DATE,
ORDSHIPCOST NUMBER(5,2),
ORDQTY NUMBER,
ORDSALES NUMBER(7,2),
CONSTRAINT ch_ORDPRIORITY
CHECK (ORDPRIORITY IN ('Low', 'Medium', 'High', 'Critical', 'Not Specified')),
CONSTRAINT ch_ORDSHIPMODE
CHECK (ORDSHIPMODE IN ('Regular Air','Delivery Truck','Express Air')),
CONSTRAINT pk_ORDERDET
PRIMARY KEY (ORDERID, CUSTID, PRODID),
CONSTRAINT fk_ORDERD
FOREIGN KEY (ORDERID) REFERENCES ORDERS (ORDERID) on DELETE RESTRICT,
CONSTRAINT fk_CUSTOMERORDER
FOREIGN KEY (CUSTID) REFERENCES CUSTOMERS (CUSTID) on DELETE RESTRICT,
CONSTRAINT fk_PRODUCTORDER
FOREIGN KEY (PRODID) REFERENCES PRODUCTS (PRODID) on DELETE RESTRICT
);
According to the documentation: CREATE TABLE
there is no on DELETE RESTRICT option, only CASCADE or SET NULL are allowed, please see attached syntax diagram below:
I guess you want to prevent from deletion of a row in the parent table in a case when there are rows in the child table that references this parent row - if yes, then skip ON DELETE clause completely, because this is default behaviour of the foreign key constraint.
----------
EDIT
----------
Error report - ORA-02264: name already used by an existing constraint
02264. 00000 - "name already used by an existing constraint" *Cause: The specified constraint name has to be unique. *Action: Specify a
unique constraint name for the constraint.
The error message says, that one of a constraint name you have used in the create table has already been creaded (used) and you cannot use it again.
I think you haven't showed us the whole error message, because Oracle should print this duplicate name.
Anyway, you can find which name is duplicate using this query:
select *
from user_objects
where object_name in (
'CH_ORDPRIORITY' ,
'CH_ORDSHIPMODE' ,
'PK_ORDERDET' ,
'FK_ORDERD' ,
'FK_CUSTOMERORDER' ,
'FK_PRODUCTORDER'
)
If one (or a few) of these names are already used, then use a different name, say FK_PRODUCTORDER_11 instead of FK_PRODUCTORDER

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.

Violated - parent key not found 02291. 00000 - "integrity constraint

Hi I am developing a database in Oracle SQL dev, that is trying to access foriegn keys from another table. I am currently working on the ItemOrdered table which I've created with the following CREATE statement
CREATE TABLE ItemOrdered(OrderID varchar2(9) REFERENCES Ords(OrderID),
BeltID varchar2(9) REFERENCES BeltID(BeltID),
Quantity varchar(4) NOT NULL,
PRIMARY KEY(OrderID, BeltID))
As you can See I have the following foriegn keys Ords and BeltID.
Now when I try to run the following statement
INSERT INTO ItemOrdered VALUES(401565981,234489212,'2')
It gives me the following error
violated - parent key not found
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
I have provided my Ords CREATE statement if its needed
CREATE TABLE Ords(OrderID varchar2(9) PRIMARY KEY,
CustomerID varchar(9) REFERENCES Customers(CustomerID),
Expected_Delivery_Date date DEFAULT sysdate NOT NULL,
Actual_Delivery_Date date DEFAULT sysdate NOT NULL,
Payment_Due_Date date DEFAULT sysdate NOT NULL,
Order_Date date DEFAULT sysdate NOT NULL, Price Varchar(10),
Order_Placed varchar2(1) CONSTRAINT OrderPlaced
CHECK(Order_Placed IN('Y','N')) NOT NULL,
Order_Confirmed varchar2(1)
CONSTRAINT Order_Confirmed CHECK(Order_Confirmed IN('Y','N')) NOT NULL,
Order_Completed varchar2(1) CONSTRAINT Order_Completed
CHECK(Order_Completed IN('Y','N')) NOT NULL)
And I have also provided my BeltID CREATE statement
CREATE TABLE BeltID(BeltID varchar2(9) PRIMARY KEY,
BeltLengthID varchar2(9) REFERENCES BeltLength(BeltLengthID),
ColourID varchar2(9) REFERENCES Colour(ColourID),
DesignID varchar2(9) REFERENCES Design(DesignID),ComponentID varchar2(9) REFERENCES Component(ComponentID))
I don't seem to quite understand why I am getting this error. Is there an clear explanation why?
Here is the http link of what I am trying to do.
link text
Due to the foreign key constraints you specified when you created table ItemOrdered, when you perform this insert:
INSERT INTO ItemOrdered VALUES(401565981,234489212,'2')
... the values 401565981 and 234489212 must correspond to key values in the Ords and BelitId tables respectively - i.e. these 2 queries should return rows:
select *
from Ords
where OrderId = 401565981;
select *
from BeltId
where BeltId = 234489212;
The error message suggests this is not the case.
I have no Oracle installation available so I can't test, but does it matter if you enclose the OrderID and BeltID in single quotes (which you should do anyway since the columns are declared as varchars)? I haven't tested it, but one idea would be that Oracle barfs on the fact that you are inserting a numeric value into a varchar column.
insert
into ItemOrdered VALUES('401565981', '234489212','2')
Another option would be that the order of the columns in the table does not correspond to the order you gave them in the insert statement. To rule this out, try rewrite the statement as:
insert
into ItemOrdered(OrderID,BeltID,Quantity) values('401565981', '234489212','2')

Trouble understanding SQL (Oracle) create table code

I am aware of Oracle's create table syntax
CREATE TABLE MyTable(
id int primary key,
...
);
This will create a table called MyTable with an int primary key. So, nothing new here.
but I am having difficulties understanding the following query:
CREATE TABLE departament (
cod_dept INTEGER CONSTRAINT dept_key PRIMARY KEY,
dept_name CHAR(15) NOT NULL,
admission DATE NOT NULL,
localization CHAR(20))
When I look up on Oracle's SQL Developer software on departement's table, I can see 4 columns: cod_dept, dept_name, admission and localization. On the constraints tab, I can also see dept_key, but I am confused as to what this might mean. What is dept_key purpose here?
Edit
Ok, seems it is a way to define the name of the constraint you're adding to the table. My next question is why don't you just call it the same name as the primary key column? From what I've seen it seems Oracle by default just creates a random name for the constraint!
Thanks
When you write id int primary key, Oracle will create a primary key constraint to ensure uniqueness of primary key values. All constraints have names, so in this case Oracle assigns an autogenerated name to this constraint. But you can set a name of this constraint explicitly using the CONSTRAINT syntax:
cod_dept INTEGER CONSTRAINT dept_key PRIMARY KEY
This name may be used later to refer to the constraint, for example, to delete or modify it:
ALTER TABLE department DROP CONSTRAINT dept_key;
EDIT:
Constraint names are unique across the schema, so Oracle can't just use the name of primary key column as a constraint name.
Primary keys can be explicitly be named. dept_key is just a name.
dept_key is the name of the primary key constraint. That means cod_dept is the unique identifier for your table, the mechanism for identifying a row, and so it can only have one occurrence of any given value.
That is the constraint you created representing the primary key.
A table is made up of:
Columns (where the data lives)
Indexes (indexed copies of the data used for faster searching)
Constraints (rules about what data can be in the table, including PK, FK, and check constraints).
dept_key is the name of the constraint. You specified the name here : "INTEGER CONSTRAINT dept_key PRIMARY KEY," so it will create a constraint with the name dept_key.
Another syntax for the same would be to write the following after your CREATE TABLE instruction.
ALTER TABLE department
ADD CONSTRAINT dept_key PRIMARY KEY (cod_dept)
dept_key is then the name of the constraint you created to be the primary key for this table. In order for a database engine to know the primary key, and to index it for fastest results and so forth, it needs to create a known constraint that is indexed. Here, it is you who has given the name which is dept_key.
For you kind information, it is often seen to write PK_[table name] for primary keys constraints and FK_[current_table_name]_[foreign_table_name] for foreign keys constraints.
Hope this helps! =)
I think whenever we create a Primary Key value then by default Oracle will crate constraint for it with the same name but it looks like that u are creating constraint with some other name.
Thank You