Setting Postgresql variable from result of insert for future use - sql

I have a table with a UUID key that is generated on insert. I need to use that key in multiple future inserts and want to store it in a variable.
CREATE TABLE table1 (UUID uuid PRIMARY KEY DEFAULT gen_random_uuid(), blah integer);
CREATE TABLE table2 (UUID uuid PRIMARY KEY DEFAULT gen_random_uuid(), UUID table1Uuid);
INSERT INTO TABLE1 (blah) values (1234);
INSERT INTO TABLE1 (blah) values (6789);
.....
INSERT INTO TABLE2 (table1Uuid theUuidMadeFromInsert1234);
I think I can make sure all the future inserts into TABLE2 are in the same session (maybe the same script) as those for TABLE1. Would like to do something like
uuid1234 = INSERT INTO TABLE1 (blah) values (1234);
uuid6789 = INSERT INTO TABLE1 (blah) values (6789);
.....
INSERT INTO TABLE2 (table1Uuid uuid1234);
but I can't get any syntax to work. I tried
create or replace function insertTable1 (junk integer)
RETURNS UUID
LANGUAGE plpgsql AS
$func$
declare
myUuid UUID;
BEGIN
insert into table1 (blah) values (junk) returning uuid into myUuid;
return myUuid;
END
$func$;
then doing something like set my.var.uuid = select insertTable1(1234) and insert into table2 (table1Uuid my.var.uuid) with various uses of current_setting
I have read many posts on SO, but can't find one that allows the value of the variable to outlast the function and be used

Is this what you want?
with t1 as (
insert into table1 (blah) values (1234), (6789)
returning *
)
insert into table2 (table1Uuid)
select uuid from t1 where blah = 1234;
The CTE inserts several rows in table1, then the outer query inserts in table2 the uuid that was generated for blah 1234.
Note that if you insert 1234 more than once in the CTE, the outer query will create as many rows in table2.
Alernatively, you can isolate the first insert in another CTE:
with
t1 as (insert into table1 (blah) values (1234) returning *),
t2 as (insert into table1 (blah) values (456), (789))
insert into table2 (table1Uuid) select uuid from t1

Related

Referencing inserted ID in multiple insert transactions in Postgres

I need to build a SQL query that must be able to insert data in a first table, grab the inserted ID and then use it as foreign key in the following tables.
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
SELECT * FROM inserted; -- this has the inserted id
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', ???)
So how do I reference the id in inserted in the secondTable insert?
You have completed this 80% percent, the complete SQL is:
with inserted as (
insert into first_table(name) values ('somename') returning id
)
insert into second_table(name, foreign_id) select 'someexternalname',id from inserted
You can do this:
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
INSERT INTO secondTable (name, foreign_id)
SELECT
'someexternalname',
id
FROM inserted;
You can try this:
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', (SELECT
MAX (id) FROM firstTable))

How to Lock multiple tables for Insert command in Sql

This is my table Structure
When I insert Data into the first table, it will have multiple entries in table 2
I am Using code
To Get ID
Select MAX(ID)+1 From Table1
To Insert Data
Insert Into Table1 Values('1','abc','add1');
Insert into table2 values('1','med','english');
Insert into table2 values('1','eng','english');
Code is working fine for single computer but when we used in application in multiple terminals it is inserting wrong data i.e. data of another id in table2
You need ensure that the ID column of table1 is an identity column and then do the following:
DECLARE #ID INT
INSERT table1 ([columns])
VALUES (...)
SELECT #ID = SCOPE_IDENTITY()
INSERT table2 (table1ID, [columns])
VALUES (#ID, ...)
You can read more about SCOPE_IDENTITY() here.
MAX(ID) will include ID values created by other processes, which is why your second insert is mixing up data.

Insert instead of from select and inserted data

I'm having trouble creating a trigger in a SQLite DB on a view that inserts values into 2 different tables and then inserts the "ID" values from those tables and values from the inserted data into a 3rd table. So basic idea is ....
CREATE TABLE [TBL1] (ID UNIQUE INT AUTOINCREMENT,VAL1);
CREATE TABLE [TBL2] (ID UNIQUE INT AUTOINCREMENT,VAL2);
CREATE TABLE [TBL3] (ID1 INT,ID2 INT,VAL3);
CREATE VIEW [v_TBL3] AS
SELECT (TBL1.VAL1,TBL2.VAL2,TBL3.VAL3)
FROM TBL3
INNER JOIN TBL1 ON TBL3.ID1 = TBL1.ID
INNER JOIN TBL2 ON TBL3.ID2 = TBL2.ID;
========== heres the problem ==========
CREATE TRIGGER [t_TBL3_INSERT] INSTEAD OF INSERT ON v_TBL3
BEGIN
INSERT OR IGNORE INTO [TBL1] (VAL1) VALUES NEW.VAL1;
INSERT OR IGNORE INTO [TBL2] (VAL2) VALUES NEW.VAL2;
INSERT INTO [TBL3] (ID1,ID2,v_TBL3.VAL3)
SELECT (TBL1.ID,TBL2.ID,VAL3)
FROM TBL1,TBL2,v_TBL3
WHERE TBL1.VAL1 = v_TBL3.VAL1 AND TBL2.VAL2 = v_TBL3.VAL2;
END;
I've looked on around on the net but I'm not finding quite what I need to get me there. Can someone help me get there?
You did not mention what your problem is, but when using proper SQL syntax, your schema would look like this:
CREATE TABLE TBL1 (ID INTEGER PRIMARY KEY AUTOINCREMENT, VAL1);
CREATE TABLE TBL2 (ID INTEGER PRIMARY KEY AUTOINCREMENT, VAL2);
CREATE TABLE TBL3 (ID1 INT, ID2 INT, VAL3);
CREATE VIEW v_TBL3 AS
SELECT TBL1.VAL1, TBL2.VAL2, TBL3.VAL3
FROM TBL3
INNER JOIN TBL1 ON TBL3.ID1 = TBL1.ID
INNER JOIN TBL2 ON TBL3.ID2 = TBL2.ID;
CREATE TRIGGER t_TBL3_INSERT
INSTEAD OF INSERT ON v_TBL3
BEGIN
INSERT OR IGNORE INTO TBL1 (VAL1) VALUES (NEW.VAL1);
INSERT OR IGNORE INTO TBL2 (VAL2) VALUES (NEW.VAL2);
INSERT INTO TBL3 (ID1, ID2, VAL3)
SELECT TBL1.ID, TBL2.ID, VAL3
FROM TBL1, TBL2, v_TBL3
WHERE TBL1.VAL1 = v_TBL3.VAL1 AND TBL2.VAL2 = v_TBL3.VAL2;
END;

Informix - update SET column with results from a subselect

I have a table with a collection column. I want to do a subselect which returns several integers and put the result in that collection column, however I can't find a syntax to do it through SQL. I did it by writing an SQL procedure which does the same thing (put results of SELECT in SET variable and return variable), however I'm trying to do the same without functions. Can it be done?
First, I create a temporary table:
CREATE TEMP TABLE table1 (
id INTEGER
, col2 SET(INT NOT NULL)
)
Then I fill it with test data:
INSERT INTO table1 (id) VALUES (1);
INSERT INTO table1 (id) VALUES (2);
And now this works:
UPDATE table1 SET col2 = SET{1,2};
...but I'm trying to do this and it doesn't work:
UPDATE table1 SET col2 = (SELECT id FROM table1) WHERE id = 1;
It returns this error:
[Error Code: -9632, SQL State: IX000] Value does not match the type of column (col2).
Manipulating SET types in pure SQL is a pain.
Your UPDATE is trying to assign an INTEGER to a SET OF INTEGER, and the error says "you can't do that".
You should be able to do:
UPDATE table1
SET col2 = SET { (SELECT id FROM table1 WHERE id = 1) }
WHERE id = 1;
However, I'm not sure what the correct modification is to get more than one value into the set; the inner WHERE is not there idly.
You can achieve this by using MULTISET and ITEM keyword
the following example will work:
CREATE TEMP TABLE table1 (
id INTEGER
,col2 MULTISET(INT NOT NULL)
);
INSERT INTO table1 (id) VALUES (1);
INSERT INTO table1 (id) VALUES (2);
UPDATE table1 SET col2 = MULTISET{1,2};
UPDATE table1
SET col2 = MULTISET(SELECT ITEM id FROM table1)
WHERE id = 1;
Be aware of the differences between SET and MULTISET
select set{1,2,1,3,1} from systables where tabid=1;
returns SET{1,2,3}
select multiset{1,2,1,3,1} from systables where tabid=1;
returns MULTISET{1,2,1,3,1}

How to automatically backup a ratio of a table based on one column?

I want to automatically backup a database so I have two databases, one with all data and the other with a ratio of each table -i.e. 20%- based on a column.
Here's my first try.
create table t1 (
id integer primary key,
val integer not null);
create table t2 (
id integer primary key,
val integer not null);
insert into t1 values (1,1000);
insert into t1 values (2,1000);
insert into t1 values (3,1000);
insert into t1 values (4,1000);
insert into t1 values (5,1000);
insert into t1 values (6,1000);
insert into t1 values (7,1000);
insert into t1 values (8,1000);
insert into t1 values (9,1000);
insert into t1 values (10,1000);
insert into t1 values (11,1000);
insert into t2
select id, val
from t1
where (val >= 1000)
and (rownum <= cast((0.2 * (select count(*) from t1)) as integer));