PostgreSQL Error: relation "products" does not exist - sql

I'm trying to create the following schema
While I execute the following code I get the relation "products" does not exist error.
CREATE TABLE Orders(
ORDERID serial NOT NULL PRIMARY KEY,
ORDERDATE text NOT NULL default'',
CUSTOMERID serial NOT NULL REFERENCES Customers(CUSTOMERID),
NETAMOUNT text NOT NULL default'',
TAX text NOT NULL default'',
TOTALAMOUNT text NOT NULL default''
);
CREATE TABLE Orderlines(
ORDERLINEID serial NOT NULL,
ORDERID serial NOT NULL REFERENCES Orders(ORDERID),
PROD_ID serial NOT NULL REFERENCES Products(PROD_ID),
QUANTITY text NOT NULL default'',
ORDERDATE text NOT NULL default'',
PRIMARY KEY(ORDERLINEID,ORDERID)
);
CREATE TABLE Products(
PROD_ID serial NOT NULL PRIMARY KEY,
CATEGORY text NOT NULL references Products(CATEGORY),
TITLE text NOT NULL default'',
ACTOR text NOT NULL default'',
PRICE text NOT NULL default''
);
I am doing this in http://sqlfiddle.com/ if it has anything to do with it.

When the table orderlines is created, the create table for the products table has not been executed. You need to add the foreign keys after all tables have been created.
You should only defined the primary key columns as serial, not the foreign key columns - they will be referencing the generated values from the target table. You don't want to generate a new value for the FK column when you insert.
The foreign key:
CATEGORY text NOT NULL references Products(CATEGORY)
is wrong because of two reasons: First because category is not the primary key of the products table. And secondly because it doesn't make sense that the category column references itself. You probably wanted to reference the categories table.
You script is also missing the customers table.
And you are choosing the wrong data types.
Number or dates should NEVER be stored in text (or varchar) columns.
Putting all that together, the script should be something like this:
create table customers
(
customerid serial primary key,
.... other columns
);
create table categories
(
category serial primary key,
categoryname text not null
);
CREATE TABLE Orders
(
ORDERID serial NOT NULL PRIMARY KEY,
ORDERDATE date NOT NULL, -- no text here!
CUSTOMERID integer NOT NULL, --- NO serial here!
NETAMOUNT decimal (22,4) NOT NULL, -- no text here!
TAX decimal(18,2) NOT NULL, -- no text here!
TOTALAMOUNT decimal (24,4) NOT NULL -- no text here!
);
CREATE TABLE Orderlines
(
ORDERLINEID serial NOT NULL,
ORDERID integer NOT NULL, -- NO serial here!
PROD_ID integer NOT NULL, -- NO serial here!
QUANTITY integer NOT NULL,
ORDERDATE date NOT NULL, -- NO text here!
PRIMARY KEY(ORDERLINEID,ORDERID)
);
CREATE TABLE Products
(
PROD_ID serial NOT NULL PRIMARY KEY,
CATEGORY integer NOT NULL references categories,
TITLE text NOT NULL,
ACTOR text NOT NULL,
PRICE decimal (18,2) NOT NULL
);
alter table orderlines add foreign key (orderid) REFERENCES Orders(ORDERID);
alter table orderlines add foreign key (prod_id) REFERENCES products(prod_id);
alter table orders add foreign key (customerid) REFERENCES Customers(CUSTOMERID);

Related

Adding an Array of INT column where each value is a primary key from another table

Given two tables like so
CREATE TABLE participants(
id SERIAL PRIMARY KEY,
Name TEXT NOT NULL,
Title TEXT NOT NULL
);
CREATE TABLE meetings (
id SERIAL PRIMARY KEY,
Organizer TEXT NOT NULL,
StartTime DATE NOT NULL,
EndTime DATE NOT NULL,
Participants INT[],
);
I want Participants column of 'meetings' table to contain set of integers which are all primary keys (specific participant) from 'participants' table.
How do I define this field in 'meetings' table ?
The old fashioned way is to create a many-many table, with a couple of commonsense constraints:
CREATE TABLE meetings_participants(
meeting_id int not null,
participant_id int not null,
primary key (meeting_id, participant_id),
foreign key(meeting_id) references meetings(id),
foreign key(participant_id) references participants(id)
)
Now it is easy to add and remove people to meetings be inserting or deleting rows or query meetings that e.g. have 4 or more participants.
A more common approach is to create a junction table for the meeting participants.
CREATE TABLE participants (
participant_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
Name TEXT NOT NULL,
Title TEXT NOT NULL
);
CREATE TABLE meetings (
meeting_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
Organizer TEXT NOT NULL,
StartTime DATE NOT NULL,
EndTime DATE NOT NULL
);
CREATE TABLE meeting_participants(
meeting_id INT NOT NULL,
participant_id INT NOT NULL,
PRIMARY KEY (meeting_id, participant_id),
FOREIGN KEY (meeting_id) REFERENCES meetings(meeting_id),
FOREIGN KEY (participant_id) REFERENCES participants(participant_id)
);
Which is then used to join the 2 tables.
For example:
SELECT m.*, p.*
FROM meeting_participants mp
JOIN meetings m USING(meeting_id)
JOIN participants p USING(participant_id)
WHERE m.Organizer = 'John Doe';

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.

There are no primary or candidate keys in the referenced table error

I have a problem with combining foreign keys to different tables. For example I made a table Customers and a Table invoices. I want a foreign key from Customers to invoices so I can get the name and everything of the Customer:
Create table code of Customers:
Create Table Customers
(
customerID int IDENTITY(100,1) NOT NULL,
customer_email varchar(30) NOT NULL,
username varchar(255) NOT NULL,
password varchar(50) NOT NULL,
firstname varchar(255) NOT NULL,
lastname varchar(255) NOT NULL,
insertion varchar(10) NULL,
phonenumber int NULL,
streetname varchar(20) NOT NULL,
number int NOT NULL,
zipcode varchar(10) NOT NULL,
city varchar(255) NOT NULL,
Constraint pk_Customers
PRIMARY KEY (customerID, customer_email, username)
)
Create table code of Invoices:
Create Table Invoices
(
invoiceID int IDENTITY(1000,1) NOT NULL,
customer_email varchar(30) NOT NULL,
customerID int NOT NULL,
creationdate datetime NOT NULL DEFAULT GETDATE(),
totalAmount decimal(5,2) NOT NULL,
Constraint pk_Invoices
PRIMARY KEY (invoiceID, customer_email,creationdate)
)
The foreign key code that I want to use:
ALTER Table Invoices
ADD Constraint fk_Customers_Invoices
FOREIGN KEY (customerID) REFERENCES Customers (customerID)
ON UPDATE CASCADE
ON DELETE NO ACTION
It throws the following error:
There are no primary or candidate keys in the referenced table 'Customers' that match the referencing column list in the foreign key 'fk_Customers_Invoices'.
How can I add my foreign key?
I think it's because your primary key is a composite key:
customerID, customer_email, username
This suggests that it is only the combination of these three fields that will uniquely identify a customer, and the foreign key would need to reference all three fields.
If customerID is unique, then it should be the primary key for the table and your foreign keys would be able to use it as a reference.
For what purpose are the other fields included in the primary key?
Since your Customers table defines this primary key:
Constraint pk_Customers
PRIMARY KEY (customerID, customer_email, username)
any table that wants to reference Customers must provide all three columns of that primary key. That's the way FK constraints work.
So from your Invoices tables, you must provide all 3 columns that make up the primary key of Customers - not just one. You can never refernce only part of a primary key - it's the whole key or nothing....
ALTER Table Invoices
ADD Constraint fk_Customers_Invoices
FOREIGN KEY (customerID) REFERENCES Customers (customerID)
ON UPDATE CASCADE
ON DELETE NO ACTION
You can either:
change the PK for Customers to be just CustomerID which would make a whole lot more sense since it's an identity column
or you could add the other two columns in the Customers PK to yoru table Invoices

What is the best way to enforce constraints across tables?

I often find myself running into situations like this one (which is contrived but illustrative of the problem):
CREATE TABLE customer (
id SERIAL PRIMARY KEY,
type TEXT
-- other columns...
);
CREATE TABLE product_order (
id SERIAL PRIMARY KEY,
customer_id INTEGER REFERENCES customer (id),
type TEXT REFERENCES customer (type), -- not actually legitimate
-- other columns...
CHECK (type = 'business')
);
Of course, the foreign key constraint on product_order.type doesn't work because customer.type is not UNIQUE or a primary key (and I can't use a CHECK CONSTRAINT on a column that only exists in another table). However, I would only like product_order entries for type = 'business' customers.
I could make customer.id and customer.type a composite primary key, but then any other tables that want to reference just customer.id must also reference customer.type unnecessarily.
What's the best approach in this situation?
EDIT: Forgot the foreign key constraint product_order.customer_id!
If you create a unique constraint on the customer.type you can reference it from the product_order table:
CREATE TABLE customer (
id SERIAL PRIMARY KEY,
type TEXT,
-- other columns...
constraint unique_cust_type unique (id, type) -- this makes the combination id/type "referencable"
);
CREATE TABLE product_order
(
id SERIAL PRIMARY KEY,
customer_id INTEGER,
type TEXT default 'business',
CHECK (type = 'business'),
foreign key (customer_id, type) references customer (id, type)
);
You could make a lookup table for types, and use the FKEY relationship to enforce
CREATE TABLE type (
id integer, PRIMARY KEY,
name TEXT
);
CREATE TABLE customer (
id SERIAL PRIMARY KEY,
type_id INTEGER, NOT NULL
-- other columns...
FOREIGN KEY (type_id) REFERENCES type(id)
);
CREATE TABLE product_order (
id SERIAL PRIMARY KEY,
type_id INTEGER, NOT NULL
-- other columns...
FOREIGN KEY (type_id) REFERENCES type(id)
);
You could access product_order as a view:
create view product_order_vw
as
select po.*
from product_order po
join customer c
on c.customerid = po.customerid
where c.type = 'business'
I think you need another type for the type. This sample is in MS SQL format:
CREATE TABLE TYPES (ctype varchar(10) NOT NULL PRIMARY KEY,
name varchar(50) not null
);
CREATE TABLE product_order (
id SERIAL PRIMARY KEY,
type varchar(10) NOT NULL REFERENCE TYPES (ctype) ,
....
);
So your product_order must have types defined in Types table. In your sample, you have only one entry 'business' but you can add as many as you want.

Pull value from another table

I want to create two tables that are related. The ITEM table has a primary key of ItemNumber and another important column of UnitPrice. The second Table has the UnitPrice again. I want to populate the UnitPrice column in the ORDER_LINE_ITEM table from the value in the ITEM UnitPrice column but am not sure how to do this. I need to have the UnitPrice in the second table so I can have a calculated column of the ExtendedPrice, unless there is a way to have a calculated column with values from another table.
CREATE TABLE ITEM
(
ItemNumber int IDENTITY(1,1) Not NULL PRIMARY KEY,
ItemName varchar(30) NOT NULL,
OrderDate datetime NOT NULL,
UnitPrice money NOT NULL,
Description text NOT NULL,
);
CREATE TABLE ORDER_LINE_ITEM
(
OrderId int FOREIGN KEY REFERENCES ORDERS(OrderID),
LineNumber int NOT NULL,
ItemNumber int FOREIGN KEY REFERENCES ITEM(ItemNumber) NOT NULL,
Quantity int Not NULL,
UnitPrice money NOT NULL,
ExtendedPrice money AS (Quantity * UnitPrice),
CONSTRAINT pk_OrderLineItem PRIMARY KEY (OrderID,LineNumber)
);
Lets start with the problem at hand, from what you are asking you will just need to give it the foreign key and reference ITEM(UnitPrice).
Insert into table ORDER_LINE_ITEM
CONSTRAINT FK_ORDER_LINE_ITEM_ITEM FOREIGN KEY(UNITPRICE) REFERENCE ITEM(UNITPRICE)
Second thing you need to work on is your overall coding style because you have two different ways of constraining foreign keys and primary keys. This will help with future coding work and if you are working with another coder on a project.