PostgreSQL: relation does not exist error - postgresql

Perhaps this error can be caused by problems with the SCHEMA, I tried to fix it, but I was completely confused.
Here is the detailed description.
There is a separate file that runs the following commands:
CREATE DATABASE weather;
CREATE SCHEMA public;
CREATE SCHEMA schema1;
SET search_path = schema1, public;
CREATE TABLE "Sities" (
Id SERIAL PRIMARY KEY,
name TEXT,
country TEXT,
weather_id_api int);
CREATE TABLE "Forecasts" (
Id SERIAL PRIMARY KEY,
city_id int,
time DATE,
temp INT,
humidity INT,
pressure INT);
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres;
GRANT usage ON SCHEMA public TO postgres;
The execution of each command is checked for errors. These commands are executed without problems.
Further in another file such commands are executed:
SET search_path = schema1, public;
INSERT INTO "Sities" (name, country, weather_id_api)
SELECT 'Orenburg', "RU", 234234
WHERE NOT EXISTS (SELECT name FROM "Sities" WHERE name="Orenburg");
The last command causes an error:
panic: pq: Relation "Sities" does not exist
goroutine 1 [running]: main.PostToDatabase(0x11731ee0)
D:/Go/src/WeatherSoket/main.go:135 +0x40f main.Update()
D:/Go/src/WeatherSoket/main.go:150 +0x52 main.main()
D:/Go/src/WeatherSoket/main.go:165 +0xbe exit status 2

This works - try to check quotes " and apostrophes ':
SET search_path = schema1, public;
INSERT INTO "Sities" (name, country, weather_id_api)
SELECT 'Orenburg', 'RU', 234234
WHERE NOT EXISTS (SELECT name FROM "Sities" WHERE name='Orenburg');
http://sqlfiddle.com/#!17/5abd9/4

Related

How can I UNION two tables in different PostgeSQL databases?

I'm running PostgreSQL 11.8 in a Docker container. I have two databases: website_db and testdb.
website_db has a products table with id, product_name, colour, product_size columns
testdb has a table called users with id, username, password
I'm using website_db and I want to UNION columns from the users table in the testdb database. I can get this to work in MySQL but am struggling with Postgres. Here's my attempt:
SELECT * FROM products WHERE product_name = 'doesntexist' OR 1=1 UNION SELECT null,username,password,null FROM testdb.users;
I get this error back:
ERROR: relation "testdb.users" does not exist
LINE 1: ...1=1 UNION SELECT null,username,password,null FROM testdb.use...
Does anyone know what I have to do to fix my query?
You can do it using dblink:
create database first;
create database second;
\c first;
create table products
(
id serial not null
constraint products_pk
primary key,
product_name varchar(50) not null
);
INSERT INTO public.products (id, product_name) VALUES (1, 'first_db');
\c second;
create table products
(
id serial not null
constraint products_pk
primary key,
product_name varchar(50) not null
);
INSERT INTO public.products (id, product_name) VALUES (1, 'sec_db');
-- dblink -- executes a query in a remote database
create extension dblink;
-- change queries and creds
SELECT id, product_name FROM products
UNION ALL
SELECT * FROM dblink('dbname=first user=root password=root', 'SELECT id, product_name FROM products') AS tb2(id int, product_name text);

Rule or trigger for replacing view insert

I have an updatable postgres view which exposes a person table. The view hides some private data, such as email. When inserting I want users to be able to insert values for that private data. Would it be better to use a rule or a trigger to gain this functionality?
After some testing it seems like I can't use a trigger to insert to columns not defined in the view.
One possible way is to use privileges instead of view to expose subset of columns.
For example, given the table
create table person(
first_name text,
last_name text,
email text
);
you can grant the following privileges to a user:
grant select(first_name, last_name) on person to someuser;
grant insert on person to someuser;
And this is how it works:
postgres=> insert into person values('Foo','Bar','foo#bar.com');
INSERT 0 1
postgres=> select * from person;
ERROR: permission denied for relation person
postgres=> select first_name, last_name from person;
first_name | last_name
------------+-----------
Foo | Bar
(1 row)
Of course, it is only possible on "per user" basis.
Another way is to use function defined as "security definer". This specifies that the function is to be executed with the privileges of the user that created it.
So you can define a function to insert data directly into the table; definer must have the insert privilege:
create function person_insert(first_name text, last_name text, email text)
returns void
security definer
as $$
insert into person(first_name, last_name, email) values ($1, $2, $3);
$$ language sql;
Then the other user can call it without having himself the insert privilege:
postgres=> insert into person(first_name, last_name, email) values ('foo', 'bar', 'foo#bar.com');
ERROR: permission denied for relation person
postgres=> select person_insert('foo','bar','foo#bar.com');
people_insert
---------------
(1 row)
postgres=> select * from person_view;
first_name | last_name
------------+-----------
Foo | Bar
(1 row)

extract data from two databases postgres

I have two database , test1 and test2
in test1 I have a table named : emplyee
in test2 I have a table named : user_
I want to extrat the users from table employee who are not exist in the table user_
I try with this query
select * from employee where mail_employe not in
( select emailaddress from test2.user_ )
I have this error :
ERROR: schema "test2" does not exist
LINE 3: ( select emailaddress from test2.user_ )
I try also with this syntax :
select * from employee where mail_employe not in
(SELECT emailaddress from dblink('dbname=test2','SELECT emailaddress FROM user_'))
I have also this error
ERROR: a column definition list is required for functions returning "record"
LINE 3: (SELECT emailaddress from dblink('dbname=test2','SELEC...
updated
I try to user the systax of SCHEMA
in the two database I have this code of SCHEMA
CREATE SCHEMA public
AUTHORIZATION postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public
IS 'standard public schema';
I try to use this code without success
select * from test1.public.employee where mail_employe not in
(SELECT emailaddress from test2.public.user_')
but i have the same error
Example:
CREATE SCHEMA sch1;
CREATE SCHEMA sch2;
CREATE TABLE sch1.foo ( id serial, name varchar );
CREATE TABLE sch2.bar ( id serial, title varchar );
Query:
SELECT sch1.foo.name, sch2.bar.title
FROM sch1.foo
INNER JOIN sch2.bar on sch1.foo.name = sch2.bar.title;
SELECT sch1.foo.name
FROM sch1.foo
WHERE sch1.foo.id IN (SELECT sch2.bar.id FROM sch2.bar);
Unfortunately, as long as you don't change search path you need to write full path to resources.

Changing primary key int type to serial

Is there a way to change existing primary key type from int to serial without dropping the table? I already have a lot of data in the table and I don't want to delete it.
Converting an int to a serial more or less only means adding a sequence default to the value, so to make it a serial;
Pick a starting value for the serial, greater than any existing value in the table
SELECT MAX(id)+1 FROM mytable
Create a sequence for the serial (tablename_columnname_seq is a good name)
CREATE SEQUENCE test_id_seq MINVALUE 3 (assuming you want to start at 3)
Alter the default of the column to use the sequence
ALTER TABLE test ALTER id SET DEFAULT nextval('test_id_seq')
Alter the sequence to be owned by the table/column;
ALTER SEQUENCE test_id_seq OWNED BY test.id
A very simple SQLfiddle demo.
And as always, make a habit of running a full backup before running altering SQL queries from random people on the Internet ;-)
-- temp schema for testing
-- ----------------------------
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE bagger
( id INTEGER NOT NULL PRIMARY KEY
, tralala varchar
);
INSERT INTO bagger(id,tralala)
SELECT gs, 'zzz_' || gs::text
FROM generate_series(1,100) gs
;
DELETE FROM bagger WHERE random() <0.9;
-- SELECT * FROM bagger;
-- CREATE A sequence and tie it to bagger.id
-- -------------------------------------------
CREATE SEQUENCE bagger_id_seq;
ALTER TABLE bagger
ALTER COLUMN id SET NOT NULL
, ALTER COLUMN id SET DEFAULT nextval('player_id_seq')
;
ALTER SEQUENCE bagger_id_seq
OWNED BY bagger.id
;
SELECT setval('bagger_id_seq', MAX(ba.id))
FROM bagger ba
;
-- Check the result
-- ------------------
SELECT * FROM bagger;
\d bagger
\d bagger_id_seq

Why can I not set this unique constraint in PostgreSQL?

I keep getting:
SQL error: ERROR: could not create
unique index
"service_import_checksum_key" DETAIL:
Key (checksum)=() is duplicated.
In statement:
ALTER TABLE "public"."service_import" ADD CONSTRAINT "service_import_checksum_key" UNIQUE ("checksum")
But this constraint ISN'T a duplicate. There is no other constraint like this anywhere in the entire database and I have no idea why on earth it keeps insisting it's a duplicate. I'm assuming this is some weird nuance of postgres that I'm missing here.
What am I doing wrong?
Table dump:
--
-- PostgreSQL database dump
--
SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = off;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET escape_string_warning = off;
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: service_import; Type: TABLE; Schema: public; Owner: cvs_tar; Tablespace:
--
CREATE TABLE service_import (
id integer NOT NULL,
name character varying(32) NOT NULL,
importfile character varying(64) NOT NULL,
reportfile character varying(64) NOT NULL,
percent smallint NOT NULL,
message text NOT NULL,
stamp timestamp without time zone DEFAULT now() NOT NULL,
complete smallint DEFAULT 0 NOT NULL,
checksum character varying(40) NOT NULL
);
ALTER TABLE public.service_import OWNER TO cvs_tar;
--
-- Name: service_imports_id_seq; Type: SEQUENCE; Schema: public; Owner: cvs_tar
--
CREATE SEQUENCE service_imports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.service_imports_id_seq OWNER TO cvs_tar;
--
-- Name: service_imports_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: cvs_tar
--
ALTER SEQUENCE service_imports_id_seq OWNED BY service_import.id;
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: cvs_tar
--
ALTER TABLE service_import ALTER COLUMN id SET DEFAULT nextval('service_imports_id_seq'::regclass);
--
-- Name: service_import_name_key; Type: CONSTRAINT; Schema: public; Owner: cvs_tar; Tablespace:
--
ALTER TABLE ONLY service_import
ADD CONSTRAINT service_import_name_key UNIQUE (name);
--
-- Name: service_import_pkey; Type: CONSTRAINT; Schema: public; Owner: cvs_tar; Tablespace:
--
ALTER TABLE ONLY service_import
ADD CONSTRAINT service_import_pkey PRIMARY KEY (id);
--
-- Name: service_import_complete_idx; Type: INDEX; Schema: public; Owner: cvs_tar; Tablespace:
--
CREATE INDEX service_import_complete_idx ON service_import USING btree (complete);
--
-- Name: service_import_stamp_idx; Type: INDEX; Schema: public; Owner: cvs_tar; Tablespace:
--
CREATE INDEX service_import_stamp_idx ON service_import USING btree (stamp);
--
-- PostgreSQL database dump complete
--
Read the error message again:
SQL error: ERROR: could not create unique index "service_import_checksum_key"
DETAIL: Key (checksum)=() is duplicated.
Looks like it is telling you that there are duplicate values in the checksum column and you're trying to enforce uniqueness on that column with your constraint. The constraint isn't duplicated, the data has duplicates.
Furthermore, the "()" part indicates that you have multiple empty strings in the checksum column. Unique constraints allow multiple NULL values (since NULL = NULL is NULL which is not true) but empty strings are not NULL.
An example to clarify what's going on:
=> CREATE TABLE x (s VARCHAR NULL);
CREATE TABLE
=> INSERT INTO x (s) VALUES (''), ('a'), ('');
INSERT 0 3
=> ALTER TABLE x ADD CONSTRAINT ux UNIQUE(s);
NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "ux" for table "x"
ERROR: could not create unique index "ux"
DETAIL: Key (s)=() is duplicated.
=> delete from x where s='';
DELETE 2
=> INSERT INTO x (s) VALUES ('a');
INSERT 0 1
=> ALTER TABLE x ADD CONSTRAINT ux UNIQUE(s);
NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "ux" for table "x"
ERROR: could not create unique index "ux"
DETAIL: Key (s)=(a) is duplicated.
In particular, note what the ERROR and DETAIL are saying and compare that to the INSERTs.