Is it possible to define in which schema new tables get created by default? (Referred by "unqualified table names".)
I've seen some details about using the "search path" in Postgres, but I think it only works while retrieving data, not creating.
I have a bunch of SQL scripts, which create many tables. Instead of modifying the scripts, I want to set the database create tables in a specific schema by default - when they have unqualified names.
Is this possible?
search_path
?[...] tables are often referred to by unqualified names, which consist of just the table name. The system determines which table is meant by following a search path, which is a list of schemas to look in.
Bold emphasis mine. This explains identifier resolution.
The “current schema” (or “default schema”) is, per documentation:
The first schema named in the search path is called the current schema. Aside from being the first schema searched, it is also the schema in which new tables will be created if the
CREATE TABLE
command does not specify a schema name.
Bold emphasis mine. The system schemas pg_temp
(schema for temporary objects of the current session) and pg_catalog
are automatically part of the search path and searched first, in this order. The manual:
pg_catalog
is always effectively part of the search path. If it is not named explicitly in the path then it is implicitly searched before searching the path's schemas. This ensures that built-in names will always be findable. However, you can explicitly placepg_catalog
at the end of your search path if you prefer to have user-defined names override built-in names.
Bold emphasis as per original. And pg_temp
comes before that, unless it's put into a different position.
There are various ways to set the runtime variable search_path
.
Set a cluster-wide default for all roles in all databases in postgresql.conf
(and reload). Careful with that!
search_path = 'blarg,public'
The shipped default for this setting is:
search_path = "$user",public
The first element specifies that a schema with the same name as the current user is to be searched. If no such schema exists, the entry is ignored.
Set it as default for one database:
ALTER DATABASE test SET search_path = blarg,public;
Set it as default for the role you connect with (effective cluster-wide):
ALTER ROLE foo SET search_path = blarg,public;
Or even (often best!) as default for a role in a database:
ALTER ROLE foo IN DATABASE test SET search_path = blarg,public;
Write the command at the top of your script. Or execute it in your DB session:
SET search_path = blarg,public;
Set a specific search_path
for the scope of a function (to be safe from malicious users with sufficient privileges). Read about Writing SECURITY DEFINER
Functions Safely in the manual.
CREATE FUNCTION foo() RETURNS void AS
$func$
BEGIN
-- do stuff
END
$func$ LANGUAGE plpgsql SECURITY DEFINER
SET search_path=blarg,public,pg_temp;