skip to Main Content

A query which accomplishes what is in the title would solve my problem.

My problem:

I want to extract column names and data types for a table. Here is my query for this:

SELECT
    column_name,
    data_type
FROM
    information_schema.columns
WHERE
    table_name = '<table_name>'
ORDER BY ordinal_position;

This works great, given that the table only occurs once in the whole database. If it occurs in multiple schemas, this query returns all the columns and data types for all tables of that name.

I know that I want only to deal with the first occurrence of this table in the search_path, i.e. the table whose schema appears first in the search_path. How do I extract that information, so I can then set a condition on the table_schema column of information_schema.columns in my query?

2

Answers


  1. Chosen as BEST ANSWER

    Thanks to @Bergi, who commented with the query to get the correct schema name.

    Here is the complete query which solves the problem I outlined in the question, using @Bergi's query as a subquery:

    SELECT
        column_name,
        data_type
    FROM
        information_schema.columns
    WHERE
        table_name = '<table_name>'
        AND table_schema = (SELECT relnamespace::regnamespace::text FROM pg_class where oid = '<table_name>'::regclass)
    ORDER BY ordinal_position;
    

  2. You can get the schemas from the search_path parameter as an array using the current_schemas() session info function. You could then join this against the information_schema.tables, add your name condition, order by the array index (from UNNEST(current_schemas(true)) WITH ORDINALITY), and LIMIT the result to the first row.

    An easier way to resolve a table name using the search path is to just use it, namely by converting the string to the respective table object identifier type. This can be done using a type cast '<table_name>'::regclass or a function call to_regclass('<table_name>') – the latter doesn’t throw an error when the table doesn’t exist. The result uniquely identifies a specific table in one of the search_path schemas, though getting the schema name from the oid is a bit cumbersome. You could directly query your table columns from the pg_attribute system table instead of information_schema.columns, though that requires you to be aware of things like attisdropped and there’s no direct equivalent to data_type.

    Instead, you could get the schema name from the pg_class system table:

    SELECT column_name, data_type
    FROM information_schema.columns
    WHERE (table_schema::regnamespace, table_name) = (
      SELECT relnamespace, relname
      FROM pg_class
      WHERE oid = to_regclass('<table_name>')
    )
    ORDER BY ordinal_position;
    

    or from the pg_identify_object function:

    SELECT column_name, data_type
    FROM information_schema.columns
    WHERE (table_schema, table_name) = (
      SELECT schema, name
      FROM pg_identify_object('pg_class'::regclass, to_regclass('<table_name>'), 0)
    )
    ORDER BY ordinal_position;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search