PostgreSQL simple key vs composite key - postgresql

We are going to store in PostgreSQL some info about organizations (in fact that is some entity, but I say "organization" just for clarity of structure). Each organization has 6 sublevels. First level - departments, second (inside departments) - sections etc. Each department (just like section and other) can have a unique name. We are thinking about 7 tables like
Table organizations
id (primary key) -- organization name
Table level_1
id (primary key) -- organization_id (foreign key) -- name
Table level_2
id (primary key) -- level_1_id (foreign key) -- name
etc
We suppose that on low levels (2-6) we can have thousands ob objects for each level.
The question is how we should construct the primary key - as simple key (like described above) or composite key. F.i.
Table level_1
id (primary key) -- organization_id (primary key) -- name
Table level_2
id (primary key) -- level_1_id (primary key) -- name
etc
What key type is better (first of all, faster for SELECT queries) and why?
Thank you.

IMHO, it's a bad design.
What will you do if you need to add a level ?
You'll need to add a table
You'll need to modify all your code, views...
Not very scalable...
You should have only one table.
Organizations
Id Parent_Id Name
Data Sample:
1 NULL Corporation
2 1 Division_1
3 1 Division_2
4 2 Dept_1_of_Division_1
5 2 Dept_2_of_Division_1
6 3 Dept_1_of_Division_2
To query this table, you would need to use WITH RECURSIVE

Related

database table for scheduling system

Please correct me if I design it wrong. I need to design 3 tables as follow:
students : id, name
sections : id, student_id, s_name
schedules: id, section_id, c_name
And here are requirements:
There are students, and each of those student has sections, and each of those sections has schedule.
The relationship from students to sections, sections to schedules is 1 to many
student can have many sections
section can have only 1 student / section can have many schedules
schedule can have only 1 section
========= Here are my tables: =====
students
id --> primary and auto increment
name
sections
id --> primary and auto increment
student_id --> foreign key reference to id of students table
s_name
schedules
id --> primary and auto increment
section_id --> foreign key reference to id of sections table
c_name
I would appreciate any helps and many thanks.
Yes, your schema seems to be BCNF normalized, but it does not fulfil all the given requirement. I would change a few things to make it more intuitive.
2. Sections Table:
section_id -> primary, auto increment
student_id -> Foreign Key to students.id
Explanation: Section ID is one to one with student, but student is one to many with section.
3. SectionNames Table:
section_id -> primary and foreign key, from section table.
section_name -> String, name of section.
Explanation : You would add this if you need to store s_name, like you're doing right now.
4. Schedule Table:
class_id -> Primary, auto increment key
section_id -> Foreign key, sections table.
Explanation: Schedule's (Class's) one to one relation to section, and sections one to many relation to classes.
5. ScheduleName Table:
class_id -> Primary, and foreign key to schedule table.
class_name -> String
Explanation: Stores c_name as per your table schema.

Cannot create foreign key constraint on table w/ inheritance

I'm trying to add a foreign key constraint to an existing table:
ALTER TABLE address
ADD FOREIGN KEY(company_id)
REFERENCES company(company_id) ON DELETE CASCADE DEFERRABLE;
That fails with:
ERROR: insert or update on table "address" violates \
foreign key constraint "address_company_id_fkey"
DETAIL: Key (company_id)=(83376) is not present in table "company".
Yet the company table does have that key:
DB=> SELECT company_id FROM company WHERE company_id = 83376;
company_id
------------
83376
(1 row)
I suspect that this is due to table inheritance (old database, very historic reasons), company is a base table and one derived table is the person table. Which is the one containing the actual key:
DB=> SELECT company_id FROM person WHERE company_id = 83376;
company_id
------------
83376
(1 row)
I'm specifically targeting the base table (assuming it contains the data of all derived tables) because the address rows refer to different derived tables.
Is there a way to make that work?
Or as an alternative, kinda even better, is there a way to have foreign keys targeting specific derived tables?

Constraint to avoid combination of foreign keys

I've here a problem that I couldn't find a proper solution on my researches, maybe it's because I couldn't find out the exact terms to search for it, so if this is a duplicate I will delete it.
My problem is I want to know if it is possible to avoid a combination of data between two fields. I will show the structure and the kind of data I want to avoid. It will be easier to understand.
Table_A Table_B
------------------------ -------------------------------
id integer (PK) id integer (PK)
description varchar(50) title varchar(50)
id1_fromA (FK A->id)
id2_fromA (FK A->id)
I'm trying to validate the following data on table Table_B (combination is between id1_fromA and id2_fromA)
id title id1_fromA id2_fromA
1 Some Title 1 2 --It will be permmited
2 Some other 1 2 --It is a duplicate NOT ALLOWED
3 One more 1 1 --It is equals NOT ALLOWED
4 Another 2 1 --It is same as registry id 1 so NOT ALLOWED
5 Sample data 3 2 --It is ok
With above data I can easily solve the problem for registry ID=2 with
ALTER TABLE table_B ADD CONSTRAINT UK_TO_A_FKS UNIQUE (id1_fromA, id2_fromA);
And the problem for registry ID=3 with
ALTER TABLE table_B ADD CONSTRAINT CHK_TO_A_FKS CHECK (id1_fromA != id2_fromA);
My Problem is with the registry ID=4 I want to avoid such duplicate of combination as 1,2=2,1. Is it possible to do it with a CONSTRAINT or an INDEX or an UNIQUE or I will need to create a trigger or a procedure to do so?
Thanks in advance.
You can't do this with a unique constraint, but you can do this with a unique index.
create unique index UK_TO_A_FKS
on table_b (least(id1_froma, id2_froma), greatest(id1_froma, id2_froma));

GUID. and automatic id as primary key in SQL databases

SELECT COUNT(*) FROM table_name;
My algorithm is:
check count
count+1 is the new primary key starting point
Then keep on incrementing before every insert operation
But what is this GUID? Does SQL Server provide something where it automatically generates and incremented primary key?
There are 3 options
CREATE TABLE A
(
ID INT IDENTITY(1,1) PRIMARY KEY,
... Other Columns
)
CREATE TABLE B
(
ID UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,
... Other Columns
)
CREATE TABLE C
(
ID UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
... Other Columns
)
One reason why you might prefer C rather than B would be to reduce fragmentation if you were to use the ID as the clustered index.
I'm not sure if you're also asking about IDENTITY or not- but a GUID is a unique identifier that is (almost) guaranteed to be unique. It can be used on primary keys but isn't recommended unless you're doing offline work or planning on merging databases.
For example a "normal", IDENTITY primary key is
1 Jason
2 Jake
3 Mike
which when merging with another database which looks like
1 Lisa
2 John
3 Sam
will be tricky. You've got to re-key some columns, make sure that your FKs are in order, etc. Using GUIDs, the data looks like this, and is easy to merge:
1FB74D3F-2C84-43A6-9FB6-0EFC7092F4CE Jason
845D5184-6383-473F-A5D6-4DE98DBFBC39 Jake
8F515331-4457-49D0-A9F5-5814EE7F50BA Mike
CE789C89-E01F-4BCE-AC05-CBDF10419E78 Lisa
4D51B568-107C-4B63-9F7F-24592704118F John
7FA4ED64-7356-4013-A78A-C8CCAB329954 Sam
Note that a GUID takes a lot more space than an INT, and because of this it's recommended to use an INT as a primary key unless you absolutely need to.
create table your table
(id int indentity(1,1) primary key,
col1 varchar(10)
)
will automatically create the primary key for you.
Check GUID in the T-SQL, don't have it at hand right now.
The issue with using count , then count +1 as key, is that were you to delete a record from the middle, you would end up with a duplicate key generated.
EG:
Key Data
1 A
2 B
3 C
4 D
now delete B (count becomes 3), and insert E. This tries to make the new primary key as 4, which already exists.
Key Data
1 A
3 C
4 D <--After delete count = 3 here
4 E <--Attempted insert with key 4
You could use primary key and auto increment to make sure you don't have this issue
CREATE TABLE myTable
(
P_Id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (P_Id)
)
Or you could use GUID. How GUIDs work is by creating a 128 bit integer (represented as a 32 char hex string)
Key Data
24EC84E0-36AA-B489-0C7B-074837BCEA5D A
.
.
This results in 2^128 possible values (reaaally large), so the chances of similar values created by one computer is extremely small. Besides there are algorithms to help try and ensure that this doesn't happen. So GUID are a pretty good choice for a key as well.
As for whether you use an integer or a GUID, is usually dependent on application, policy etc.

Foreign key refering to primary keys across multiple tables?

i have three tables say city,state and road
1) city -> city_id(PK),name
2) state-> Stt_id(PK),name
3) Road-> Edge_id(PK), Admin_id(FK)
where Admin_id refers to city_id and Stt_id both.
This is done because the tables are too huge.
say city_id contains 1,2,3
and Stt_id contains 4,5,6
now if i am inserting 1,2,3,4,5,6 in admin_id it is throuing an error .. what is the solution of my problem,
regards
sanjay
Create an admin table that holds an entry for every city and state, using its admin_ids as city_id and stt_id in their respective tables. Then declare foreign keys on city_id, stt_id and road.admin_id, referencing admin.admin_id (retaining all the existing PKs, of course).