Insert multiple values with foreign key Postgresql - sql

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.

Related

How to UPDATE or INSERT in PostgreSQL

I want to UPDATE or INSERT a column in PostgreSQL instead of doing INSERT or UPDATE using INSERT ... ON CONFLICT ... because there will be more updates than more inserts and also I have an auto incrementing id column that's defined using SERIAL so it increments the id column everytime it tries to INSERT or UPDATE and that's not what I want, I want the id column to increase only if it's an INSERT so that all ids would be in an order instead
The table is created like this
CREATE TABLE IF NOT EXISTS table_name (
id SERIAL PRIMARY KEY,
user_id varchar(30) NOT NULL,
item_name varchar(50) NOT NULL,
code_uses bigint NOT NULL,
UNIQUE(user_id, item_name)
)
And the query I used was
INSERT INTO table_name
VALUES (DEFAULT, 'some_random_id', 'some_random_name', 1)
ON CONFLICT (user_id, item_name)
DO UPDATE SET code_uses = table_name.code_uses + 1;
Thanks :)
Upserts in PostgreSQL do exactly what you described.
Consider this table and records
CREATE TABLE t (id SERIAL PRIMARY KEY, txt TEXT);
INSERT INTO t (txt) VALUES ('foo'),('bar');
SELECT * FROM t ORDER BY id;
id | txt
----+-----
1 | foo
2 | bar
(2 Zeilen)
Using upserts the id will only increment if a new record is inserted
INSERT INTO t VALUES (1,'foo updated'),(3,'new record')
ON CONFLICT (id) DO UPDATE SET txt = EXCLUDED.txt;
SELECT * FROM t ORDER BY id;
id | txt
----+-------------
1 | foo updated
2 | bar
3 | new record
(3 Zeilen)
EDIT (see coments): this is the expected behaviour of a serial column, since they're nothing but a fancy way to use sequences. Long story short: using upserts the gaps will be inevitable. If you're worried the value might become too big, use bigserial instead and let PostgreSQL do its job.
Related thread: serial in postgres is being increased even though I added on conflict do nothing

Generate unique IDs in non-unique columns

Consider this table:
ex_table
| gid | val |
| --- | --- |
| 1 | v1 |
| 1 | v2 |
| 2 | v3 |
Notice that gid is the id-like column and not unique.
I want to be able to insert values into the table either by generating a unique gid or by specifying which one to use.
For example:
INSERT INTO ex_table (val)
SELECT --....
Should generate a unique gid, while
INSERT INTO ex_table (gid, val)
SELECT --....
Should use the provided gid.
Any way to do this?
You can do what you want to the letter of what you say by using overriding system value and an auto-generated column. For instance:
create table t (
gid int generated always as identity,
name varchar(255)
);
Then
insert into t (name) values ('abc');
insert into t (gid, name) overriding system value values (1, 'def')
will insert two rows with a gid value of 1.
Here is an example.
Just one caveat: Inserting your own value does not change the next value that is automatically generated. So, if you manually insert values that do not exist, then you might find that duplicates are later generated for them.
You can try something like this
CREATE SEQUENCE table_name_id_seq;
CREATE TABLE table_name (
gid integer NOT NULL DEFAULT nextval('table_name_id_seq'),
name varchar);
ALTER SEQUENCE table_name_id_seq
OWNED BY table_name.id;
OR SIMPLY
CREATE TABLE table_name(
gid SERIAL,
name varchar);
AND THEN TO INSERT
INSERT INTO fruits(gid,name)
VALUES(DEFAULT,'Apple');

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

uniqueness in an array datatype in psql

I have a table with the following structure:-
uniq_id | integer | not null default nextval('#########'::regclass)
user_id | integer | not null
team_type | text[] |
I have a unique index on user_id and team_type.
The column team_type will have values like 'R' and 'F'.
for instance ,for a user_id 1234,I have a team type inserted {R,F}.i do not want anyone to insert {R} for the same user.
One more example for my requirements:
If user_id 1234 has 2 entries as {R} AND {F}, I do not want anyone to insert a record as {R,F} for the same user.
I am in need of a constraint or unique index which can do this for me.
Thanks in advance.!

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.