14

I can run the following line:

ALTER SEQUENCE seqName OWNED BY table.id;

How can I get the 'owner' set by OWNED BY for a sequence (in this case: table.id)?

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
johnlemon
  • 20,761
  • 42
  • 119
  • 178
  • Upon re-reading the question, I understand now that you want to get the **table and column "owning" the sequence**, rather than the role "owning" it. I edited the title accordingly. Please roll back if I misunderstood. – Erwin Brandstetter Jul 15 '13 at 01:10

5 Answers5

18

You may use following query:

select s.relname as seq, n.nspname as sch, t.relname as tab, a.attname as col
from pg_class s
  join pg_depend d on d.objid=s.oid and d.classid='pg_class'::regclass and d.refclassid='pg_class'::regclass
  join pg_class t on t.oid=d.refobjid
  join pg_namespace n on n.oid=t.relnamespace
  join pg_attribute a on a.attrelid=t.oid and a.attnum=d.refobjsubid
where s.relkind='S' and d.deptype='a'

It returns all sequences with owner information. Just filter them in WHERE clause and that's it.

alexius
  • 2,501
  • 20
  • 21
12

Get the "owning" table and column

ALTER SEQUENCE seqName OWNED BY table.id;

Your ALTER SEQUENCE statement causes an entry in the system catalog pg_depend with the dependency type (deptype) 'a' and a refobjsubid greater than 0, pointing to the attribute number (attnum) in pg_attribute. With that knowledge you can devise a simple query:

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."seqName"'::regclass  -- your sequence here
AND    d.refobjsubid > 0
AND    d.classid = 'pg_class'::regclass;
  • Double quotes ("") are only needed for otherwise illegal names (mixed case, reserved words, ...).

  • No need to assert that refclassid is of type regclass since the join to pg_attribute does that automatically.
    No need to assert that the sequence is a sequence since schema-qualified object names are unique across the database.
    No need to join to pg_class or pg_namespace at all.

  • The schema name is only needed to disambiguate or if it's not in the search_path.
    The same table name (or sequence name for that matter) can be used in multiple schemas. A cast to the object identifier type regclass observes the current search_path to pick the best match if you omit the schema qualification. If the table is not visible, you get an error message.

  • What's more, a regclass type is displayed as text to the user automatically. (If not, cast to text.) The schema-name is prepended automatically where necessary to be unambiguous in your session.

Get the actual "owner" (the role)

To get the role owning a specific sequence, as requested:

SELECT c.relname, u.usename 
FROM   pg_class c
JOIN   pg_user  u ON u.usesysid  = c.relowner
WHERE  c.oid = '"seqName"'::regclass;  -- your sequence here
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Same as previous comment. @PavelStehule if you have PostGIS in your database there is dependencies store in `pg_depend` and `pg_class` contains `relkind = 'i'` for spatial index. I fix this query with `INNER JOIN pg_class c ON c.oid = d.objid AND c.relkind = 'S'` – GeoStoneMarten May 30 '22 at 10:26
  • in fact I don't understrand why `pg_namespace` and `pg_class` is not necessary because the objective can be set all sequences owner and if you are postgres user you are permission on pg_toast and it return result with this query – GeoStoneMarten May 30 '22 at 11:49
  • 1
    @GeoStoneMarten: Pavel's comment is already implemented by `AND d.classid = 'pg_class'::regclass;` I didn't understand your second comment. – Erwin Brandstetter May 30 '22 at 13:41
  • OK. it work fine only if you specify only one sequence. If I remove an element of where clause, there is others elements. Not only sequence but fields use in spatial index or in pg_toast if namespace if not dismiss – GeoStoneMarten May 30 '22 at 14:36
  • 1
    @GeoStoneMarten: This question is about a single sequence. Consider starting a new question if you have a different case that needs a different solution. You can always reference this one for context. – Erwin Brandstetter May 30 '22 at 14:41
4

I was able to list the table and corresponding sequence for a particular column using the following SQL statement:

SELECT   table_schema
       , table_name 
       , column_name
       , LTRIM(RTRIM(RTRIM(column_default, '::regclass)'),''''),'nextval(''') AS SEQUENCE_NAME
FROM information_schema.columns
WHERE  column_default like '%nextval%'; 
Sashank Bhogu
  • 659
  • 7
  • 6
  • 1
    Thanks, that worked for me, but i needed to add an extra LTRIM otherwise it would cut off the first letter of sequence name: `SELECT table_schema , table_name , column_name , LTRIM(LTRIM(RTRIM(RTRIM(column_default, '::regclass)'),''''),'nextval('), '''') AS SEQUENCE_NAME FROM information_schema.columns WHERE column_default like '%nextval%'; ` – Arthur Mastropietro Aug 29 '22 at 23:34
  • Thank you this was the only answer here that worked! There is an issue with my pg_depend table causing it to have some wrong dependency ids so the normal solution caused a major issue for me during my last migration. – Daniel Marcus Jan 14 '23 at 21:51
2
SELECT c.relname,u.usename 
  FROM pg_class c, pg_user u
 WHERE c.relowner = u.usesysid and c.relkind = 'S'
   AND relnamespace IN (
    SELECT oid
      FROM pg_namespace
     WHERE nspname NOT LIKE 'pg_%'
       AND nspname != 'information_schema'
    ); 
A.H.
  • 63,967
  • 15
  • 92
  • 126
Yuri Levinsky
  • 1,515
  • 2
  • 13
  • 26
  • 1
    This works, because sequences "OWNED BY" a table must have the same owner as the table - according to the [docs](http://www.postgresql.org/docs/current/interactive/sql-altersequence.html). – A.H. Jul 14 '13 at 21:39
0

I use that query for get all queries.

Change CTE to filter the result

WITH table_with_sequence as (
SELECT
    d.refobjid::regclass::text tablename,
    c.relname::text sequencename,
    np.nspname::text schemaname,
    a.attname::text attname,
    u.usename::text
FROM
    pg_depend d
    INNER JOIN pg_class c ON c.oid = d.objid
        AND c.relkind = 'S'
    INNER JOIN pg_namespace np ON np.oid = c.relnamespace
        AND (np.nspname NOT LIKE 'pg_%'
            AND np.nspname != 'information_schema')
        INNER JOIN pg_user u ON u.usesysid = c.relowner
        INNER JOIN pg_attribute a ON a.attrelid = d.refobjid
            AND a.attnum = d.refobjsubid
)

SELECT
    'ALTER SEQUENCE '|| QUOTE_LITERAL(QUOTE_IDENT(schemaname) || '.' || QUOTE_IDENT(sequencename)) ||' OWNED BY ' || tablename || '.' || QUOTE_IDENT(attname)
FROM table_with_sequence 
GeoStoneMarten
  • 533
  • 1
  • 7
  • 19