How to Insert Primary Value (PK) to Related Table (FK) - sql

I'm having trouble from Inserting 1 Primary Value (Increment) of TABLE to another TABLE (Foreign Key)
Table 1 has the Primary key of Student Number; if i enter values for last and first name from TABLE 1 then the student number will automatically giving it's own value because of Increment, and else if i entered from TABLE 2, I want the value of Student Number from TABLE i will increment even the value of Last and First name if TABLE 1 is NULL
Table 1
(PK)Student_# | Last_Name | First_Name
...........1...........|........a..........|..........b.......
...........2...........|........c..........|..........b.......
Table 2
(FK)Student_# | Year_Level | Section
...........NULL................|..........2nd Year......|.....C1 .........
...........NULL................|..........3rd Year......|.....D1 .........
Needed
(FK)Student_# | Year_Level | Section
..............1...................|..........2nd Year......|.....C1 .........
..............2...................|..........3rd Year......|.....D1 .........

It sounds to me that you need a primary key with an identity seed on table2 and also a foreign key to the student table:
(PK/Identity) Table2ID | (FK)Student_# | Year_Level | Section
This way you can insert the student_# when you insert the record into table 2 and also be able to give each row in table2 a unique identifier
CREATE TABLE Table2
(
Table2ID INT IDENTITY(1,1) PRIMARY KEY
,Student_# INT NOT NULL FOREIGN KEY REFERENCES Table1(Student_#)
,Year_Level NVARCHAR(255) --Use whatever data type you need
,Section NVARCHAR(255) --Use whatever data type you need
)
I have assumed you are using sql server as you have not specified in your question. You may need to change this query for a different RDBMS.

Related

how to add primary key column without truncating table in oracle

We have received a requirement where we need to add a new column to primary key where table is having records:
alter table customer add (bill_to number(9,0),
CONSTRAINT CUSTOMER_PK PRIMARY KEY (bill_to));
In this case after it adds the new column to the table by default null values will be stored if table is having records, technically we cannot make this column a primary key, either table shouldn't have the records or we have to truncate the table, but we cannot do it in production,
is there any other way to deal this? please suggest.
You can do it in 2 statements by first adding an IDENTITY column and second making it the PRIMARY KEY:
So, if you have the table:
CREATE TABLE customer ( value ) AS
SELECT 'A' FROM DUAL CONNECT BY LEVEL <= 3 UNION ALL
SELECT 'B' FROM DUAL CONNECT BY LEVEL <= 2;
Then you can:
ALTER TABLE customer ADD (
bill_to NUMBER(9,0)
GENERATED ALWAYS AS IDENTITY
);
ALTER TABLE customer ADD CONSTRAINT CUSTOMER_PK PRIMARY KEY ( bill_to );
And the table becomes:
VALUE | BILL_TO
:---- | ------:
A | 1
A | 2
A | 3
B | 4
B | 5
db<>fiddle here
You can not do it in a single statement.
You can achieve it using the three-step process as follows:
ALTER TABLE CUSTOMER ADD BILL_TO NUMBER(9, 0);
UPDATE CUSTOMER
SET BILL_TO = SEQ OR ANYOTHER LOGIC FOR UNIQUE VALUE FOR EACH ROW;
ALTER TABLE CUSTOMER ADD CONSTRAINT CUSTOMER_PK PRIMARY KEY ( BILL_TO );

How to update unique table row numbers before inserting new row at existing position

SQL table:
id | name
----+--------
1 | apple
2 | orange
3 | apricot
The id is primary key, unique, could be SERIES. The goal is to insert new row where id equals 2 and shift existing row numbers below, that is 2 and 3, to 3 and 4 position.
I have tried shift rows before inserting new row:
"UPDATE some_table SET id = id + 1 WHERE id >= id"
but an error occurred:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "some_table_pkey"
Detail: Key (id)=(3) already exists.
Is there some effective way to do such an operation?
The table should look like this after update:
id | name
----+--------
1 | apple
2 | cherry
3 | orange
4 | apricot
While I think the attempt is futile, you can achieve that by marking the primary key constraint as deferrable:
CREATE TABLE some_table
(
id int,
name text
);
alter table some_table
add constraint pk_some_table
primary key (id)
deferrable initially immediate; --<< HERE
In that case the PK constraint is evaluated at per statement, not per row.
Online example: https://rextester.com/JSIV60771
update Names
set id=id+1
where id in
(select id from Names where id>=2 order by id desc);
Here first you can update the id's and then you can insert
insert into Names (id,name) values(2,'cheery')

Insert multiple values with foreign key Postgresql

I am having trouble figuring out how to insert multiple values to a table, which checks if another table has the needed values stored. I am currently doing this in a PostgreSQL server, but will be implementing it in PreparedStatements for my java program.
user_id is a foreign key which references the primary in mock2. I have been trying to check if mock2 has values ('foo1', 'bar1') and ('foo2', 'bar2').
After this I am trying to insert new values into mock1 which would have a date and integer value and reference the primary key of the row in mock2 to the foreign key in mock1.
mock1 table looks like this:
===============================
| date | time | user_id |
| date | integer | integer |
| | | |
And the table mock2 is:
==================================
| Id | name | program |
| integer | text | test |
Id is a primary key for the table and the name is UNIQUE.
I've been playing around with this solution https://dba.stackexchange.com/questions/46410/how-do-i-insert-a-row-which-contains-a-foreign-key
However, I haven't been able to make it work. Could someone please point out what the correct syntax is for this, I would be really appreciative.
EDIT:
The create table statements are:
CREATE TABLE mock2(
id SERIAL PRIMARY KEY UNIQUE,
name text NOT NULL,
program text NOT NULL UNIQUE
);
and
CREATE TABLE mock1(
date date,
time_spent INTEGER,
user_id integer REFERENCES mock2(Id) NOT NULL);
Ok so I found an answer to my own question.
WITH ins (date,time_spent, id) AS
( VALUES
( '22/08/2012', 170, (SELECT id FROM mock3 WHERE program ='bar'))
)
INSERT INTO mock4
(date, time_spent, user_id)
SELECT
ins.date, ins.time_spent, mock3.id
FROM
mock3 JOIN ins
ON ins.id = mock3.id ;
I was trying to take the 2 values from the first table, match these and then insert 2 new values to the next table, but I realised that I should be using the Primary and Foreign keys to my advantage.
I instead now JOIN on the ID and then just select the key I need by searching it from the values with (SELECT id FROM mock3 WHERE program ='bar') in the third row.

Build correct logical db

I use 4 table in database.
Example:
Create table applicant(
Id int not null primary key,
IdName integer
idSkill integer,
idContact integer
Constraint initial foreign key (idName) References Initiale(id)
CONSTRAINT contacT foreign key (idContact) References contact(id)
CONSTRAINT Skills foreign key (idSkill) references skill(id))
Create table Initiale(
Id int not null primary key,
firstname text,
middlename text)
Create table contact(
Id int not null primary key,
phone text,
email text)
Create tabke Skills(
Id int not null primary key,,
Nane text)
I want insert data promptly in 4 table,but i not understand, what get id and insert in applicant.
Create tabke Skills ..... will fail. You should use Create table Skills.
Nor should you have Id int not null primary key,, (two commas), this would fail.
You should very likely be using Id INTEGER PRIMARY KEY not Id int not null primary key.
That is because generally an Id column should be a unique identifier of the row. With SQLite INTEGER PRIMARY KEY has a special meaining whilst INT PRIMARY KEY does not.
That is, if INTEGER PRIMARY KEY is used then the column will be an alias of the rowid column which has to be a unique signed 64 bit integer and importantly if no value is provided when inserting a row then SQLite will assign a unique integer. i.e. the all important Id.
This Id will initially be 1, then likely 2, then likely 3 and so on, although there is no guarantee that the Id will be monotonically increasing.
There are additional errors, mainly comma's omitted. The following should work :-
CREATE TABLE IF NOT EXISTS applicant(
Id INTEGER PRIMARY KEY,
IdName integer,
idSkill integer,
idContact integer,
Constraint initial foreign key (idName) References Initiale(id),
CONSTRAINT contacT foreign key (idContact) References contact(id),
CONSTRAINT Skills foreign key (idSkill) references Skills(id));
Create table IF NOT EXISTS Initiale(
Id INTEGER PRIMARY KEY,
firstname text,
middlename text);
Create table IF NOT EXISTS contact(
Id INTEGER PRIMARY KEY,
phone text,
email text);
Create table IF NOT EXISTS Skills(
Id INTEGER PRIMARY KEY,
Nane text);
You could then insert data along the lines of :-
INSERT INTO Initiale (firstname,middlename) -- Note absence of Id so SQLite will generate
VALUES
('Fred','James'), -- very likely id 1
('Alan','Roy'), -- very likely id 2
('Simon','Gerorge')-- very likely id 3
;
INSERT INTO contact -- alternative way of getting Id generated (specify null for Id)
VALUES
(null,'0123456789','email01#email.com'), -- very likely id 1
(null,'0987654321','email02#email.com'), -- very likely id 2
(null,'3333333333','email03.#email.com') -- very likely id 3
;
INSERT INTO Skills (Nane)
VALUES
('Skill01'),('Skill02'),('Skill03') -- very likely id's 1,2 and 3
;
INSERT INTO applicant (IdName,idSkill,idContact)
VALUES
-- First applicant
(2, -- Alan Roy
3, -- Skill 3
1), -- Contact 0123456789 )
-- Second Applicant
(3, -- Simon George
3, -- Skill 3
2), -- Contact 0987654321 )
-- Third Applicant
(2, -- Alan Roy again????
1, -- Skill 1
3), -- contact 3333333333)
(1,1,1) -- Fred James/ Skill 1/ Contact 0123456789
--- etc
;
Noting that Rows on the Initiale, Contact and Skills table MUST exists before insertions can be made into the Applicant table.
You could then run a query such as :-
SELECT * FROM applicant
JOIN Initiale ON Initiale.Id = idName
JOIN contact ON contact.Id = idContact
JOIN Skills ON Skills.Id = idSkill
This would result in (using the data as inserted above) :-

Foreign key from a NON audit trail table to an audit trail table

In an existing schema I am introducing audit trail/milestone support only for one of the tables. For discussing the question we'll use following simplified toy example for better illustration of a question.
DEPARTMENT
ID | NAME | CREATED_TS | MODIFIED_TS | VERSION
1 | "ABC" | 11/20/2015 | 12/1/9999 | 1
Now when every time update request for department record for id=1 comes in, system does following. Basically each update is an INSERT - which changes existing record's MODIFIED_TS to the time UPDATE request came in and latest record's MODIFIED_TS always remains as 12/1/9999 (a.k.a INFINITY TIMESTAMP)
Say updating ID=1 record where name was changed , following is what it looks like in db.
DEPARTMENT
ID | NAME | CREATED_TS | MODIFIED_TS | VERSION
1 | "ABC" | 11/20/2015 | 11/22/2015 | 1
1 | "XYZ" | 11/22/2015 | 12/1/9999 | 2
Now assume there is an existing EMPLOYEE table with DEPT_ID as a foreign key. Note that EMPLOYEE table doesn't have an audit trail requirement so there is no INFINITY timestamp or VERSIONing concept there. EMPLOYEE table looks like as below
EMPLOYEE
ID | NAME | AGE | DEPT_ID
1 | "John" | 31 | 1
Everything was fine in terms of EMPLOYEE having a FK relationship with DEPT where DEPT had ID as a PK before. Now DEPARTMENT table's PK is changed to a composite PK (ID,VERSION)
After these schema changes for DEPARTMENT table to create auit trail for its data, FK in EMPLOYEE will have to somehow create a FK in such a way where not only DEPT_ID but also include INFINITY timestamp (MODIFIED_TS ) of DEPT record into it because EMPLOYEE will always be referring the latest DEPT record (requirement)
What's the best way to change EMPLOYEE table's FK for pointing to the most current record in DEPT table?
This is a terrible data-modelling hack to solve your problem; don't try this at home...
Since the PK for department is {id, modified_ts}, the FK from employee must also be composite (or it could point to another unique set of columns).
So the solution is to give it what it wants: a column with a constant value of 'infinity'. ('infinity' is a valid value for dates and timestamps in postgres, you don't need to invent your own sentinel values)
CREATE TABLE department
( id INTEGER NOT NULL
, name varchar
, created_ts timestamp
, modified_ts timestamp
, version integer not null default 0
, PRIMARY KEY (id, modified_ts)
);
INSERT INTO department (id, name, created_ts, modified_ts, version) VALUES
(1 , 'ABC', '2015-11-20' , '2015-11-22' , 1) ,
(1 , 'XYZ', '2015-11-22' , 'infinity' , 2) ;
-- CREATE UNIQUE INDEX ON department (id) WHERE modified_ts = 'infinity'::timestamp;
-- Now assume there is an existing EMPLOYEE table with DEPT_ID as a foreign key. Note that EMPLOYEE table doesn't have an audit trail requirement so there is no INFINITY timestamp or VERSIONing concept there. EMPLOYEE table looks like as below
CREATE TABLE employee
( id INTEGER NOT NULL PRIMARY KEY
, name varchar
, age integer not null default 0
, modified_ts timestamp NOT NULL DEFAULT 'infinity'::timestamp CHECK (modified_ts = 'infinity'::timestamp)
, dept_id INTEGER NOT NULL
, FOREIGN KEY (id,modified_ts)
REFERENCES department(id, modified_ts)
);
INSERT INTO employee(id ,name,age,dept_id) VALUES
(1 , 'John' , 31 , 1);
a FK really SHOULD NOT point to a moving target
for the above to work, the FK constraint will need DEFERRABLE INITIALLY DEFERRED
but in practice you should use stable keys, (and move the trail to a separate table)
and in real life, both employee and department should allow history, and so should their (M:N) junction table.