Postgres query fails without schema - postgresql

THis doesn't work, resulting in ERROR: relation "user" does not exist
select * from "user"
This one does
select * from "dbo"."user"

Tables that aren't schema-qualified are searched for on the search_path. This doesn't search every schema. By default it only searches:
pg_catalog (implicitly always first, not listed on search_path)
pg_temp tablespaces (implicit, not listed on search_path)
A schema named after the current user, listed as $user in search_path
The public schema
If you want PostgreSQL to look elsewhere you have to modify the search_path to tell it so, or fully schema-qualify the name.
See the PostgreSQL manual on search_path.
Also, note that unlike some databases the name dbo has no particular significance in PostgreSQL. It's just another name.

Related

Replacing schema name when sharing sql script with other users

When collaborating with colleagues I need to change the schema name every time I receive a SQL script (Postgres).
I am only an ordinary user of a corporate database (no permissions to change anything). Also, we are not allowed to create tables in PUBLIC schema. However, we can use (read-only) all the tables from BASE schema.
It is cumbersome for the team of users, where everybody is creating SQL scripts (mostly only for creating tables), which need to be shared amongst others. Every user has its own schema.
Is it possible to change the script below, where I will share the script to another user without the need for the other user to find/replace the schema, in this case, user1?
DROP TABLE IF EXISTS user1.table1;
CREATE TABLE user1.table1 AS
SELECT * FROM base.table1;
You can set the default schema at the start of the script (similar to what pg_dump generates):
set search_path = user1;
DROP TABLE IF EXISTS table1;
CREATE TABLE table1 AS
SELECT * FROM base.table1;
Because the search path was change to contain user1 as the first schema, tables will be searched in that schema when dropping and creating. And because the search path does not include any other schema, no other schema will be consulted.
If you
However the default search_path is "$user", public which means that any unqualified table will be searched or created in a schema with the same name as the current user.
Caution
Note that a DROP TABLE will drop the table in the first schema found in that case. So if table1 doesn't exist in the user's schema, but in the public schema, it would be dropped from the public schema. So for your use-case setting the path to exactly one schema might be more secure.

Accessing table without using schema name

I am new with DB2.
I am not able to get data from a table without using the schema name. If I use a schema name with table name, I am able to fetch data.
Example:
SELECT * FROM TABLE_NAME;
It is giving me error, while
SELECT FROM SCHEMA_NAME.TABLE_NAME;
is fetching a result.
What do I have to set up not to always have to use the schema name?
By default, your username is used as the schema name for unqualified object names. You can see the current schema with, e.g. VALUES CURRENT SCHEMA. You can change the current schema for you current session with SET SCHEMA new_schema_name, or via e.g. a JDBC connection parameter. Most query tools also have a place to specify/change the current schema.
See the manual page for SET SCHEMA https://www.ibm.com/support/knowledgecenter/en/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0001016.html
The full rules for the qualification of unqualified objects is here https://www.ibm.com/support/knowledgecenter/en/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000720.html#r0000720__unq-alias
E.g.
Unqualified alias, index, package, sequence, table, trigger, and view names are implicitly qualified by the default schema.
However, you can create a public alias for a table, module or sequence if you wish to be able to reference it regardless of your CURRENT SCHEMA value.
https://www.ibm.com/support/knowledgecenter/SSEPGG_11.5.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000910.html
(P.S. all the above assumes you are using Db2 LUW)
Try using SET SCHEMA to set the default schema to be used in the session:
SET SCHEMA SCHEMA_NAME;
SELECT * FROM TABLE_NAME;
When using DBeaver - right click on connection > Connection Settings > Initialization, and select your default DB and default Schema:
After that, open your SQL Script and select Active DB:

Set deafult schema while querying in pgAdmin 4 with query tool

Whenever i have to execute sql commands in pgAdmin 4 i have to append schema_name with tables.
Eg :-
SELECT * FROM my_schema.users //where myschema is schema name
ORDER BY id ASC
Is there any way to execute sql commands in pgAdmin 4 without schema name, by setting a default schema in advance.
Some thing like this
SELECT * FROM programme
ORDER BY id ASC
- without specifying schema name with table.
Is there a way to set default schema in pgAdmin 4 for querying in sql tool?
You can do it in 2 ways:
SET search_path = my_schema, "$user", public; -- For current session only
ALTER ROLE your_role SET search_path = my_schema, "$user", public; -- Persistent, for role
You can also set it for whole database, same way as for role.
EDIT: Just to explain what this does - it will change where and in what order Postgres will search for objects matching object identifiers that did not get prefixed with schema name.
You might need also to restart pgAdmin4 in order for the search_path to start working. At least it was my case.
A good double check if the search_path was set in pgAdmin4 is to go to:
Login/Group Roles -> Right click on the user (by default it is 'postgres') -> Properties -> Parameters tab. Here you should see your new parameter 'search_path' with the value 'your_schema_name'.

Additional module citext is installed, but type "citext" not found?

I'm trying to run an inline query on my database - which has the citext extension installed (using CREATE EXTENSION) - and yet the executed query keeps throwing this error when calling a function:
type "citext" does not exist
DO
LANGUAGE plpgsql
$$
DECLARE
_id INT;
BEGIN
SELECT * FROM "dbo"."MyFunction"(_id, 'some value'::citext);
END;
$$;
If I omit the ::citext cast, it says:
function dbo.MyFunction(integer, unknown) does not exist.
You might need to add explicit type casts.
The citext extension is added, is part of the schema and works with other queries. This keeps coming up randomly - what causes it?
EDIT:
The installed extensions:
extname | nspname
----------+-----------
plpgsql | pg_catalog
citext | public
uuid-ossp | public
Search path:
show search_path;
search_path
-----------
dbo
As suspected, the extension schema is missing from the search_path. Read up on how to set the schema search path in this related answer:
How does the search_path influence identifier resolution and the "current schema"
It seems like your client sets search_path = dbo on connection, which seems to be misconfigured. dbo is something we see a lot for SQL Server (used to be the default schema here or still is?), very untypical for Postgres. Not sure how you got there.
Why do table names in SQL Server start with "dbo"?
One alternative would be to install extensions into the dbo schema as well:
Best way to install hstore on multiple schemas in a Postgres database?
You can even move (most) extensions to a different schema:
ALTER EXTENSION citext SET SCHEMA dbo;
But I would advice to install extensions to a dedicated schema and include it in the search_path.
Leave plpgsql alone in any case. It's installed by default and should should stay in pg_catalog.
One way or another, clean up the mess with varying search_path settings.
As for the second question: that's guided by the rules of Function Type Resolution. The call cannot be resolved, because citext does not have an implicit cast to text.
Related
Is there a way to disable function overloading in Postgres

Postgres not following search_path to locate tables

I'm not sure the exact point at which this starting happening ( I believe it may have been after launching pgadmin3 for the first time ). Basically this seemed to happen all of a sudden and everything seems to be configured correctly..
PostgreSQL seems to no longer be following the search_path to locate my tables.
\d
No relations found.
My search path has been set (persistently at that):
SHOW search_path;
"public, myschema1, myschema2"
(1 row)
Not only am I the owner of the tables in question, I have run:
GRANT ALL ON SCHEMA public to myusername;
GRANT ALL ON SCHEMA myschema1 to myusername;
GRANT ALL ON SCHEMA myschema2 to myusername;
The data is all there. I can see the schemas when running a \dn. I can also run queries if I fully qualify the schema and table names. The biggest issue is that already created functions that reference an unqualified table name won't work.
Can anyone think of something I might not have tried? Any thoughts as to what caused this issue to start happening?
Thanks for any help!
-hightech
Probably you entered search_path as one string
postgres=# set search_path to public, s1;
SET
postgres=# show search_path ;
search_path
-------------
public, s1
(1 row)
postgres=# set search_path to 'public, s1';
SET
postgres=# show search_path ;
search_path
--------------
"public, s1"
(1 row)
second setting is wrong and doesn't work.
I fixed a similar issue by GRANTing that user USAGE ON SCHEMA, logged on as the OWNER on that schema. Let me develop:
User story: I could reproduce this strange behaviour with Postgres 9.6, see console output below. How bizarre was that? I could \dt preprod.users, but \dt only will not issue anything! I could also SELECT on these tables, which was really confusing me.
(In search_path, note the space after the comma, automatically adjusted by PostgreSQL)
do_preprod=> -- I'm logged on as preprod_www_ro, a read-only user who belongs to readonly ROLE.
do_preprod=> SET search_path TO preprod,public;
SET
do_preprod=> SHOW search_path;
search_path
-----------------
preprod, public
(1 row)
do_preprod=> \dt
Did not find any relations.
do_preprod=> \dt users;
Did not find any relation named "users".
do_preprod=> \dt preprod.users;
List of relations
Schema | Name | Type | Owner
---------+-------+-------+-------------
preprod | users | table | preprod_www
(1 row)
Then, logged on as preprod_www (= schema owner), I GRANTed the readonly ROLE (preprod_www_ro's) the USAGE privilege.
do_preprod=> GRANT USAGE ON SCHEMA preprod TO readonly;
Then, back as preprod_www_ro, I could immediately see the relations with \dt, enjoying fully my search_path, without having to log out log back in.
I would have liked a clearer message from PostgreSQL in the first place, when issuing \dt, or \dt preprod.users: "No USAGE ON SCHEMA granted..." or something like that, as in fact that user COULD use it...but not entirely smoothly.