SQL multiple insert select in one row - sql

I'm new in SQL and I'm trying to put values in my table that has two foreign keys.
CREATE TABLE ROOM
(
ROOM_NAME VARCHAR2(40 BYTE)
, PATIENT_ID NUMBER
, DOC_NAME VARCHAR2(50 BYTE)
)
LOGGING
TABLESPACE USERS
PCTFREE 10
INITRANS 1
STORAGE
(
INITIAL 65536
NEXT 1048576
MINEXTENTS 1
MAXEXTENTS UNLIMITED
BUFFER_POOL DEFAULT
)
NOPARALLEL;
ALTER TABLE ROOM
ADD CONSTRAINT DOC_ROOM FOREIGN KEY (DOC_NAME)
REFERENCES DOCTOR(DOC_NAME) ENABLE;
ALTER TABLE ROOM
ADD CONSTRAINT PATIENT_ROOM FOREIGN KEY (PATIENT_ID)
REFERENCES RECORD(ID) ENABLE;
Created using the left panel in SQL Developer. As you can see I have two foreign keys. I have no idea how to add values to the columns Patient_ID and Doc_Name.
So far what I did was just inserting one by one into the table, but that resulted in having three different rows.
What I got:
ROOM_NAME | PATIENT_ID | DOC_NAME
---------------------------------------
Emergency Room | NULL | NULL
NULL | 1 | NULL
NULL | NULL | Dr. John
What I want to get:
ROOM_NAME | PATIENT_ID | DOC_NAME
---------------------------------------
Emergency Room | 1 | Dr. John

insert will always create a new row (unless some constraint is violated).
To insert a row with all values at once, use this:
insert into room
(ROOM_NAME, PATIENT_ID, DOC_NAME)
values
('Emergency Room', 1, 'Dr. John');
If you want to change an already existing row, you need to use the UPDATE statement, e.g:
update room
set doc_name = 'Dr. House'
where room_name = 'Emergency Room'
and patient_id = 1;
Your room table is missing a primary key, you should add one that uniquely identifies rows in this table.

Nevermind. Saw the answer from another question.
insert into room values ('EmergencyRoom', (Select id from record where id = 1), (select doc_name from DOCTOR where doc_name = 'Dr. John'))

Related

What's wrong with my "on delete set default"?

I'm on Postgresql 13.
I want a table(rooms) that assume the default value of "1" if I delete from building which is the "parent table"
This is my sql code
DROP TABLE rooms;
DROP TABLE buildings;
CREATE TABLE buildings (
building_no INT default 1 primary key,
building_name VARCHAR(255),
address VARCHAR(255));
CREATE TABLE rooms (
room_no INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
room_name VARCHAR(255),
building_no INT default 1,
FOREIGN KEY (building_no) REFERENCES buildings (building_no) ON DELETE SET default );
I insert the values into the tables
insert into buildings values (1,'Building1','Street 33');
insert into buildings values (2,'Build-B','Street 34');
insert into rooms values (1,'Room 1',1);
insert into rooms values (2,'Room 2',2);
Then I delete from buildings
delete from buildings;
When I delete from buildings instead of make the default value of 1 as I ask it set the value NULL.
test=> select * from rooms;
room_no | room_name | building_no
---------+-----------+-------------
1 | Room 1 |
2 | Room 2 |
What's wrong in my sql code?
By deleting all of the records in buildings, the default value of 1 in the rooms table violates the FK constraint. Therefore, it's going to set it to NULL. If you were to delete all buildings EXCEPT building 1, you will not encounter the behavior you are describing.

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 );

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.

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.

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

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.