How to import only specific columns from CSV in PostgreSQL - postgresql

PostgreSQL version: 9.6
I have a table xyz with columns a integer, b integer, c text, d integer.
The column c has a non-null constraint.
I have a CSV looking like so:
foo.csv
1,4
2,5
3,7
How could I only update column a and d by importing the CSV above?
I tried COPY xyz (a,d) FROM '/foo.csv' DELIMITER ','; but it gave me an error
ERROR: null value in column "c" violates not-null constraint DETAIL: Failing row contains (1, null, null, 4).

Usually, a not null column should have a default value defined. You can define a default value for an existing column, e.g.
alter table xyz alter c set default '';
After that, the copy command will succeed.

Related

Alter Column TYPE USING - cannot change from varchar to numeric

I would be eternaly grateful if somebody could help me a bit. I am totally new to Postrgresql 10
I had a large file millions of lines 73 columns, I could not imported so I set all the columns to varchar. Now I need to manipulate the data I cannot change the datatype. I tried for hours. The column contains a few values with 1 or 2 decimals. This is what I am doing:
ALTER TABLE table1
ALTER COLUMN facevalue TYPE numeric USING (facevalue::numeric);
this is the error I get
ERROR: invalid input syntax for type numeric: " "
SQL state: 22P02
Thank you for your time and consideration
you apparently have empty strings or whitespace only values. You need to convert them to NULL
ALTER TABLE table1
ALTER COLUMN facevalue TYPE numeric USING (nullif(trim(facevalue),'')::numeric);

psql copy from csv automatically generating ids

Well consider a table created like this:
CREATE TABLE public.test
(
id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
name text,
PRIMARY KEY (id)
)
So the table has a unique 'id' column that auto generates default values using a sequence.
Now I wish to import data from a csv file, extending this table. However "obviously" the ids need to be unique, and thus I wish to let the database itself generate the ids, the csv file itself (coming from a complete different source) has hence an "empty column" for the ids:
,username
,username2
However if I then import this csv using psql:
\copy public."user" FROM '/home/paul/Downloads/test.csv' WITH (FORMAT csv);
The following error pops up:
ERROR: null value in column "id" violates not-null constraint
So how can I do this?
The empty colum from the CSV file is interpreted as SQL NULL, and inserting that value overrides the DEFAULT and leads to the error.
You should omit the empty column from the file and use:
\copy public."user"(name) FROM '...' (FORMAT 'csv')
Then the default value will be used for id.

COPY if column exists

I am writing a PLPGSQL function, that needs to import files into a table.
I have created a temporary table with 4 columns
CREATE TABLE IF NOT EXISTS tmp_ID_Customer (
ID int4 NULL,
Name varchar(2000) NULL,
CodeEx varchar(256) NULL,
AccountID varchar(256) NULL
)ON COMMIT DROP;
I am then trying to copy a file into this table, with the following
EXECUTE format('COPY tmp_ID_Customer FROM %L (FORMAT CSV, HEADER TRUE, DELIMITER(''|''))', _fileName);
The issue I have is some of these files only contain the first 3 columns.
So I am receiving an error saying
extra data after last expected column
I've tried specifying the columns, but as the final column doesn't always exist. I get an error.
Specify the columns you are copying:
COPY tmp_ID_Customer(id, name, codex) FROM ...

How to convert a currency column of a table into a numeric column in postgresql

We need to make our schema support multiple currencies. So, using currency field is not a option. So, I am trying to convert currency column into numeric(12,2). I tried the following approaches:
ALTER TABLE lead ALTER COLUMN deal_size TYPE NUMERIC(12, 2);
ALTER TABLE lead ALTER COLUMN deal_size TYPE NUMERIC(12, 2) using deal_size::money::numeric(12,2);
each time I get the following error:
ERROR: numeric field overflow
DETAIL: A field with precision 12, scale 2 must round to an absolute value less than 10^10.
I verified that none of the values for this column in the table is more than $1,000,000
I test the following in my PostgreSQL and works perfectly well. What version of PostgreSQL are you running?
create temp table lead (id serial not null primary key, deal_size money);
insert into lead (deal_size) select (random()*100000000)::numeric(14,4) from generate_series(1,10000) a;
ALTER TABLE lead ALTER COLUMN deal_size TYPE NUMERIC(12, 2);
You don't have values greater than a million. Have you tested for large negative values?

How to change column datatype from character to numeric in PostgreSQL 8.4

I am using following query:
ALTER TABLE presales ALTER COLUMN code TYPE numeric(10,0);
to change the datatype of a column from character(20) to numeric(10,0) but I am getting the error:
column "code" cannot be cast to type numeric
You can try using USING:
The optional USING clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new. A USING clause must be provided if there is no implicit or assignment cast from old to new type.
So this might work (depending on your data):
alter table presales alter column code type numeric(10,0) using code::numeric;
-- Or if you prefer standard casting...
alter table presales alter column code type numeric(10,0) using cast(code as numeric);
This will fail if you have anything in code that cannot be cast to numeric; if the USING fails, you'll have to clean up the non-numeric data by hand before changing the column type.
If your VARCHAR column contains empty strings (which are not the same as NULL for PostgreSQL as you might recall) you will have to use something in the line of the following to set a default:
ALTER TABLE presales ALTER COLUMN code TYPE NUMERIC(10,0)
USING COALESCE(NULLIF(code, '')::NUMERIC, 0);
(found with the help of this answer)
Step 1: Add new column with integer or numeric as per your requirement
Step 2: Populate data from varchar column to numeric column
Step 3: drop varchar column
Step 4: change new numeric column name as per old varchar column