"no matching unique or primary key for this column-list" Error in SQL - sql

Was creating some tables in SQL and got stuck when I had to design the following tables:
As you can see it is impossible to create Room details and services details Table without customer receipt table as they contain Receipt_no as the primary key.
Similarly, it is impossible to create a Customer Receipt table without Room_charges and Service_charges attributes without first creating the two details tables.
Hence, I first created a customer receipt table but without FK constraints on Room_Charges and Service_charges and then I created Services Details and Room Details tables.
Later, using ALTER command I tried to add FK Constraints on Customer Receipt table but it gives me this error
ORA-02270: no matching unique or primary key for this column-list
Now, after researching a bit about it on StackOverflow, there might be three possible cases as mentioned in the approved answer (# Oracle (ORA-02270) : no matching unique or primary key for this column-list error )
I think my case is number 3 as I have ensured the first two cases to be implemented.
Can anyone help me resolve it?
I am attaching SQL Code as a reference:
CREATE TABLE Customer_Receipt
(
Receipt_no VARCHAR2(12) PRIMARY KEY,
Booking_no NUMBER NOT NULL,
Total_charges NUMBER(12,2),
CONSTRAINT bookingnocustrec
FOREIGN KEY(Booking_no) REFERENCES Room_booking (Booking_no)
);
CREATE TABLE Services_Details
(
Receipt_no VARCHAR2(12) NOT NULL,
Service_offered VARCHAR2(8) NOT NULL,
Service_charges NUMBER(12,2),
PRIMARY KEY(Receipt_no, Service_offered),
CONSTRAINT recno
FOREIGN KEY(Receipt_no) REFERENCES Customer_receipt (Receipt_no)
);
ALTER TABLE Services_Details
MODIFY Service_charges NOT NULL;
CREATE TABLE Room_Details
(
Receipt_no VARCHAR2(12) NOT NULL,
Category_name VARCHAR2(9) NOT NULL,
Days_stayed INT,
Room_charges NUMBER(12,2),
PRIMARY KEY(Receipt_no, Category_name),
CONSTRAINT recno1
FOREIGN KEY(Receipt_no) REFERENCES Customer_receipt (Receipt_no),
CONSTRAINT catname1
FOREIGN KEY(Category_name) REFERENCES Room_category (Category_name)
);
ALTER TABLE Customer_receipt
ADD Room_charges NUMBER(12,2) NOT NULL;
ALTER TABLE Customer_receipt
ADD CONSTRAINT FK_RC
FOREIGN KEY (Room_charges) REFERENCES Room_Details (Room_charges);

As a frame challenge.
Can anyone help me resolve it?
Yes, do not violate Third Normal Form and do not duplicate data by storing Total_Charges, Service_Charges or Room_Charges in the Customer_Receipt table when the data is already stored in the Service_Details and Room_Details tables.
If you are storing the same data in two locations then you are likely get into the situation where the data is inconsistent between those two location; just store each piece of data in a single location so there is a single source of truth in your database.
CREATE TABLE Customer_Receipt
(
Receipt_no VARCHAR2(12)
CONSTRAINT custreceipt__recno__pk PRIMARY KEY,
Booking_no CONSTRAINT custreceipt__bookingno__fk REFERENCES Room_booking
NOT NULL
);
CREATE TABLE Services_Details
(
Receipt_no CONSTRAINT servicedetails__recno__fk REFERENCES Customer_receipt
NOT NULL,
Service_offered VARCHAR2(8)
NOT NULL,
Service_charges NUMBER(12,2),
CONSTRAINT servicedetails__recno_servoff__pk PRIMARY KEY(Receipt_no, Service_offered)
);
CREATE TABLE Room_Details
(
Receipt_no CONSTRAINT roomdetails__recno__fk REFERENCES Customer_receipt
NOT NULL,
Category_name CONSTRAINT roomdetails__catname__fk REFERENCES Room_category
NOT NULL,
Days_stayed INT,
Room_charges NUMBER(12,2),
CONSTRAINT roomdetails__recno_catname__pk PRIMARY KEY(Receipt_no, Category_name)
);
If you want to display the Total_Charges, Service_Charges and Room_Charges then use a JOIN and get the data from the related tables. Something like:
SELECT cr.*,
COALESCE(s.service_charges, 0) AS service_charges,
COALESCE(r.room_charges, 0) AS room_charges,
COALESCE(s.service_charges, 0) + COALESCE(r.room_charges, 0)
AS total_charges
FROM customer_receipt cr
LEFT OUTER JOIN (
SELECT receipt_no,
SUM(service_charges) AS service_charges
FROM services_details
GROUP BY receipt_no
) s
ON cr.receipt_no = s.receipt_no
LEFT OUTER JOIN (
SELECT receipt_no,
SUM(days_stayed * room_charges) AS room_charges
FROM room_details
GROUP BY receipt_no
) r
ON cr.receipt_no = r.receipt_no;
Or create a view (or a materialized view).

Related

How to fix "ERROR: FK name length exceeds maximum allowed length(30)" in SQL Developer Data Modeller

I'm trying to turn the Logical Model of my Database into a DDL script, but I don't know how to fix this error in the DDL script or Data Modeller:-- ERROR: FK name length exceeds maximum allowed length(30)
It seems to be based on my junction-table's Primary Key, which is made up from two Foreign Keys from the two neighboring tables.
I have tried changing the names of the Primary Keys in the neighboring tables, but when I try to generate a NEW DDL script with Data Modeler, it still generates the old script.
Here's the sections of code that create the 3 tables and link them together:
CREATE TABLE items (
item_no NUMBER (8) NOT NULL,
"year" DATE,
price NUMBER (20,2)
);
ALTER TABLE items ADD CONSTRAINT items_pk PRIMARY KEY ( item_no );
CREATE TABLE purchase_order (
order_no NUMBER(8) NOT NULL,
quantity INTEGER,
item_description VARCHAR2(200),
unit_price NUMBER(20,2),
total NUMBER(20,2),
order_date DATE,
sales_person_code VARCHAR2(5) NOT NULL,
supplier_id NUMBER(3) NOT NULL
);
ALTER TABLE purchase_order ADD CONSTRAINT purchase_order_pk PRIMARY KEY ( order_no );
CREATE TABLE purchase_order_items (
purchase_order_order_no NUMBER(8) NOT NULL,
items_item_no NUMBER(8) NOT NULL
);
ALTER TABLE purchase_order_items ADD CONSTRAINT purchase_order_items_pk PRIMARY KEY ( items_item_no,
purchase_order_order_no );
ALTER TABLE purchase_order_items
ADD CONSTRAINT purchase_order_items_items_fk FOREIGN KEY ( items_item_no )
REFERENCES items ( item_no );
-- ERROR: FK name length exceeds maximum allowed length(30)
ALTER TABLE purchase_order_items
ADD CONSTRAINT purchase_order_items_purchase_order_fk FOREIGN KEY ( purchase_order_order_no )
REFERENCES purchase_order ( order_no );
ALTER TABLE purchase_order
ADD CONSTRAINT purchase_order_sales_person_fk FOREIGN KEY ( sales_person_code )
REFERENCES sales_person ( code );
ALTER TABLE purchase_order
ADD CONSTRAINT purchase_order_supplier_fk FOREIGN KEY ( supplier_id )
REFERENCES supplier ( id );
So I'm not sure exactly what FK name length is too long and what I need to change in the script to fix this error.
Oracle limits identifiers to 30 characters, so
purchase_order_items_purchase_order_fk needs to be shorted. Perhaps to something like poi_purchase_porder_fk.

Oracle: Constraints of keys

I have an entity within Oracle's SQL:
and I'm wondering, what does "UF" represent? I've written the SQL code but I do not know how to represent the "UF" attribute as a constraint.
CREATE TABLE entry (
entryno NUMBER(4) NOT NULL,
carndate DATE NOT NULL,
entrystarttime DATE NOT NULL,
entryfinishtime DATE NOT NULL,
entryplace NUMBER(4) NOT NULL,
charname VARCHAR2(30) NOT NULL,
compno NUMBER(4) NOT NULL,
eventypecode CHAR(3) NOT NULL,
teamname VARCHAR2(30) NOT NULL
);
ALTER TABLE entry ADD CONSTRAINT entry_pk PRIMARY KEY ( entryno,
carndate );
ALTER TABLE entry
ADD CONSTRAINT entry_charity_fk FOREIGN KEY ( charname )
REFERENCES charity ( charname );
ALTER TABLE entry
ADD CONSTRAINT entry_carnival_fk FOREIGN KEY ( carndate )
REFERENCES carnival ( carndate );
ALTER TABLE entry #
ADD CONSTRAINT entry_competitor_fk FOREIGN KEY ( compno )
REFERENCES competitor ( compno );
ALTER TABLE entry #
ADD CONSTRAINT entry_event_fk FOREIGN KEY ( carndate, eventypecode )
REFERENCES evenet ( carndate, eventypecode );
ALTER TABLE entry
ADD CONSTRAINT entry_team_fk FOREIGN KEY ( teamname, carndate )
REFERENCES team ( teamname,carndate );
ALTER TABLE entry
ADD CONSTRAINT ... ("UF")
The UF is actually two flags.
As you've recognised the F means the column is a foreign key. The U stands for Unique. Those columns form part of the compound unique key:
ALTER TABLE entry ADD CONSTRAINT entry_carnival_un UNIQUE
( carndate, compno, eventypecode );
carndate is also part of the compound primary key so really it should be flagged PFU but I guess the modelling tool didn't allow for three flags.

ORA-01748: only simple column names allowed here in Oracle

What I am trying to do ?
I am trying to create two tables and at the same time i am trying to link them together using foreign and primary keys. However I successfully create my parent table ( Student with primary key ) but failed to create child table ( Attendence with foreign key ).
What is the problem ?
I get the following error while creating Attendence table:
ERROR at line 5: ORA-01748: only simple column names allowed here
My code:
Student table:
create table Student (
ST_ROLLNO NUMBER(6) constraint s_pk primary key,
ST_NAME VARCHAR(30) not null,
ST_ADDRESS varchar(35) not null
);
Attendence table:
create table Attendence (
ST_ROLLNO NUMBER(6),
ST_DATE VARCHAR(30) not null,
ST_PRESENT_ABSENT varchar(1) not null,
constraint f_pk Attendence.ST_ROLLNO foreign key references Student(ST_ROLLNO)
);
Your foreign key constraint syntax is wrong; it should be:
constraint f_pk foreign key (ST_ROLLNO) references Student(ST_ROLLNO)
You are preceding the FK column name with the table name, which is wrong in itself, but also have it in the wrong place.
create table Student (
ST_ROLLNO NUMBER(6) constraint s_pk primary key,
ST_NAME VARCHAR(30) not null,
ST_ADDRESS varchar(35) not null
);
Table STUDENT created.
create table Attendence (
ST_ROLLNO NUMBER(6),
ST_DATE VARCHAR(30) not null,
ST_PRESENT_ABSENT varchar(1) not null,
constraint f_pk foreign key (ST_ROLLNO) references Student(ST_ROLLNO)
);
Table ATTENDENCE created.
According to oracle documentation,
ORA ERR
ORA-01748 only simple column names allowed here
The following is the cause of this error:
This SQL statement does not allow a qualified column name, such as
username.table.column or table.column.
Action you can take to resolve this issue: Remove the qualifications
from the column and retry the operation.
In your case, you are trying to refer to the table name while defining a constraint -
Attendence.ST_ROLLNO - WRONG.
It must contain a simple name without the table name or schema name.

No matching unique or primary key for this column-list in Oracle

I have created PERSON table in Oracle by this SQL syntax:
Create table person
(
p_id int not null,
personName char(5) not null );
Then I am trying to create ORDERS table with the following syntax:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES person(p_id) );
But I am getting the following error .
No matching unique or primary key for this column-list.
What is the problem ? How can I solve this ?
Add primary key to person table:
CREATE TABLE person(
p_id int not null,
personName char(5) not null,
PRIMARY KEY (p_ID)
);
SqlFiddleDemo
Foreign keys enforce a one-to-many relationship. That is, however many records there are in the dependent table they can only reference a single record in the parent table. This means the referenced column(s) in the parent table must be constrained by a PRIMARY or UNIQUE key.
The error message is telling you that there is no such constraint on person(p_id). And lo! if we compare the two DDL statements you have posted we can see that you have created a primary key for ORDERS but not for PERSON.
The solution is simple: constrain P_ID by adding a primary key to PERSON. You can either drop and re-create the table, or you can use an alter table statement to add a primary key.
You should add primary key to person table.
try this:
ALTER TABLE Person
ADD CONSTRAINT p_id PRIMARY KEY (p_id);

Sybase constraint with foreign key and conditional check against foreign table column value

Is it possible on Sybase to define a constraint(s) which require a column to be a foreign key and also satisfy a condition based on the value of a foreign column, e.g. in the below example tables could a constraint be created on the "product" table such that "product.code is a foreign key of a brand.code which has valid=1"?
CREATE TABLE brand (
code char(8) NOT NULL,
valid int NOT NULL,
rowid numeric(10,0) IDENTITY,
CONSTRAINT brand_pk PRIMARY KEY (code),
CONSTRAINT valid_check CHECK (valid IN (0,1))
)
CREATE TABLE product (
code char(8) NOT NULL,
CONSTRAINT product_pk PRIMARY KEY (code)
)
I think it's best to change the structure just a little bit.
CREATE TABLE brand (
code char(8) NOT NULL,
valid int NOT NULL,
rowid numeric(10,0) IDENTITY,
CONSTRAINT brand_pk PRIMARY KEY (code),
-- The following UNIQUE constraint lets the pair of values be the target of
-- a foreign key reference.
CONSTRAINT brand_is_valid UNIQUE (code, valid),
CONSTRAINT valid_check CHECK (valid IN (0,1))
);
CREATE TABLE product (
code char(8) NOT NULL,
valid int NOT NULL,
-- The column "code" is a PK in the referenced table, so this still works. It's
-- a 1:0 or 1:1 relationship.
CONSTRAINT product_pk PRIMARY KEY (code),
-- The next constraint requires a unique constraint on the pair of
-- columns in the table "brand". By itself, it references every row
-- in "brand". That's too many rows.
CONSTRAINT product_fk FOREIGN KEY (code, valid)
REFERENCES brand (code, valid),
-- But this constraint restricts the foreign key references to only those
-- rows that have valid = 1 in the table "brand".
CHECK (valid = 1)
);
In order to bypass the creation of a foreign-key based on the "valid" condition, you will need to modify your table design and create a trigger to set the product.code = NULL. Pardon my syntax (I haven't coded Sybase for a while), but this is the general idea:
Add a new column to serve as the primary key since we will need to set product.code = NULL when valid=0:
CREATE TABLE product (
rowid int identity primary key,
code char(8) NULL,
CONSTRAINT brand_fk FOREIGN KEY (code) REFERENCES brand(code)
)
Then create a trigger similar to this one:
create trigger FK_WhenValid
on product
for insert
AS
IF (SELECT COUNT(*) FROM brand b inner join inserted i on b.code = i.code AND b.valid=0 ) > 0
BEGIN
UPDATE product SET code = NULL WHERE code in (SELECT i.code from brand b join inserted i on b.code = i.code and b.valid = 0)
END
Note: this trigger only supports product insertions. If "valid" can change, another approach is required.
You could also implement the foreign key as a trigger instead of a declarative constraint and only set product.code = inserted.code when valid = 1