Postgres - how to bulk insert table with foreign keys - postgresql

I am looking to do a bulk insert into my postgreSQL database.
database is not yet live
postgreSQL 13
I have a temporary staging table which I bulk inserted data
TABLE public.temp_inverter_location
(
id integer ,
inverter_num_in_sld integer,
lift_requirements character varying,
geo_location_id integer NOT NULL (foreign key references geo_location.id),
location_name character varying,
project_info_id integer NOT NULL (foreign key references project_info.id)
)
I am trying to populate the two foreign key columns temp_inverter_location.geo_location_id and temp_inverter_location.project_info_id.
The two referenced tables are referenced by their id columns:
geo_location
CREATE TABLE public.geo_location
(
id integer,
country character varying(50) COLLATE pg_catalog."default",
region character varying(50) COLLATE pg_catalog."default",
city character varying(100) COLLATE pg_catalog."default",
location_name character varying COLLATE pg_catalog."default",
)
and
project_info
CREATE TABLE public.project_info
(
id integer
operation_name character varying,
project_num character varying(10),
grafana_site_num character varying(10)
)
I want to populate the correct foreign keys into the columns temp_inverter_location.geo_location_id and temp_inverter_location.project_info_id.
I am trying to use INSERT INTO SELECT to populate temp_inverter_location.geo_location_id with a JOIN that matches geo_location.location_name and temp_inverter_location.name.
I have tried this query however inverter_location.geo_location_id remains blank:
INSERT INTO temp_inverter_location(geo_location_id) SELECT geo_location.id FROM geo_location INNER JOIN temp_inverter_location ON geo_location.location_name=temp_inverter_location.location_name;
Please let me know if more info is needed, thanks!

I was able to resolve this issue using update referencing another table.
Basically, I updated the geo_location_id column using
UPDATE temp_inverter_location SET geo_location_id = geo_location.id FROM geo_location WHERE geo_location.location_name = temp_inverter_location.location_name;
and updated the project_info_id using
UPDATE load_table SET project_info_id = project_info.id FROM project_info WHERE project_info.operation_name = load_table.location_name;
It seems to have worked.

Related

Add data from one table to an array in another table based on matching value in postgres 15

I have two tables, one for reviews and another with urls for photos. I want to add the urls to an array in the reviews table. I want to match them based on the id for reviews they both have. Ideally I would be able to add the photos as a JSON object to the array, with one property for the photo id and another for the url. I'm new to postgres and SQL and struggling to come up with the query to be able to do this. Below is the sql for the two tables, below them is my attempt at a query:
CREATE TABLE IF NOT EXISTS public.reviews
(
id integer NOT NULL,
product_id integer NOT NULL,
rating integer,
date text COLLATE pg_catalog."default",
summary text COLLATE pg_catalog."default" NOT NULL,
body text COLLATE pg_catalog."default" NOT NULL,
recommend boolean,
reported boolean,
reviewer_name text COLLATE pg_catalog."default" NOT NULL,
reviewer_email text COLLATE pg_catalog."default" NOT NULL,
response text COLLATE pg_catalog."default",
helpfulness integer,
photos text[] COLLATE pg_catalog."default",
CONSTRAINT reviews_pkey PRIMARY KEY (id)
)
CREATE TABLE IF NOT EXISTS public.photos
(
id integer,
review_id integer,
url text COLLATE pg_catalog."default"
)
update reviews
set photos = array_append(photos, photos.url)
where photos.review_id = reviews.id;
You are missing a FROM clause for the photos table:
update reviews
set photos = array_append(reviews.photos, photos.url)
from photos
where photos.review_id = reviews.id;
Prefixing the photos column on the right hand side of the assignment isn't strictly necessary, but if there is a table and a column with the same name, I find this to be more readable.
Note that array_append(reviews.photos, photos.url) can also be written as reviews.photos || photos.url

How can i update a row in postgresql?

i have a table named person and it looks like this:
CREATE TABLE public.person
(
"idPerson" integer NOT NULL DEFAULT nextval('idperson'::regclass),
fname character varying(45) COLLATE pg_catalog."default",
lname character varying(45) COLLATE pg_catalog."default",
sex character(1) COLLATE pg_catalog."default",
dateofbirth date,
address character varying(75) COLLATE pg_catalog."default",
city character varying(45) COLLATE pg_catalog."default",
country character varying(45) COLLATE pg_catalog."default",
CONSTRAINT "idPerson_PK" PRIMARY KEY ("idPerson")
)
I want to perform an update through a function( my_update_function(fname,lname , sex ,dateofbirth,address,city,country) . My problem here is that i dont want a specific condition ,instead i want to just call the function like this for example:
SELECT my_update_function('Jamie','Phillips', 'F',1973-03-08,'Santina Island 108','Okhotsk',Russia)
and updates my table in the row with idPerson 57 only in the column that it is different (fname in this case )
This is what i did:
UPDATE person
SET fname=my_update_function.fname , lname=my_update_function.lname
,sex=my_update_function.sex , dateofbirth=my_update_function.dateofbirth
,address=my_update_function.address , city=my_update_function.city
,country=my_update_function.country
WHERE person.fname='Karissa';
I updated my table but the problem here is that i had to put the specific fname 'Karissa' inside of the function ,instead i want to be done automatically .
How can i do something like that?
Thank you.
Maybe you can try something like this
execute 'UPDATE person
SET fname='||my_update_function.fname||' , lname='||my_update_function.lname||'
,sex='||my_update_function.sex||' , dateofbirth='||my_update_function.dateofbirth||'
,address='||my_update_function.address||' , city='||y_update_function.city||'
,country='||my_update_function.country||'
WHERE person.fname='''||my_update_function.fname||'''';
or (better, because it is not vulnerable to SQL injection)
prepare query as UPDATE person SET fname=$1 , lname=$2 ,sex=$3, dateofbirth=$4,address=$5, city=$6,country=$7 WHERE person.fname=$8;
execute query(fname,lname,sex,dateofbirth,address,city,country,fname);

How to automatically fill columns on a row based on the foreign key being the primary key on another table

I'm working on a sql database for QGIS. I have 8 tables: 3 three of them are the base tables and the others are relational tables. One relational table,
"tabela_is_po", has 4 fields:
indice_sequencial_po (integer and Primary Key),
tema (character varying),
subtema (character varying),
designacao (character varying)
And the base table, "tabela_objecto_area", has 7 fields:
identificador integer ,
dtcc character varying(4),
planta_po boolean,
indice_sequencial_po integer (foreign key),
tema_po character varying(254),
subtema_po character varying(254),
designacao_po character varying(254)
In "tabela_objecto area", when I fill, indice_sequencial_po integer (foreign key), I want the table to be able to automatically get the data from the relational table "tabela_is_po", based on the number that is filled in indice_sequencial_po.
I've tried the trigger function but it never worked well.
tabela_objecto_area code:
CREATE TABLE pdm2019.tabela_objecto_area
(
identificador integer NOT NULL DEFAULT nextval('pdm2019.tabela_objecto_area_identificador_seq'::regclass),
dtcc character varying(4) NOT NULL DEFAULT '0101',
planta_po boolean NOT NULL,
indice_sequencial_po integer,
tema_po character varying(254),
subtema_po character varying(254),
designacao_po character varying(254),
CONSTRAINT tabela_objecto_area_pkey PRIMARY KEY (identificador)
)
WITH (
OIDS=FALSE
);
Trigger function:
CREATE OR REPLACE FUNCTION tema_e_subtema_automatico() RETURNS TRIGGER AS $tema_e_subtema_automatico$
BEGIN
IF NEW.pdm2019.tabela_objecto_area.indice_sequencial_po IS NOT NULL THEN
INSERT INTO pdm2019.tabela_objecto_area(tema_po,subtema_po,designacao_po) SELECT tema,subtema,designacao FROM pdm2019.tabela_is_po WHERE indice_sequencial_po = NEW.pdm2019.tabela_objecto_area.indice_sequencial_po;
END IF;
END;
$tema_e_subtema_automatico$ LANGUAGE plpgsql;
CREATE TRIGGER tema_e_subtema_automatico AFTER INSERT OR UPDATE ON pdm2019.tabela_objecto_area
FOR EACH ROW EXECUTE PROCEDURE tema_e_subtema_automatico();
You would probably be better off using a view. See https://en.wikipedia.org/wiki/Relational_model for an overview, basically each item should appear only once in the database.
For data entry, it's often easier to use a framework like django (https://www.djangoproject.com/) to create the structure of your tables and input data, which you can then view in qgis.
CREATE TABLE pdm2019.tabela_objecto_area
(
identificador integer NOT NULL DEFAULT nextval('pdm2019.tabela_objecto_area_identificador_seq'::regclass),
dtcc character varying(4) NOT NULL DEFAULT '0101',
planta_po boolean NOT NULL,
indice_sequencial_po integer,
-- tema_po character varying(254), -- use a view to populate these
-- subtema_po character varying(254), -- use a view to populate these
-- designacao_po character varying(254), -- use a view to populate these
CONSTRAINT tabela_objecto_area_pkey PRIMARY KEY (identificador)
)
WITH (
OIDS=FALSE
);
CREATE VIEW v_tabela_objecto_area as (
select a.*, b.tema_po, b.subtema_po, b.designacao_po
from tabela_objecto_area a, tabela_is_po b
where a.indice_sequencial_po = b.indice_sequencial_po);

Postgres Update table id with sequence

I am trying to connect a sequence for user table to auto incremental value for id field.
I created following sequence,
CREATE SEQUENCE "USER_MGMT"."USER_SEQ"
INCREMENT 1
START 1000
MINVALUE 1000
MAXVALUE 99999999
CACHE 1;
ALTER SEQUENCE "USER_MGMT"."USER_SEQ"
OWNER TO postgres;
following is my table,
-- Table: "USER_MGMT"."USER"
-- DROP TABLE "USER_MGMT"."USER";
CREATE TABLE "USER_MGMT"."USER"
(
"USER_ID" bigint NOT NULL,
"FIRST_NAME" character varying(50) COLLATE pg_catalog."default" NOT NULL,
"LAST_NAME" character varying(50) COLLATE pg_catalog."default" NOT NULL,
"EMAIL_ID" character varying(100) COLLATE pg_catalog."default" NOT NULL,
"DESK_NUMBER" bigint,
"MOBILE_NUMBER" bigint,
"IS_ACTIVE" boolean NOT NULL DEFAULT true,
"CREATED_BY" character varying(100) COLLATE pg_catalog."default",
"MODIFIED_BY" character varying(100) COLLATE pg_catalog."default",
"DATE_CREATED" timestamp without time zone NOT NULL,
"DATE_MODIFIED" timestamp without time zone,
CONSTRAINT "USER_ID_PK" PRIMARY KEY ("USER_ID"),
CONSTRAINT "EMAIL_ID_UK" UNIQUE ("EMAIL_ID"),
CONSTRAINT "MOBILE_NUMBER_UK" UNIQUE ("MOBILE_NUMBER"),
CONSTRAINT "USER_ID_UK" UNIQUE ("USER_ID")
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE "USER_MGMT"."USER"
OWNER to postgres;
I want to connect this sequence to USER_ID column, so it will be auto incremented.
Table name and fields should be in upper case,
I am trying to execute the following query, but its not working
ALTER TABLE USER_MGMT.USER ALTER COLUMN USER_ID SET DEFAULT nextval('USER_MGMT.USER_SEQ');
It says the following error message in console.
ERROR: schema "user_mgmt" does not exist
********** Error **********
That is because when you use double quotes then you are creating case sensitive object identifier or to be more precise - this object will have identifier with exact case as given in the query during creation. If you do not double quote them, then they are converted to lower case.
So what you need is to either stop using double quotes, create objects in lower case or use double quotes in your alter query:
ALTER TABLE "USER_MGMT"."USER" ALTER COLUMN "USER_ID" SET DEFAULT nextval('"USER_MGMT"."USER_SEQ"');

Cascade Delete is not work

I am not able to delete record from parent table of PostGres DB.. Any one of you can get me an idea on this.
-- Table: tbl_patient
-- DROP TABLE tbl_patient;
CREATE TABLE tbl_patient
(
patient_id bigserial NOT NULL,
date_of_birth date NOT NULL,
fathers_name character varying(255) NOT NULL,
first_name character varying(255) NOT NULL,
last_name character varying(255),
marital_status character varying(255),
mobile_number character varying(255) NOT NULL,
occupation character varying(255),
phone_number character varying(255),
pregnancy_status character varying(255),
sex character varying(255) NOT NULL,
CONSTRAINT tbl_patient_pkey PRIMARY KEY (patient_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE tbl_patient
OWNER TO postgres;
-- Table: tbl_address
CREATE TABLE tbl_address
(
address_id bigserial NOT NULL,
address_line_1 character varying(255) NOT NULL,
address_line_2 character varying(255),
city character varying(255),
country character varying(255),
district character varying(255) NOT NULL,
pincode character varying(255) NOT NULL,
state character varying(255),
street character varying(255),
patient_id bigint,
CONSTRAINT tbl_address_pkey PRIMARY KEY (address_id),
CONSTRAINT fk_slc6pgeimmox5buka8bydy6c4 FOREIGN KEY (patient_id)
REFERENCES tbl_patient (patient_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE tbl_address
OWNER TO postgres;
//-------------------------------------------------------------------
When I put this command
DELETE FROM tbl_patient
WHERE patient_id = 1;
I got this error below
ERROR: update or delete on table "tbl_patient" violates foreign key
constraint "fk_slc6pgeimmox5buka8bydy6c4" on table "tbl_address" SQL
state: 23503 Detail: Key (patient_id)=(1) is still referenced from
table "tbl_address".
You write DELETE NO ACTION and you wanting actions:) Just need to change to
REFERENCES tbl_patient (patient_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
NO ACTION means that server wont do anything with referenced rows if they exists. Since they exists and you specified also MATCH SIMPLE to one-column-foreign key then PostgreSQL cannot perform deletion because of that referenced rows.