I am looking for a pgsql query to pull the last PK for all tables given the db schema. Need this for my db migration work.
            Asked
            
        
        
            Active
            
        
            Viewed 453 times
        
    1 Answers
0
            
            
        You can do this with a variation of a dynamic row count query:
with pk_list as (
  select tbl_ns.nspname as table_schema, 
         tbl.relname as table_name,
         cons.conname as pk_name, 
         col.attname as pk_column
  from pg_class tbl
    join pg_constraint cons on tbl.oid = cons.conrelid and cons.contype = 'p'
    join pg_namespace tbl_ns on tbl_ns.oid = tbl.relnamespace 
    join pg_attribute col on col.attrelid = tbl.oid and col.attnum = cons.conkey[1]
    join pg_type typ on typ.oid = col.atttypid
  where tbl.relkind = 'r' 
    and cardinality(cons.conkey) = 1 -- only single column primary keys
    and tbl_ns.nspname not in ('pg_catalog', 'information_schema') 
    and typ.typname in ('int2','int4','int8','varchar','numeric','float4','float8','date','timestamp','timestamptz')
    and has_table_privilege(format('%I.%I', tbl_ns.nspname, tbl.relname), 'select')
), maxvals as (
  select table_schema, table_name, pk_column, 
          (xpath('/row/max/text()',
             query_to_xml(format('select max(%I) from %I.%I', pk_column, table_schema, table_name), true, true, ''))
          )[1]::text as max_val
  from pk_list
) 
select table_schema, 
       table_name, 
       pk_column, 
       max_val
from maxvals;
The first CTE (pk_list ) retrieves the name of the primary key column for each "user" table (that is: tables that are not system tables)
The second CTE (maxvals) then creates a select statement that retrieves the max value for each PK column from the first CTE and runs that query using query_to_xml(). The xpath()  function is then used to parse the XML and return the max value as a text value (so it's possible to mix numbers and varchars)
The final select then simply displays the result from that.
The above has the following restrictions:
- Only single-column primary keys are considered
- It only deals with data types that support using max()on them (e.g. UUID columns are not included)
 
    
    
        Community
        
- 1
- 1
- 
                    Cool! that helps a lot! – EuJinn Ng Oct 24 '19 at 08:18
