I am working on a database and I need to add indexes to it.
I have a table like this.
CREATE TABLE Customers
(
Id SERIAL PRIMARY KEY,
FirstName CHARACTER VARYING(30),
LastName CHARACTER VARYING(30),
Email CHARACTER VARYING(30),
Age INTEGER
);
CREATE UNIQUE INDEX customers_idx ON Customers (Id);
Do I need to add indexes to it if there is a field with the SERIAL attribute?
As per the documentation,
Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key, and will force the column(s) to be marked NOT NULL.
So no, in this case you do not need to create the customers_idx yourself, because you defined that column as a primary key. However, the serial type itself (if the column isn't a primary key or unique) does NOT automatically come with an index.
Related
in postgres, just checking if we need to index all columns of composite primary key
CREATE TABLE BOOK_TYPE(
ID TEXT NOT NULL,
TYPE TEXT NOT NULL,
LABELS HSTORE NOT NULL,
CONSTRAINT BOOK_TYPE_PKEY PRIMARY KEY (ID,TYPE)
);
should I have to index ID and type separately?
You don't need to create any extra index unless you happen to need it to speed up a query. The primary key will automatically create a unique index on (id, type), and that is all that is needed to guarantee consistency.
Based on the documentation it's pretty straightforward how to prevent any overlapping reservations in the table at the same time.
CREATE EXTENSION btree_gist;
CREATE TABLE room_reservation (
room text,
during tsrange,
EXCLUDE USING GIST (room WITH =, during WITH &&)
);
However, when you have multiple resources that can be reserved by users, what is the best approach to check for overlappings? You can see below that I want to have users reserve multiple resources. That's why I'm using the junction table Resources_Reservations. Is there any way I can use EXCLUDE in order to check that no resources are reserved at the same time?
CREATE TABLE Users(
id serial primary key,
name text
);
CREATE TABLE Resources(
id serial primary key,
name text
);
CREATE TABLE Reservations(
id serial primary key,
duration tstzrange,
user_id serial,
FOREIGN KEY (user_id) REFERENCES Users(id)
);
CREATE TABLE Resources_Reservations(
resource_id serial,
reservation_id serial,
FOREIGN KEY (resource_id) REFERENCES Resources(id),
FOREIGN KEY (reservation_id) REFERENCES Reservations(id),
PRIMARY KEY (resource_id, reservation_id)
);
I think what you want is doable with a slight model change.
But first let's correct a misconception. You have foreign key columns (user_id, resource_id, etc) defined as SERIAL. This is incorrect, they should be INTEGER. This is because SERIAL is not actually a data type. It is a psuedo-data type that is actually a shortcut for: creating a sequence, creating a column of type integer, and defining the sequence created as the default value. With that out of the way.
I think your Resources_Reservations is redundant. A reservation is by a user, but a reservation without something reserved would just be user information. Bring the resource_id into Reservation. Now a Reservation is by a user for a resource with a duration. Everything your current model contains but less complexity.
Assuming you don't have data that needs saving, then:
create table users(
id serial primary key,
name text
);
create table resources(
id serial primary key,
name text
);
create table reservations(
user_id integer
resource_id integer
duration tstzrange,
foreign key (user_id) references users(id)
foreign key (resource_id) references resources(id),
primary key (resource_id, user_id)
);
You should now be able to create your GIST exclusion.
PostgreSQL/PGAdmin4 ERROR: there is no unique constraint matching given keys for referenced table
This is the ‘schema’ I’m trying to code into PGAdmin4/Postgresql:
http://i.imgur.com/xPEu8Sh.jpg
I was able to convert all tables, except “QUALIFICATIONS”.
I tried to process the following query:
create table REGISTRATION(
StudentID int,
SectionNo int,
Semester varchar(16),
foreign key(StudentID) references Student(StudentID),
foreign key (SectionNo, Semester) references Section(SectionNo, Semester),
primary key(studentID, SectionNo, Semester)
);
I received the following message:
ERROR: there is no unique constraint matching given keys for referenced table "section"
These are the foreign and primary I have in the table SECTION
PKEY: i.imgur.com/BcUNKug.jpg
FKEY: i.imgur.com/D8B8hRW.jpg
Code of SECTION table:
CREATE TABLE class_scheduling_01.section
(
sectionno integer NOT NULL,
semester character varying(16) COLLATE pg_catalog."default" NOT NULL,
courseid character varying(16) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT section_pkey PRIMARY KEY (sectionno, semester, courseid),
CONSTRAINT section_sectionno_key UNIQUE (sectionno),
CONSTRAINT section_courseid_fkey FOREIGN KEY (courseid)
REFERENCES class_scheduling_01.course (courseid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
I additionally ran the command: ALTER TABLE section ADD UNIQUE (sectionno);
Since none of the attributes seemed to be repeating itself.
Despite all this I’m getting:
ERROR: there is no unique constraint matching given keys for referenced table "section" Query returned successfully in 642 msec.
Edit: I've gone back to the COURSE table and made courseID a unique constraint. I still get the same message. SECTION table has a composite primary key made up of 3 columns. As seen in the first picture linked, out of all the values, only SECTION.sectionno is the only column with unique/non-repeating values.
2nd edit: I decided to create the table "REGISTRATION" one step at a time, and make the foreign keys last with alter table command.
I was able to make the columns StudentID andd SectionNo foreign keys to their respective columns. When I tried to make REGISTRATION.semester a foreign key to SECTION.semester I got the error message again.
alter table REGISTRATION add foreign key (semester) references section(semester);
As seen in the image I linked Semester value, is repeated; despite this, am I still required to make it unique? Or do I make a unique command assigning all 3 columns (of SECTION) together as unique, instead of just 1? If so, how?
This
foreign key (SectionNo, Semester) references Section(SectionNo, Semester),
requires that there be a unique constraint on the pair of columns SectionNo and Semester.
CREATE TABLE class_scheduling_01.section
(
sectionno integer NOT NULL,
semester character varying(16) COLLATE pg_catalog."default" NOT NULL,
courseid character varying(16) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT section_pkey PRIMARY KEY (sectionno, semester, courseid),
CONSTRAINT section_sectionno_key UNIQUE (sectionno),
CONSTRAINT section_courseid_fkey FOREIGN KEY (courseid)
REFERENCES class_scheduling_01.course (courseid) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
-- Unique constraint on the pair
CONSTRAINT your_constraint_name UNIQUE (SectionNo, Semester)
);
That change should let these SQL statements succeed. I didn't check to see whether that's a good idea.
SQL is case insensitive.
I understand what you mean, but this is a bad way to think about it.
PostgreSQL folds unquoted identifiers to lowercase. So PostgreSQL would treat the identifiers SQL, Sql, and sql as if they were all sql. A quoted or delimited identifier, like "Select" always refers to either a table or a column; it's never interpreted as a keyword. Quoted identifiers are case-sensitive. You can't successfully refer to the table "Select" as select.
I'm not sure which indexes postgresql AUTOMATICALLY creates; I think it will create one on Book(ibsn), because its the primary key, and also Book(title), because its a candidate key... but I'm not sure if postgres will automatically create a combined index on all key attributes Book(ibsn, title). Also, would it create any other indexes automatically?
CREATE TABLE Book (
isbn INTEGER CONSTRAINT B_ISBN CHECK (ISBN BETWEEN 1 AND 2000),
title VARCHAR(200) CONSTRAINT B_TITLE NOT NULL UNIQUE,
author VARCHAR(50) CONSTRAINT B_AUTH NOT NULL,
cost FLOAT DEFAULT 0.00,
lent_date DATE,
returnDate DATE,
times_lent INTEGER,
sectionID SMALLINT,
CONSTRAINT BOOK_PRIME PRIMARY KEY (isbn),
CONSTRAINT BOOK_SECT FOREIGN KEY (sectionID) REFERENCES Section(sectionID) ON DELETE CASCADE
);
Postgres will automatically create indexes only for:
primary keys: Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key
unique constraints: Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint
In your case, Postgres creates one unique index on the column isbn and one unique index on the column unique because you declared each column individually to be unique, not the combination of both.
No other indexes will be created automatically.
I have a table where part of the primary key is a foreign key to another table.
create table player_result (
event_id integer not null,
pub_time timestamp not null,
name_key varchar(128) not null,
email_address varchar(128),
withdrawn boolean not null,
place integer,
realized_values hstore,
primary key (event_id, pub_time, name_key),
foreign key (email_address) references email(address),
foreign key (event_id, pub_time) references event_publish(event_id, pub_time));
Will the index generated for the primary key suffice to back the foreign key on event_id and pub_time?
Yes.
Index A,B,C
is good for:
A
A,B
A,B,C (and any other combination of the full 3 fields, if default order is unimportant)
but not good for other combinations (such as B,C, C,A etc.).
It will be useful for the referencing side, such that a DELETE or UPDATE on the referenced table can use the PRIMARY KEY of the referencing side as an index when performing checks for the existence of referencing rows or running cascade update/deletes. PostgreSQL doesn't require this index to exist at all, it just makes foreign key constraint checks faster if it is there.
It is not sufficient to serve as the unique constraint for a reference to those columns. You couldn't create a FOREIGN KEY that REFERENCES player_result(event_id, pub_time) because there is no unique constraint on those columns. That pair can appear multiple times in the table so long as each pair has a different name_key.
As #xagyg accurately notes, the unique b-tree index created by the foreign key reference is also only useful for references to columns from the left of the index. It could not be used for a lookup of pub_time, name_key or just name_key, for example.