Copying rows violates not-null constraint in PostgreSQL - 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;

Related

Duplicate Key error even after using "On Conflict" clause

My table has following structure
CREATE TABLE myTable
(
user_id VARCHAR(100) NOT NULL,
task_id VARCHAR(100) NOT NULL,
start_time TIMESTAMP NOT NULL,
SOME_COLUMN VARCHAR,
col1 INTEGER,
col2 INTEGER DEFAULT 0
);
ALTER TABLE myTable
ADD CONSTRAINT pk_4_col_constraint UNIQUE (task_id, user_id, start_time, SOME_COLUMN);
ALTER TABLE myTable
ADD CONSTRAINT pk_3_col_constraint UNIQUE (task_id, user_id, start_time);
CREATE INDEX IF NOT EXISTS index_myTable ON myTable USING btree (task_id);
However when i try to insert data into table using
INSERT INTO myTable VALUES (...)
ON CONFLICT (task_id, user_id, start_time) DO UPDATE
SET ... --updating other columns except for [task_id, user_id, start_time]
I get following error
ERROR: duplicate key value violates unique constraint "pk_4_col_constraint"
Detail: Key (task_id, user_id, start_time, SOME_COLUMN)=(XXXXX, XXX, 2021-08-06 01:27:05, XXXXX) already exists.
I got the above error when i tried to programatically insert the row. I was successfully able to the execute query successfully via SQL-IDE.
Now i have following questions:
How is that possible? When 'pk_3_col_constraint' is ensuring my data is unique at 3 columns, adding one extra column will not change anything. What's happening here?
I am aware that although my constraint name starts with 'pk' i am using UNIQUE constraint rather than Primary Key constraint(probably a mistake while creating constraints but either way this error shouldn't have occurred)
Why didn't i get the error when using SQL-IDE?
I read in few articles unique constraint works little different as compared to primary key constraint hence causes this issue at time. If this is known issue is there any way i can replicate this error to understand in more detail.
I am running PostgreSQL 11.9 on x86_64-pc-linux-gnu, compiled by x86_64-pc-linux-gnu-gcc (GCC) 7.4.0, 64-bit version Postgres. My programmatic env was a Java AWS Lambda.
I have noticed people have faced this error occasionally in the past.
https://www.postgresql.org/message-id/15556-7b3ae3aba2c39c23%40postgresql.org
https://www.postgresql.org/message-id/flat/65AECD9A-CE13-4FCB-9158-23BE62BB65DD%40msqr.us#d05d2bb7b2f40437c2ccc9d485d8f41e but there are conclusions as to why it is happening

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)

Unique constraint on column values for rows which have same value on another column

Let sample_table be the following postgres 9.6.6 table:
CREATE TABLE sample_table (
col_a integer,
col_b integer
);
Is it possible to add constraints to sample_table to ensure that, on every one of its rows with col_b=42, no value on col_a appears twice?
You could add a conditional index (which can not be converted to a constraint, but works as if):
CREATE UNIQUE INDEX ON sample_table(col_a)
WHERE col_b=42;
I would prefer col_a to be NOT NULLable

How to insert new record with sequence on postgres

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

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;