Anyone can Explain what is partition_position in all_tab_partitions.
And anyone can tell me what is conversion of this
SELECT partition_position
FROM all_tab_partitions tp
WHERE tp.table_owner = ? AND
tp.table_name = ? AND
tp.partition_name = ?
to Postgres.
ALL_TAB_PARTITIONS
Column
Datatype
Description
PARTITION_POSITION
NUMBER
Position of the partition within the table
I don't know how (if anyhow) it can be translated from Oracle to PostgreSQL.
You can convert oracle queries like below (maybe it's not like that but I think it helps you):
Postgres doesn't have partition_position column and should create manually based on table object id
WITH partition_info as (
SELECT nmsp_parent.nspname AS parent_schema,
parent.relname AS parent,
owner_parent.rolname AS parent_owner,
nmsp_child.nspname AS child_schema,
child.relname AS child,
owner_child.rolname AS child_owner,
row_number() OVER (PARTITION BY parent.relname ORDER BY child.oid) AS partition_position
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
JOIN pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
JOIN pg_authid owner_parent ON owner_parent.oid = parent.relowner
JOIN pg_authid owner_child ON owner_child.oid = child.relowner
)
SELECT partition_position
FROM partition_info
WHERE child_owner = ? -- table_owner
AND parent = ? -- partition_name
AND child = ? -- table_name
PostgreSQL doesn't have a concept of order in the list of partitions for a table, and indeed it wouldn't make sense in all cases. What if the partitioning key is a data type that doesn't have a total ordering, like polygon? I admit that that is an unusual data type to partition by, but it could be used with list partitioning.
Related
I have a many to many relation with three columns, (owner_id,property_id,ownership_perc) and for this table applies (many owners have many properties).
So I would like to find all the owner_id who has many properties (property_id) and connect them with other three tables (Table 1,3,4) in order to get further information for the requested result.
All the tables that I'm using are
Table 1: owner (id_owner,name)
Table 2: owner_property (owner_id,property_id,ownership_perc)
Table 3: property(id_property,building_id)
Table 4: building(id_building,address,region)
So, when I'm trying it like this, the query runs but it returns empty.
SELECT address,region,name
FROM owner_property
JOIN property ON owner_property.property_id = property.id_property
JOIN owner ON owner.id_owner = owner_property.owner_id
JOIN building ON property.building_id=building.id_building
GROUP BY owner_id,address,region,name
HAVING count(owner_id) > 1
ORDER BY owner_id;
Only when I'm trying the code below, it returns the owner_id who has many properties (see image below) but without joining it with the other three tables:
SELECT a.*
FROM owner_property a
JOIN (SELECT owner_id, COUNT(owner_id)
FROM owner_property
GROUP BY owner_id
HAVING COUNT(owner_id)>1) b
ON a.owner_id = b.owner_id
ORDER BY a.owner_id,property_id ASC;
So, is there any suggestion on what I'm doing wrong when I'm joining the tables? Thank you!
This query:
SELECT owner_id
FROM owner_property
GROUP BY owner_id
HAVING COUNT(property_id) > 1
returns all the owner_ids with more than 1 property_ids.
If there is a case of duplicates in the combination of owner_id and property_id then instead of COUNT(property_id) use COUNT(DISTINCT property_id) in the HAVING clause.
So join it to the other tables:
SELECT b.address, b.region, o.name
FROM (
SELECT owner_id
FROM owner_property
GROUP BY owner_id
HAVING COUNT(property_id) > 1
) t
INNER JOIN owner_property op ON op.owner_id = t.owner_id
INNER JOIN property p ON op.property_id = p.id_property
INNER JOIN owner o ON o.id_owner = op.owner_id
INNER JOIN building b ON p.building_id = b.id_building
ORDER BY op.owner_id, op.property_id ASC;
Always qualify the column names with the table name/alias.
You can try to use a correlated subquery that counts the ownerships with EXISTS in the WHERE clause.
SELECT b1.address,
b1.region,
o1.name
FROM owner_property op1
INNER JOIN owner o1
ON o1.id_owner = op1.owner_id
INNER JOIN property p1
ON p1.id_property = op1.property_id
INNER JOIN building b1
ON b1.id_building = p1.building_id
WHERE EXISTS (SELECT ''
FROM owner_property op2
WHERE op2.owner_id = op1.owner_id
HAVING count(*) > 1);
I have this query to get the list of indexes on a table:
SELECT
ns.nspname as schema_name,
tab.relname as table_name,
cls.relname as index_name,
am.amname as index_type,
idx.indisprimary as is_primary,
idx.indisunique as is_unique
FROM
pg_index idx
INNER JOIN pg_class cls ON cls.oid=idx.indexrelid
INNER JOIN pg_class tab ON tab.oid=idx.indrelid
INNER JOIN pg_am am ON am.oid=cls.relam
INNER JOIN pg_namespace ns on ns.oid=tab.relnamespace
WHERE ns.nspname = #Schema AND tab.relname = #Name
It seems to be working right. But now I need a query for the list of columns and I'm having trouble understanding how the system views work.
Specifically what I'm looking for are:
[index name or id for matching to the first query]
Order in index
Column name
ascending or descending
sorted column or included column
Ideally I would like to get the above items for all indexes of a given table at one time.
Note that I'm looking for more than just the column names.
Use the system catalog information function pg_get_indexdef(index_oid) to get complete information (including the list of index expressions) - in a query against pg_index to get all indexes for a given table:
SELECT pg_get_indexdef(indexrelid) || ';' AS idx
FROM pg_index
WHERE indrelid = 'public.tbl'::regclass; -- optionally schema-qualified
Related:
Django/PostgreSQL varchar to UUID
Copy indexes from one table to another
If you rely on an unqualified table name (without schema) you depend on the current search_path setting and might get results for a table of the same name in a different schema.
Alternatively, you can join to pg_attribute by hand to get individual columns like demonstrated in these related answers:
How to get column attributes query from table name using PostgreSQL?
Find tables with multiple indexes on same column
Key ingredient is to join like this:
FROM pg_index idx
LEFT JOIN pg_attribute a ON a.attrelid = idx.indrelid
AND a.attnum = ANY(idx.indkey)
AND a.attnum > 0
The manual about pg_index.indkey:
This is an array of indnatts values that indicate which table columns
this index indexes. For example a value of 1 3 would mean that the
first and the third table columns make up the index entries. Key
columns come before non-key (included) columns. A zero in this array
indicates that the corresponding index attribute is an expression over
the table columns, rather than a simple column reference.
Adding AND a.attnum > 0 is not technically necessary as there is no a.attnum = 0. But it makes the query clearer and it won't hurt. The manual:
Ordinary columns are numbered from 1 up. System columns, such as oid, have (arbitrary) negative numbers.
Be aware, that there the "list of column names" can actually contain expressions, too. And since Postgres 11 there are also "included" columns (no expressions there). pg_get_indexdef() deals with all possible complications out of the box.
You can puzzle it together from the system catalogs, as Erwin Brandstetter detailed.
Here is a query that will return the information you want:
SELECT i.indexrelid::regclass AS indexname,
k.i AS index_order,
i.indnkeyatts,
coalesce(a.attname,
(('{' || pg_get_expr(
i.indexprs,
i.indrelid
)
|| '}')::text[]
)[k.i]
) AS index_column,
i.indoption[k.i - 1] = 0 AS ascending,
k.i <= i.indnkeyatts AS is_key
FROM pg_index i
CROSS JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS k(attnum, i)
LEFT JOIN pg_attribute AS a
ON i.indrelid = a.attrelid AND k.attnum = a.attnum
WHERE i.indrelid = 'schemaname.tablename'::regclass;
This query will only work from PostgreSQL v11 on (but there are no covering Indexes before v11).
Also, the query will fail if the indexed expression contains a comma; I don't know how to fix that.
Version 10.4
SELECT idx.indexrelid::regclass AS indexname,
k.i AS index_order,
--i.indnkeyatts,
coalesce(att.attname,
(('{' || pg_get_expr(
idx.indexprs,
idx.indrelid
)
|| '}')::text[]
)[k.i]
) AS index_column,
pg_index_column_has_property(idx.indexrelid,k.i::int,'asc') AS ascending,
k.i != -1 AS is_key
FROM pg_index idx
CROSS JOIN LATERAL unnest(idx.indkey) WITH ORDINALITY AS k(attnum, i)
LEFT JOIN pg_attribute AS att
ON idx.indrelid = att.attrelid AND k.attnum = att.attnum
How can I find all Views and Tables with rules which depend on a given Table?
I need this in order to find which views and tables I have to check if I want to alter/drop that given Table.
Get Views or Tables which refer to a given table TABLENAME:
SELECT cl_r.relname AS ref_table
FROM pg_rewrite AS r
JOIN pg_class AS cl_r ON r.ev_class=cl_r.oid
JOIN pg_depend AS d ON r.oid=d.objid
JOIN pg_class AS cl_d ON d.refobjid=cl_d.oid
WHERE cl_d.relkind IN ('r','v') AND cl_d.relname='TABLENAME'
GROUP BY cl_r.relname
ORDER BY cl_r.relname;
I did it by reversing the following answer: https://stackoverflow.com/a/4337615
If I understand correctly, you want the rules not the relations. If you want the custom defined ones you can:
SELECT * from pg_rules WHERE tablename = 'TABLENAME'
if you want to see the system defines ones (for examples the one from the views) you can:
SELECT
N.nspname AS schemaname,
C.relname AS tablename,
R.rulename AS rulename,
pg_get_ruledef(R.oid) AS definition
FROM (pg_rewrite R JOIN pg_class C ON (C.oid = R.ev_class))
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE C.relname = 'TABLENAME';
I just took the query from the definition of pg_rules that is actually a system view (with \d+ pg_rules), and changed the WHERE clause, that is normally:
WHERE r.rulename <> '_RETURN'::name;
I have a sequence called seque_post.
I need to find out in what table it's being used.
Is there a way to write a query that will give the table name?
I wrote this query to find the sequence:
select *
from pg_class
where relname like 'seque_post'
there is a filed there reltoastrelid which according to the manual gives:
OID of the TOAST table associated with this table, 0 if none. The TOAST table stores large attributes "out of line" in a secondary table.
but i'm not sure how to continue from here.. suggestions?
To find the table a sequence is "related" to, you can use something like this:
select seq_ns.nspname as sequence_schema,
seq.relname as sequence_name,
tab_ns.nspname as table_schema,
tab.relname as related_table
from pg_class seq
join pg_namespace seq_ns on seq.relnamespace = seq_ns.oid
JOIN pg_depend d ON d.objid = seq.oid AND d.deptype = 'a'
JOIN pg_class tab ON d.objid = seq.oid AND d.refobjid = tab.oid
JOIN pg_namespace tab_ns on tab.relnamespace = tab_ns.oid
where seq.relkind = 'S'
and seq.relname = '[your sequence name]'
and seq_ns.nspname = 'public';
Just to complete the picture:
The other way round (looking up a sequence for a column) is easier, because Postgres has a function to find the sequence for a column:
select pg_get_serial_sequence('public.some_table', 'some_column');
The key catalog here is the rather versatile pg_depend, which can connect basically any two items of any sort.
The ::regclass cast is a magic trick for converting to and from oids, which allows you to look up something like this, with no joins (but possible ambiguities):
select
D.refobjid::regclass, -- the target table name
D.* -- see docs for meaning of other columns
from
pg_depend as D
where
-- source is a relation (in this case, a sequence)
D.classid = 'pg_catalog.pg_class'::regclass
-- target is also a relation (in this case, a table)
and D.refclassid = 'pg_catalog.pg_class'::regclass
-- source is the sequence you're looking for, fully qualified name
and D.objid = 'public.seque_post'::regclass
Try this using pg_depend instead of pg_class:
SELECT d.refobjid::regclass, a.attname
FROM pg_depend d
JOIN pg_attribute a ON a.attrelid = d.refobjid AND a.attnum = d.refobjsubid
WHERE d.objid = 'public."seque_post"'::regclass;
If you add the join to pg_attribute then you even have the column name that uses the sequence.
The ::regclass cast can be used to magically convert object identifiers to relation names.
Hope that helps.
It seems an easy question but I am comparing a table contain random tables and columns with syscolumns
this query will give me the missing columns
select object_name(syscolumns.id) , syscolumns.name
from syscolumns
where not exists
(select 1
from CHECKINGTABLE
where object_name(CHECKINGTABLE.id) = object_name(syscolumns.id)
and CHECKINGTABLE.name=syscolumns.name)
and object_name(syscolumns.id) ='TAB1'
but in such way it will give me wrong results
select object_name(syscolumns.id) , syscolumns.name
from syscolumns , CHECKINGTABLE
where not exists
(select 1
from CHECKINGTABLE
where object_name(CHECKINGTABLE.id) = object_name(syscolumns.id)
and CHECKINGTABLE.name=syscolumns.name)
and object_name(syscolumns.id) =object_name(CHECKINGTABLE.id)
what I am doing wrong ? I want a query to compare a table I own with syscolumns to identify the missing data in my table
You could try the following. I do not have an ASE DB at hand but the syntax should be correct I hope.
SELECT syscolumns.id , syscolumns.name
FROM syscolumns LEFT OUTER JOIN CHECKINGTABLE
ON (CHECKINGTABLE.id = syscolumns.id
AND CHECKINGTABLE.name=syscolumns.name)
WHERE CHECKINGTABLE.name IS NULL