db2 query insert from another table - db2

I have a table product(id_product , name );
I have another one: productHistory (id_H , id_product , name);
I wanna create a query (db2) to insert all the rows of product in productHistory;
I have a sequence product_history_seq
I wanna do something like that:
insert into productHistory
(id_h , , id_product , name)
values ( product_history_seq.nextval,..
Or,
select (id_product , name) from product
What's the correct query?

I believe you are looking for:
insert into productHistory
( id_h
, id_product
, name
)
select next value for product_history_seq
, id_product
, name
from product
;

Make id_h auto increment and try this
insert into productHistory ( id_product , name) values (select id_product , name from product );
id_h will auto-increment no need to put it in query
Hope it will help

INSERT INTO productHistory (id_h, id_product, name)
(SELECT
product_history_seq.nextval,
id_product,
name
FROM product);
That works

"insert into yourtableone select default, val1, val2 from yourtabletwo" and declare the id as genereated by default

Related

Postgresql: 'upserting' into two tables using the same id with a unique constraint

I have two tables, one containing all the hot columns and one the static ones. The static table has an unique constraint. When the conflict on the unique constraint triggers only the hot columns in the other table should be updated using the the id from the static table.
For better clarity some code:
CREATE TABLE tag (
id bigserial PRIMARY KEY
, key text
, value text
-- UNIQUE (key, value) -- ?
);
CREATE TABLE tag_hotcolumns (
id bigserial PRIMARY KEY
, hot text
, stuff text
);
with s as (
select id, "key", "value"
from tag
where key = 'key1' and value = 'value1'
), i as (
insert into tag ("key", "value")
select 'key1', 'value1'
where not exists (select 1 from s)
returning id
)
select id
from i
union all
select id
from s
The second block works fine, but I can't get the returned id into the insert statement for the tag_hotcolumns...
I tried:
insert into tag_attributes (with s as (
select id, "key", "value"
from tag
where key = 'key1' and value = 'value1'
), i as (
insert into tag ("key", "value")
select 'key1', 'value1'
where not exists (select 1 from s)
returning id
)
select id, 'hot1', 'stuff1'
from i
union all
select id
from s);
And that gives me "WITH clause containing a data-modifying statement must be at the top level
LINE 5: ), i as ("
Any help would be greatly apreciated :)
dwhitemv from stackexchange helped me solve this. The solution you can find here:
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=f72cae495e6eed579d904a5c7b48f05b

Coalesce sentence containing an insert into clause fails in PostgreSQL

This is my trivial test table,
create table test (
id int not null generated always as identity,
first_name. varchar,
primary key (id),
unique(first_name)
);
As an alternative to insert-into-on-conflict sentences, I was trying to use the coalesce laziness to execute a select whenever possible or an insert, only when select fails to find a row.
coalesce laziness is described in documentation. See https://www.postgresql.org/docs/current/functions-conditional.html
Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; that is, arguments to the right of the first non-null argument are not evaluated. This SQL-standard function provides capabilities similar to NVL and IFNULL, which are used in some other database systems.
I also want to get back the id value of the row, having being inserted or not.
I started with:
select coalesce (
(select id from test where first_name='carlos'),
(insert into test(first_name) values('carlos') returning id)
);
but an error syntax error at or near "into" was found.
See it on this other DBFiddle
https://www.db-fiddle.com/f/t7TVkoLTtWU17iaTAbEhDe/0
Then I tried:
select coalesce (
(select id from test where first_name='carlos'),
(with r as (
insert into test(first_name) values('carlos') returning id
) select id from r
)
);
Here I am getting a WITH clause containing a data-modifying statement must be at the top level error that I don't understand, as insert is the first and only sentence within the with.
I am testing this with DBFiddle and PostgreSQL 13. The source code can be found at
https://www.db-fiddle.com/f/hp8T1iQ8eS4wozDCBhBXDw/5
Different method: chained CTEs:
CREATE TABLE test
( id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY
, first_name VARCHAR UNIQUE
);
WITH sel AS (
SELECT id FROM test WHERE first_name = 'carlos'
)
, ins AS (
INSERT INTO test(first_name)
SELECT 'carlos'
WHERE NOT EXISTS (SELECT 1 FROM test WHERE first_name = 'carlos')
RETURNING id
)
, omg AS (
SELECT id FROM sel
UNION ALL
SELECT id FROM ins
)
SELECT id
FROM omg
;
It seems that the returning value from the insert into clause is not equivalent in nature to the scalar query of a select clause. So I try encapsulating the insert into into an SQL function and it worked.
create or replace function insert_first_name(
_first_name varchar
) returns int
language sql as $$
insert into test (first_name)
values (_first_name)
returning id;
$$;
select coalesce (
(select id from test where first_name='carlos'),
(select insert_first_name('carlos'))
);
See it on https://www.db-fiddle.com/f/73rVXgqGfrG4VmjrAk6Z3i/2
This is a refinement on #wildplasser accepted answer. it avoids comparing first_name twice and uses coalesce instead of union all. Kind of an selsert in just one sentence.
with sel as (
select id from test where first_name = 'carlos'
)
, ins as (
insert into test(first_name)
select 'carlos'
where (select id from sel) is null
returning id
)
select coalesce (
(select id from sel),
(select id from ins)
);
See it at https://www.db-fiddle.com/f/goRh4TyAebTkEZFHk6WbtK/6

How to insert and then update returned Id from insert query as returning id in a single command in postgres?

I have a demo table
CREATE TABLE items (
id SERIAL primary key,
user_id integer,
name character varying,
created timestamp with time zone default now()
);
And I want a single query to run and first insert data, then return primary key using returning id and then update the same table with the returned id.
INSERT INTO items (name) values ('pen') RETURNING id as idd
update items set user_id=(select idd) where id=(select idd)
but the above command doesn't work and throws syntax error.
Any help will be appriciated.
You can do that right within the INSERT statement:
INSERT INTO items
(name, user_id)
values
('pen', currval(pg_get_serial_sequence('items','id')));
Online example
You can try this way also :
create temp table insert_item as
with insert_item_cte as (
INSERT INTO items (name)
values ('pen') returning id
)
select id from insert_item_cte;
update items set user_id = items.id
from insert_item ii
where ii.id = items.id;
Online Demo

Update from inserted id

LOGIC: I want to create loyalty_customers when customers.user_id is null and update customers.user_id is loyalty_customers.id
I have a query and it's not working:
UPDATE customers
SET user_id = (
INSERT INTO loyalty_users (name) VALUES ('anonymous')) RETURNING id
)
WHERE user_id IS NULL;
Error like:
LINE 3: INSERT INTO loyalty_users
Look like INSERT can not be wrapped by any query, I tried this query and it's still not working:
SELECT id FROM (
INSERT INTO loyalty_users (name) VALUES ('anonymous')) RETURNING id);
However, stand-alone INSERT query work like a charm:
INSERT INTO loyalty_users (name) VALUES ('anonymous')) RETURNING id;
May be the right way to do this thing is:
WITH updated_customer AS (
UPDATE customers
SET name = 'anonymous'
WHERE user_id IS NULL
RETURNING user_id AS id
)
INSERT INTO loyalty_users SELECT * FROM updated_customer;
It's work for me, but if you have another idea, please comment in this question.

T-SQL Delete Inserted Records

I know the title may seem strange but this is what I want to do:
I have table with many records.
I want to get some of this records and insert them in other table. Something like this:
INSERT INTO TableNew SELECT * FROM TableOld WHERE ...
The tricky part is that I want this rows that I have inserted to be deleted form the origin table as well.
Is there a easy way to do this, because the only think that I have managed to do is to use a temporary table for saving the selected records and then to put them in the second table and delete rows that match with them from the first table. It is a solution, but with so many records (over 3 millions and half) I am looking for some other idea...
In 2005+ use OUTPUT clause like this:
DELETE FROM TableOld
OUTPUT DELETED.* INTO TableNew
WHERE YourCondition
It will be performed in single transaction and either completed or roll back simultaneously
You can use the insert ... output clause to store the ID's of the copied rows in a temporary table. Then you can delete the rows from the original table based on the temporary table.
declare #Table1 table (id int, name varchar(50))
declare #Table2 table (id int, name varchar(50))
insert #Table1 (id,name)
select 1, 'Mitt'
union all select 2, 'Newt'
union all select 3, 'Rick'
union all select 4, 'Ron'
declare #copied table (id int)
insert #Table2
(id, name)
output inserted.id
into #copied
select id
, name
from #Table1
where name <> 'Mitt'
delete #Table1
where id in
(
select id
from #copied
)
select *
from #Table1
Working example at Data Explorer.
You should do some thing like this:
INSERT INTO "table1" ("column1", "column2", ...)
SELECT "column3", "column4", ...
FROM "table2"
WHERE ...
DELETE FROM "table1"
WHERE ...