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.
Related
Suppose the following:
create table member (
id serial primary key,
member_name varchar(55),
role_ids bigint[] not null
);
create table role (
id serial primary key,
role_name varchar(55) unique
);
insert into role values (1, 'admin'), (2, 'common');
I can create an admin member like this:
insert into member (role_ids)
select ARRAY[id] as role_id from role where role_name = 'admin';
But how can I specify other fields, like member_name as well?
I've tried this:
insert into member (member_name, role_ids) values('test member', role_ids)
select ARRAY[id::bigint] as role_id from role where role_name = 'admin';
But this throws an error, error at or near select
In your case I would probably choose to use a nested SELECT inside the VALUES, to emphasize that this is a lookup that you expect to succeed and return only one value:
insert into member (member_name, role_ids)
values('test member',
(select ARRAY[id] from role where role_name = 'admin'));
This wouldn't work if you were selecting more than one column in your select. Another solution would be to just use SELECT and no VALUES, because nothing stops you from returning literal values in your SELECT. You don't name the columns in the select for your insert, instead you order them to match the order of the columns in the insert:
insert into member (member_name, role_ids)
select 'test member', ARRAY[id] from role where role_name = 'admin';
Given the following snippet from my schema:
create table users (
id serial primary key,
name text not null
);
create table user_groups (
id serial primary key,
name text not null
);
create table user_user_group (
user_id integer not null references users(id),
user_group_id integer not null references user_groups(id)
);
grant all on users to staff;
grant all on user_groups to staff;
grant all on user_user_group to staff;
create function can_access_user_group(id integer) returns boolean as $$
select exists(
select 1
from user_user_group
where user_group_id = id
and user_id = current_user_id()
);
$$ language sql stable security invoker;
create function can_access_user(id integer) returns boolean as $$
select exists(
select 1
from user_user_group
where user_id = id
and can_access_user_group(user_group_id)
);
$$ language sql stable security invoker;
alter table users enable row level security;
create policy staff_users_policy
on users
to staff
using (
can_access_user(id)
);
Please assume the staff role, and current_user_id() function are tested and working correctly. I'm hoping to allow the "staff" role to create users in user groups they can access via the user_user_group table. The following statement fails the staff_users_policy:
begin;
set local role staff;
with new_user as (
insert into users (
name
) values (
'Some name'
)
returning id
)
insert into user_user_group (
user_id,
user_group_id
)
select
new_user.id,
1 as user_group_id
from new_user;
commit;
I can add a staff_insert_users_policy like this:
create policy staff_insert_users_policy
on users
for insert
to staff
with check (
true
);
Which allows me to insert the user but fails on returning id, and I need the new user id in order to add the row to the user_user_group table.
I understand why it fails, but conceptually how can I avoid this problem? I could create a "definer" function, or a new role with it's own policy just for this but I'm hoping there's a more straightforward approach.
I just came around this problem too and solved it by generating the uuid before inserting it:
create or replace function insert_review_with_reviewer(
v_review_input public.review,
v_reviewer_input public.reviewer
)
returns void
language plpgsql
security invoker
as
$$
declare
v_review_id uuid := gen_random_uuid();
begin
insert into public.review
(id,
organisation_id,
review_channel_id,
external_id,
star_rating,
comment)
values (v_review_id,
v_review_input.organisation_id,
v_review_input.review_channel_id,
v_review_input.external_id,
v_review_input.star_rating,
v_review_input.comment);
insert into public.reviewer
(organisation_id, profile_photo_url, display_name, is_anonymous, review_id)
values (v_reviewer_input.organisation_id, v_reviewer_input.profile_photo_url, v_reviewer_input.display_name,
v_reviewer_input.is_anonymous, v_review_id);
end if;
end
$$;
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);
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
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)