From https://stackoverflow.com/a/17943883/156458
in both Postgres and the SQL Standard we have this containment
hierarchy:
A computer may have one cluster or multiple.
A database server is a cluster.
A cluster has [catalogs][8]. ( Catalog = Database )
Catalogs have [schemas][9]. (Schema = [namespace][10] of tables, and security boundary)
Schemas have [tables][11].
Tables have [rows][12].
Rows have values, defined by [columns][13].
In postgresql, I have a database called students and there is a table called student under it:
postgres=# \c students
You are now connected to database "students" as user "postgres".
students=# \dt;
public | student | table | postgres
I was wondering if database students is also a catalog?
Where is the schema between students and student?
In general, how can I list
all the catalogs and
all the schemas under a catalog, and
all the tables under a schema?
How can I show
the current catalog, and
the current schema?
Thanks.
In shortly, I usually explain to my junior teammate when they starting to research about PostgreSQL.
In PostgreSQL:
A Database Server is like an Industrial Zone, there will have many Databases-Cluster (Building)
Each Database-Cluster (Building) have many Databases. Those are like the floors in Building. The Databases is here as you call the Catalogs. Those Databases-Catalogs (floors) are quite independent with each other, you can not using others materials directly, you must use somethings just like stair, electric wire ... (in database is DBLINK).
Okay, next, each Database-Catalogs have many Schemas, which are like many Rooms on your floors. Those Schemas can use the material from each others.
Then, each Schemas have many cell elements such as Table, View, Function, Sequence .... All schemas have the same structure.
Now, back to you example:
students: is Database (which you call Catalogs)
public: is schema.
student: is table.
public | student | table | postgres is corresponding with schema | table | kind of table | owner of table
You can list:
catalogs (Database) by the command \l in psql or query select * from pg_database;
Schemas under a catalog by the command \dn in psql or query select * from information_schema.schemata;
Tables under a schemas by the query select * from pg_tables WHERE schemaname = 'Your schema';
You can show:
Current Database (Catalogs) by the query select current_database();
Current Schema by the query select current_schema;
Please pay attention that PostgreSQL have two system schema call information_schema and pg_catalog, this maybe make you confuse.
The pg_catalog is a system schema. More information.
The system catalogs are the place where a relational database management system stores schema metadata, such as information about tables and columns, and internal bookkeeping information. PostgreSQL's system catalogs are regular tables. You can drop and recreate the tables, add columns, insert and update values, and severely mess up your system that way. Normally, one should not change the system catalogs by hand, there are always SQL commands to do that. (For example, CREATE DATABASE inserts a row into the pg_database catalog — and actually creates the database on disk.) There are some exceptions for particularly esoteric operations, such as adding index access methods.
The information_schema is a system schema. More information.
The information schema consists of a set of views that contain information about the objects defined in the current database. The information schema is defined in the SQL standard and can therefore be expected to be portable and remain stable — unlike the system catalogs, which are specific to PostgreSQL and are modeled after implementation concerns. The information schema views do not, however, contain information about PostgreSQL-specific features; to inquire about those you need to query the system catalogs or other PostgreSQL-specific views.
I hope these information will help you clearly.
Related
I need to get complete list of external tables in db2 database. I have defined schema called DB2INST1. How to get complete list of external tables information using system tables?
The information lives in syscat.tables (documentation here) for Db2-LUW databases that support external tables, which have their PROPERTY column with value Y in position 27 of that column.
Example query returns the fully qualified name of external tables:
select trim(tabschema)||'.'||rtrim(tabname)
from syscat.tables
where substr(property,27,1)='Y'
with ur;
In general, the best and most reliable way to retrieve all information and to recreate the DDL statements for tables is to use the db2look tool. If you want to extract the metadata on your own, there are some catalog views to start with:
SYSCAT.TABLES holds the table information. Look for the PROPERTY column and check there if it is an external table.
SYSCAT.COLUMNS has the basic column information. But there are more related tables depending on types and attributes.
SYSCAT.EXTERNALTABLEOPTIONS shows the actual options for an external table, the things in addition to what makes a regular table.
There are many more tables to hold table properties, depending on the complexity of the table and column definitions.
In my multi-tenant postgres database, I have a schema per tenant for my data warehouse with the same tables in each.
I wish to create views and queries for these tables. If I were programming I would practice DRY and structure my code so that all of these were parameterised by the tenant. How do I achieve a similar structure in postgres?
You can run the same queries on different schemas just by changing search_path variable.
set search_path = schema1;
select * from orders; -- resolves to schema1.orders
set search_path = schema2;
select * from orders; -- resolves to schema2.orders
As for views, you will have create/drop them individually across all schemas just like you do with the tables.
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.
I am an Oracle DBA, new to PostgreSQL. I have a requirement to separate some modules data, so that one module will not have access to read the data of another module.
I read about the use of schemas in PostgreSql which is somewhat different than the use of it in Oracle. However seems like it is recommended to use the method of different schemas for separation and management - just like in Oracle.
However, when I create 2 schemas - connected to the same database and same user - I can do a select from the other schema's table.
That is, for example, if I have schema A owning table a, and schema B owning table b, when I set the search path to schema B I can do a select on schema’s A table a without any problem.
I couldn't find a way to revoke this privilege from schema B.
The only I could find then to separate access to data, is using different roles, that is to create role A with schema A, and role B with schema B. then I can grant and revoke access from user B in order for it to see what I want from role's A tables.
Is this correct? Am I missing something?
if I have schema A owning table a
A schema does not "own" a table in Postgres - a user does. This is the same as in Oracle - the difference (and maybe where your confusion arises) is that in Oracle in a regular user can't create tables outside of a schema that has the same name as the user account.
So if user arthur creates a table in schema_a and one in schema_b, both tables are owned by arthur - not "the schema".
If you used different schemas/users in Oracle to separate data and to prevent access to the other user's tables, then you need two users and two schemas in Postgres as well.
The default search_path in Postgres is setup in a way, that (unqualified) tables are always first searched (and created) in a schema with the same name as the user running the statement.
So if you create two users and a schema with the user's name for each user, you pretty much have the same setup as in Oracle:
create user arthur with password 'foobar';
create schema arthur authorization arthur; --<< this is what Oracle does "automatically"
create user bob with password 'verysecret';
create schema bob authorization bob;
Now, if bob creates a table, that table is created in the schema bob and is owned by the user bob. User arthur has not privileges to access that table.
If you never need to share data between those users (or schemas), then you can create two databases, create two users and let both users create everything in the public schema of "their" database.
I have a table X in tablespace T1 and a table Y in tabelspace T2.(Oracle DB)
I have to create a trigger in tablespace T1 that will,
on the event of updating a column C in table X,
update column D in table Y (tablespace T2).
Because they are in different tablespaces, my first question is can this be done at all?
And if yes then how it can be done? What privileges are required to do such a thing?
It has not so much to do with the tablespace. You do need privileges to insert into the table (and that particular column) though, and if the table Y is in another schema than the trigger, you need to use the qualified table name: . (In Oracle, the schemaname is the name of the user that owns the object)
CREATE TRIGGER aur_x
AFTER UPDATE OF c ON x
FOR EACH ROW
UPDATE schema_containing_y.Y SET D = ...
;
EDIT:
It just occurred to me that you might not be familiar with the distinction between schema and tablespace, so here's a short explanation. A tablespace is a logical storage container: it dedfines datafiles, growth characteristics, logging types etc. Tablespaces can then be used as to store data associated with schema objects (tables, indexes, views definitions, but also packages and stored procedure definitions etc).
A schema is a collection of objects (like tables, views, pacakages etc.) These objects are owned by a user, and as far as i am aware, in oracle the schema has an name identical to the user that owns the objects. THe objects rely on the storage provided by one or more tablespaces, but tablespaces themselves are not schema objects.
Typically, a schema is used to group functionally related objects (for example, you'd typically create one schema for one application). Tablespaces can also be created especially to store all objects of one application, but you can also create different tablespaces for tables with different characteristics.
Normally, application developers shouldn't worry too much about tablespaces. Your DBA will typically set them up in a way that is convenient for things like backup plan.