How to select a schema in postgres when using psql? - postgresql

I have a postgres database with multiple schemas. When I connect to the database from a shell with psql and I run \dt it uses the default connection schema which is public. Is there a flag I can specify or how can I change the schema?

In PostgreSQL the system determines which table is meant by following a search path, which is a list of schemas to look in.
The first matching table in the search path is taken to be the one wanted, otherwise, if there is no match a error is raised, even if matching table names exist in other schemas in the database.
To show the current search path you can use the following command:
SHOW search_path;
And to put the new schema in the path, you could use:
SET search_path TO myschema;
Or if you want multiple schemas:
SET search_path TO myschema, public;
Reference: https://www.postgresql.org/docs/current/static/ddl-schemas.html

\l - Display database
\c - Connect to database
\dn - List schemas
\dt - List tables inside public schemas
\dt schema1. - List tables inside particular schemas. For eg: 'schema1'.

Do you want to change database?
\l - to display databases
\c - connect to new database
Update.
I've read again your question.
To display schemas
\dn - list of schemas
To change schema, you can try
SET search_path TO

if you in psql just type
SET schema 'temp';
and after that \d shows all relations in "temp

Use schema name with period in psql command to obtain information about this schema.
Setup:
test=# create schema test_schema;
CREATE SCHEMA
test=# create table test_schema.test_table (id int);
CREATE TABLE
test=# create table test_schema.test_table_2 (id int);
CREATE TABLE
Show list of relations in test_schema:
test=# \dt test_schema.
List of relations
Schema | Name | Type | Owner
-------------+--------------+-------+----------
test_schema | test_table | table | postgres
test_schema | test_table_2 | table | postgres
(2 rows)
Show test_schema.test_table definition:
test=# \d test_schema.test_table
Table "test_schema.test_table"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
Show all tables in test_schema:
test=# \d test_schema.
Table "test_schema.test_table"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
Table "test_schema.test_table_2"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
etc...

This is old, but I put exports in my alias for connecting to the db:
alias schema_one.con="PGOPTIONS='--search_path=schema_one' psql -h host -U user -d database etc"
And for another schema:
alias schema_two.con="PGOPTIONS='--search_path=schema_two' psql -h host -U user -d database etc"

key word :
SET search_path TO
example :
SET search_path TO your_schema_name;

quick solution could be:
SELECT your_db_column_name from "your_db_schema_name"."your_db_tabel_name";

if playing with psql inside docker exec it like this:
docker exec -e "PGOPTIONS=--search_path=<your_schema>" -it docker_pg psql -U user db_name

PostgreSQL 14 Debian
postgres#ovhswift:~$ psql
psql (14.0 (Debian 14.0-1.pgdg100+1))
Type "help" for help.
postgres=# create database test;
CREATE DATABASE
postgres=# \c test
You are now connected to database "test" as user "postgres".
test=# create schema tests;
CREATE SCHEMA
test=# \dt
Did not find any relations.
test=# create table pubtable (id integer);
CREATE TABLE
test=# create table tests.schematable (id integer);
CREATE TABLE
test=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | pubtable | table | postgres
(1 row)
test=# \dt tests.
Did not find any relation named "tests.".
test=# \dt tests
Did not find any relation named "tests".
test=# \dt 'tests.'
Did not find any relation named "tests.".
test=# \dt 'tests.*'
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+----------
tests | schematable | table | postgres
(1 row)
test=# \dt 'tests*'
Did not find any relation named "tests*".
test=# \dt 'tests.*'
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+----------
tests | schematable | table | postgres
(1 row)
Ditto for \dv etc. to see the views in the schema

Related

Validating the data inside postgres table

I have launched a postgres container. By injecting script.sql at docker entrypoint, I created database, schema, tables and have inserted data into them. Docker Logs says that all table creation and data insertion is successful .
But How can I validate the data insertion? Below commands didn't help
List of relations
Schema | Name | Type | Owner
------------+----------------------+-------+----------
my_db | users | table | postgres
my_db | audit_log | table | postgres
my_db | config | table | postgres
(3 rows)
my_db=# SELECT * FROM my_db.users
my_db-# SELECT * FROM users
my_db-# SELECT * FROM my_db.users;
What is wrong here? Please help.
You should use
\c my_db
to connect to your database. And then:
SELECT * FROM users;
To query your table into your database.
It seems that you understood this part, but everything should be done using postgresql command line, so inside the docker container.

PostGIS type "geometry" doesn't exist when pg_dump copying database to server

Similar question to many that have already been asked, but I have yet to find a solution.
I'm copying a Postgres db from my local machine to a server using:
pg_dump -C -h localhost -U localuser dbname | psql -h remotehost -U remoteuser dbname
However, whenever I try to execute this, any tables with PostGIS geography columns are skipped and not copied over, and I'm left with the following error:
ERROR: type "<mydb>.geography" does not exist
Attempted solutions:
On this server, I have successfully installed PostGIS and created the relevant extensions:
mydb=# select postgis_version();
postgis_version
---------------------------------------
2.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
(1 row)
Additionally, geometry is a recognized data type:
mydb=# \dT *.geometry
List of data types
Schema | Name | Description
--------+----------+-----------------------------------------
public | geometry | postgis type: Planar spatial data type.
(1 row)
My search_path includes everything relevant:
mydb=# show search_path;
search_path
------------------------
mydb, public, postgis
and
mydb=# SELECT r.rolname, d.datname, rs.setconfig
FROM pg_db_role_setting rs
LEFT JOIN pg_roles r ON r.oid = rs.setrole
LEFT JOIN pg_database d ON d.oid = rs.setdatabase
WHERE r.rolname = 'mydb' OR d.datname = 'mydb';
rolname | datname | setconfig
---------+---------+----------------------
| mydb | {search_path=public}
(1 row)
My only guess as to what might be causing this headache is that the superuser on my local machine isn't the same name as the remote superuser. I.e., localuser and remoteuser don't match.
The rest of the answer assumes that the error you quote is the first error while restoring the dump. If not, it might be the consequence of an earlier error (e.g., failure to CREATE EXTENSION postgis).
If PostGIS is installed on both servers, the message suggests that it is installed in different schemas on both databases.
Examine the result of
\dx postgis
on both databases to check.
Since PostGIS is not a relocatable extension, you have to drop and re-create it to move it to a different schema.

Restrict user to one schema in PostgreSQL?

Is it possible in PostgreSQL to create a user that can only access a single schema?
Here is what I tried:
REVOKE ALL ON DATABASE testdb FROM public;
GRANT CONNECT ON DATABASE testdb TO testuser;
When I connect as testuser indeed I cannot access the actual data:
> SELECT * FROM some_table;
ERROR: permission denied for relation some_table
However, I can still list all the tables, etc. in all the other schemas:
SELECT * FROM pg_tables;
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
--------------------+-------------------------------------------+------------+------------+------------+----------+-------------+-------------
test2 | foo | postgres | | t | f | f | f
test2 | bar | postgres | | t | f | f | f
...
It is impossible to configure PostgreSQL so that a user can only see those objects in the system catalogs for which he or she has permissions.
If you need such a setup, you should create a database per user.
I was able to do this like so:
GRANT USAGE ON SCHEMA schema_name TO user_name;
ALTER USER user_name SET search_path = schema_name;
The ALTER USER statement like this is a way of permanently setting the search path for schemas the way you would set the schema search path of an individual sessions with
SET SEARCH_PATH= schema_name_1, schema_name_2;

PostgreSQL permissions explained

Please explain the output of the \z command in PostgreSQL. I understand the permission, I read the documentation, but somehow I missed the interpretation of the output of \z.
datastore_default=> \z
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+-----------------+-------+-----------------------------------+--------------------------
public | _table_metadata | view | ckan_default=arwdDxt/ckan_default+|
| | | datastore_default=r/ckan_default +|
| | | readonlyuser=r/ckan_default +|
public | foo | table | ckan_default=arwdDxt/ckan_default+|
| | | datastore_default=r/ckan_default +|
| | | readonlyuser=r/ckan_default +|
Somehow readonlyuser seems to be able to read tables foo and _foo but in practice it cannot. Both commands return an error:
sudo -u postgres psql -d datastore_default -U readonlyuser -c 'SELECT * FROM foo'
sudo -u postgres psql -d datastore_default -U readonlyuser -c 'SELECT * FROM public.foo'
ERROR: permission denied for schema public
LINE 1: SELECT * FROM public.foo
Edit: apparently I had a poor understanding of how database and schema permissions work. First of all only the db admin (user postgres) or the owner of the database (in my case user ckan_default) can grant other users privileges on a specific database. The schema is only at a database level, so it's ok that I added readonlyuser the permission to see the public schema, it cannot select from other databases anyway.
The error says permission denied for schema public (emphasis mine)
You need to give readonlyuser rights on schema public:
GRANT USAGE ON SCHEMA public TO readonlyuser;
The contents of the ACL is explained on this page. The most relevant part quoted here:
rolename=xxxx -- privileges granted to a role
=xxxx -- privileges granted to PUBLIC
r -- SELECT ("read")
w -- UPDATE ("write")
a -- INSERT ("append")
d -- DELETE
D -- TRUNCATE
x -- REFERENCES
t -- TRIGGER
X -- EXECUTE
U -- USAGE
C -- CREATE
c -- CONNECT
T -- TEMPORARY
arwdDxt -- ALL PRIVILEGES (for tables, varies for other objects)
* -- grant option for preceding privilege
/yyyy -- role that granted this privilege
The + are part of the way psql formats the result, they are not part of the value.

PostgreSQL command does not list all schemas

I'm wondering why \d only lists tables in the public schema? I have another schema in the database, sps, but those tables are not listed...
# psql -p 5432 -U postgres -h localhost myDB
Password for user postgres:
psql (9.1.5)
Type "help" for help.
myDB=# \d
List of relations
Schema | Name | Type | Owner
--------+----------------------------+----------+----------
public | tableA | table | postgres
public | tableB | table | postgres
public | tableC | table | postgres
public | table_col_seq | sequence | postgres
(4 rows)
You need to change your search_path. In psql use \dn and then build your search_path:
SET search_path = schema1,schema2,public;
I had this problem i Intellij IDEA Database tab.
I got the soultion doing :
Data Sources and Drivers -> YOUR_DATA_SOURCE -> Schemas -> Check "All databases"