How to insert new record with sequence on postgres - postgresql

I have a table 'new_table' with sequence id as primary key.
how can I insert new records to it with data from other table. I tried:
insert into new_table (
(select (select NEXTVAL('my_sequence')),a,b,c from old_table)
);
but got
duplicate key value violates unique constraint DETAIL: Key (id)=(...)
already exists.

just list columns skipping the one with sequence, smth like:
insert into new_table (a,b,c) select a,b,c from old_table;
If default value is set to get nextval, you don't have to do it manually.
check if your sequence is not behind the max(id) value. smth like:
select max(id) from new_table
if it is, restart sequence with new cellar, smth like:
alter sequence my_sequence restart with 1999; or what your maximum is

Related

PostgreSQL add auto increment to empty ID column

I create table in PostgreSQL but I forgot to add auto increment.
How to alter empty Id column in Postgres to add auto increment?
Starting with Postgres 10 it's recommended to use identity columns for this.
You can turn an existing column into an identity column using an ALTER TABLE:
alter table the_table
alter id add generated always as identity;
If you already have data in the table, you will need to sync the sequence:
select setval(pg_get_serial_sequence('the_table', 'id'), (select max(id) from the_table));
You will need to create a sequence owned by that column and set that as the default value.
e.g.
CREATE TABLE mytable (id int);
CREATE SEQUENCE mytable_id_seq OWNED BY mytable.id;
ALTER TABLE mytable ALTER COLUMN id SET DEFAULT nextval('mytable_id_seq');

Auto update primary key when insert into existing table?

Actually my question is basically the same as here but I need to insert values from a nested query into an existing table and I'am not that familiar with sql as to know how to incorporate the setval part into my query:
insert into table_a
select *
from table_b
where val_1 IN (select "val_1" from table_c where "val_2" is null)
returns
ERROR: duplicate key value violates unique constraint "table_a_pkey"
DETAIL: Key (qid)=(470971) already exists.
Now I know I could do a workaround with drop column and autgenerate as described here but there must be a more elegant way. I am using Postgresql/Postgis 2.4 btw.
It he primary key is auto-generated, don't insert the PK column:
insert into table_a (some_column, other_column, third_column)
select some_column, other_column, third_column
from table_b
where val_1 IN (select "val_1" from table_c where "val_2" is null)
(I had to guess the column names as you did not provide the real ones)

How to get child table's foreign key to have same value as parent's primary auto-increment key

I have created these two tables:
CREATE TABLE Purchase(
purchaseID SERIAL,
custName VARCHAR(30) NOT null,
PRIMARY KEY (purchaseID));
CREATE TABLE PurchasedItem(
purchaseID INT,
itemNo INT NOT NULL,
PRIMARY KEY (purchaseID, itemNo),
FOREIGN KEY (purchaseID) REFERENCES Purchase(purchaseID));
Next I wish to insert data into both tables, with the purchaseID foreign key of purchased item having the same value as the purchaseID Serial from Purchase table.
I am using a PostgreSQL client called PSequel. I tried setting AUTOCOMMIT to off first in the client so I could have the two INSERT statement in the same transaction, however the client didn't recognise "autocommit", so I tried it in the terminal and I think it worked... anyway, these are the two INSERT statements I tried.
INSERT INTO Purchase(custName) VALUES ('Lendl');
INSERT INTO PurchasedItem(purchaseID, itemNo) VALUES (DEFAULT, 111);
commit;
However I get an error:
ERROR: null value in column purchaseID violates not-null constraint.
this is referring to the PurchasedItem's purchaseID as in running the first INSERT statement by itself it works. How do I solve this problem?
DEFAULT will work for SERIAL as it sets default value for column. So
INSERT INTO Purchase VALUES (DEFAULT,'Lendl');
should work. But PurchasedItem.purchaseID has no default value set, so it it tries to insert NULL (and null is not in referenced column yet), so it fails.
try:
INSERT INTO Purchase(custName) VALUES ('Lendl') RETURNING purchaseID;
you will see the value of inserted purchaseID, use it in next query:
INSERT INTO PurchasedItem(purchaseID, itemNo) VALUES (_the_value_above_, 111);
commit;
If you want it to be used without interactivity, use DO block with returning purchaseID into _value
update:
or cte, smth like
WITH i AS (
INSERT INTO Purchase(custName, orderedDate)
VALUES ('Lendl', '2016-09-28')
RETURNING purchaseID
)
insert into PurchasedItem
select i.purchaseID,'smth',3
from i
You can use lastval()
INSERT INTO Purchase(custName) VALUES ('Lendl');
INSERT INTO PurchasedItem(purchaseID, itemNo) VALUES (lastval(), 111);
commit;
Alternatively query the underlying sequence directly:
INSERT INTO Purchase(custName) VALUES ('Lendl');
INSERT INTO PurchasedItem(purchaseID, itemNo)
VALUES (currval('purchase_purchaseid_seq'), 111);
commit;
Or if you don't want to rely on the automatic naming of the sequence, use pg_get_serial_sequence to get the sequence associated with the column:
INSERT INTO Purchase(custName) VALUES ('Lendl');
INSERT INTO PurchasedItem(purchaseID, itemNo)
VALUES (currval(pg_get_serial_sequence('purchase', 'purchaseid')), 111);
commit;
For more details see the manual: https://www.postgresql.org/docs/current/static/functions-sequence.html

Copying rows violates not-null constraint in PostgreSQL

I am trying to do what is described in this solution and also here. That means I would like to copy rows with many columns while changing only a few values. So my query looks like this:
CREATE TEMPORARY TABLE temp_table AS
SELECT * FROM original_table WHERE <conditions>;
UPDATE temp_table
SET <auto_inc_field>=NULL,
<fieldx>=<valuex>,
<fieldy>=<valuey>;
INSERT INTO original_table SELECT * FROM temporary_table;
However, the <auto_inc_field>=NULL part is not working for me, respectively my PostgreSQL 9.4 database:
Exception: null value in column "auto_inc_field" violates not-null constraint
The <auto_inc_field> column is defined as BIGINT, SERIAL, and has a primary key constraint.
What do I need to pass, if NULL is not working? Is there an alternative method?
I understand that the primary key is a serial. List all columns but the primary key in the insert command. List the correspondent columns and values in the select command:
insert into original_table (col_1, col_2, col_3)
select col_1, value_2, value_2
from original_table
where the_conditions;

Add a serial column based on a sorted column

I have a table that has one column with unordered value. I want to order this column descending and add a column to record its order. My SQL code is:
select *
into newtable
from oldtable
order by column_name desc;
alter table newtable add column id serial;
Would this implement my goal? I know that rows in PostgreSQL have no fixed order. So I am not sure about this.
Rather than (ab)using a SERIAL via ALTER TABLE, generate it at insert-time.
CREATE TABLE newtable (id serial unique not null, LIKE oldtable INCLUDING ALL);
INSERT INTO newtable
SELECT nextval('newtable_id_seq'), *
FROM oldtable
ORDER BY column_name desc;
This avoids a table rewrite, and unlike your prior approach, is guaranteed to produce the correct ordering.
(If you want it to be the PK, and the prior table had no PK, change unique not null to primary key. If the prior table had a PK you'll need to use a LIKE variant that excludes constraints).
You can first create a new table, sorted based on the column you want to use:
CREATE TABLE newtable AS
SELECT * FROM oldtable
ORDER BY column_name desc;
Afterwards, since you want to order from the largest to the smallest, you can add a new column to your table:
ALTER TABLE newtable ADD COLUMN id serial unique;