【问题标题】:How to query for a table's primary keys in Redshift如何在 Redshift 中查询表的主键
【发布时间】:2016-09-30 07:21:52
【问题描述】:

我尝试使用 Postgresql wiki (https://wiki.postgresql.org/wiki/Retrieve_primary_key_columns) 上建议的代码:

SELECT a.attname, format_type(a.atttypid, a.atttypmod) AS data_type
FROM   pg_index i
JOIN   pg_attribute a ON a.attrelid = i.indrelid
                     AND a.attnum = ANY(i.indkey)
WHERE  i.indrelid = 'tablename'::regclass
AND    i.indisprimary;

不幸的是,它似乎在 Redshift 中不起作用。我得到这个错误:

ERROR:  op ANY/ALL (array) requires array on right side

是我做错了什么还是这又是一个红移异常?

任何帮助将不胜感激。

【问题讨论】:

  • 你使用什么 postgres 版本?另外:您要获取哪个表的索引?

标签: postgresql amazon-redshift


【解决方案1】:

在这个帮助下尝试: https://bitbucket.org/zzzeek/sqlalchemy/pull-request/6/sqlalchemy-to-support-postgresql-80/diff

SELECT attname column_name, attnotnull, 
  format_type(atttypid, atttypmod) as column_type, atttypmod,
  i.indisprimary as primary_key,
  col_description(attrelid, attnum) as description
FROM pg_attribute c
  LEFT OUTER JOIN pg_index i
  ON c.attrelid = i.indrelid AND i.indisprimary AND
  c.attnum = ANY(string_to_array(textin(int2vectorout(i.indkey)), ' '))
where c.attnum > 0 AND NOT c.attisdropped AND c.attrelid = :tableOid
order by attnum

【讨论】:

    【解决方案2】:

    Redshift 不强制执行主键 http://docs.aws.amazon.com/redshift/latest/dg/t_Defining_constraints.html 的概念,但身份属性可用于设置唯一性。 (更多信息http://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html

    现有表的详细信息,可以使用如下查询

    select column_name, is_nullable, data_type, character_maximum_length 
    from information_schema.columns 
    where table_schema='schema_name' 
    and table_name='table_name' 
    order by ordinal_position
    

    【讨论】:

    • re “Redshift 没有主键的概念”这是不正确的;它们只是没有强制执行,但您链接到的页面实际上建议您定义它们。
    • 据我所知,上述查询实际上并没有对表进行限制。
    【解决方案3】:

    Redshift 没有主键http://docs.aws.amazon.com/redshift/latest/dg/t_Defining_constraints.html 的概念,但可以使用身份属性来设置唯一性。 (更多信息http://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html

    这不是真的。

    Redshift 不强制执行主键约束,但它们可以通过其他方式使用。它们在自动化数据管道或数据质量检查时很有用。在设计星型模式时,redshift 也推荐使用它们,因为它们被查询优化器用作提示。 https://aws.amazon.com/blogs/big-data/optimizing-for-star-schemas-and-interleaved-sorting-on-amazon-redshift/

    这是获取表主键的一种方法:

    SELECT
      schemaname,
      tablename,
      replace(substr(ddl, POSITION('(' IN ddl)+1 ),')','') primary_key
    FROM
      admin.v_generate_tbl_ddl
    WHERE
      schemaname = 'schema'
      AND tablename='table'
      AND upper(ddl) LIKE '%PRIMARY%';
    

    视图admin.v_generate_tbl_ddl的代码在这里:https://github.com/awslabs/amazon-redshift-utils/tree/master/src/AdminViews

    【讨论】:

    • 这个答案似乎假设 'primary' 不是任何列名中的子字符串。
    【解决方案4】:

    您可以使用以下 sql 获取架构“schemaname”中表“tablename”的主键列表

    SELECT
      att.attname
    FROM pg_index ind, pg_class cl, pg_attribute att
    WHERE 
      cl.oid = 'schemaname."tablename"'::regclass 
      AND ind.indrelid = cl.oid 
      AND att.attrelid = cl.oid
      and att.attnum = ANY(string_to_array(textin(int2vectorout(ind.indkey)), ' '))
      and attnum > 0
      AND ind.indisprimary
    order by att.attnum;
    

    【讨论】:

      【解决方案5】:

      这比INFORMATION_SCHEMA 更容易做到:

      select TC.column_name
      from information_schema.table_constraints AS TC
      inner join information_schema.key_column_usage AS KCU
        on KCU.constraint_catalogue = TC.constraint_catalogue
        and KCU.constraint_schema = TC.constraint_schema
        and KCU.constraint_name = TC.constraint_name
      where TC.constraint_type = 'PRIMARY KEY'
      and TC.table_schema = '<my schema>'
      and TC.table_name = '<my table>'
      order by KCU.ordinal_position
      

      是的,这适用于 Redshift。

      【讨论】:

      • 同意要容易得多,谢谢@dsz 注意,我必须将constraint_catalogue 更改为美国拼写constraint_catalog,并且在TC 中找不到column_name,因此将其更改为来自key_column_usage .
      • 遗憾的是我发现information_schema.table_constraints并没有讲完整的故事,但是我找到了一个可靠的方法,请参阅stackoverflow.com/a/55242160/1335793
      【解决方案6】:

      dsz 的回答对我不起作用,但非常接近! (必须更改“catalogue”的拼写,从 key_column_usage 中选择而不是 table_constraints,并在连接中添加一个额外的和)

      这对我来说适用于 redshift 和 MySQL。尚未明确尝试过 Postgres,但应该可以:

      select KCU.table_schema, KCU.table_name, KCU.column_name
      from information_schema.table_constraints AS TC
      inner join information_schema.key_column_usage AS KCU
       on KCU.constraint_catalog = TC.constraint_catalog
       and KCU.constraint_schema = TC.constraint_schema
       and KCU.table_name = TC.table_name
       and KCU.constraint_name = TC.constraint_name
      where TC.constraint_type = 'PRIMARY KEY'
      and TC.table_schema = '<my schema>'
      and TC.table_name = '<my table>'
      order by KCU.ordinal_position;
      

      【讨论】:

        【解决方案7】:

        遗憾的是,ISO 标准 information_schema 视图并不能说明 Redshift 的全部情况。我怀疑这些约束没有在 information_schema.table_constraints 中列出,因为它们没有在 Redshift 中强制执行。

        总之有办法

        AWS 提供了一个 github 存储库,其中包含许多管理工具、实用程序和视图。 观看次数为here

        其中一个观点是v_generate_tbl_ddl

        此视图可以为您提供重新创建表的完整 DDL,包括指定 Primary Key

        我已经提取了视图的相关部分,它将为您提供主键。该视图的其他部分显示了如何获取 dist 键、排序键和其他有用的东西:

        SELECT 
            c.oid::bigint AS table_id, 
            n.nspname AS schemaname,
            c.relname AS tablename, 
             pg_get_constraintdef(con.oid)::character varying AS PRIMARYKEY /*AS ddl*/
        FROM pg_constraint con
        JOIN pg_class c ON c.relnamespace = con.connamespace AND c.oid = con.conrelid
        JOIN pg_namespace n ON n.oid = c.relnamespace
        WHERE c.relkind = 'r'::"char" AND pg_get_constraintdef(con.oid) !~~ 'FOREIGN KEY%'::text
        

        【讨论】:

          【解决方案8】:

          information_schema 并不适用于所有用户

          SELECT
              f.attname AS column_name
          FROM
              pg_catalog.pg_namespace n
          JOIN pg_catalog.pg_class c ON
              n.oid = c.relnamespace
          JOIN pg_catalog.pg_attribute f ON
              c.oid = f.attrelid
          JOIN pg_catalog.pg_constraint p ON
              p.conrelid = c.oid
              AND f.attnum = ANY (p.conkey)
          WHERE
              n.nspname = 'schema_name'
              AND c.relkind = 'r'
              AND c.relname = 'table_name'
              AND p.contype = 'p'
              AND f.attnum > 0
          ORDER BY
              f.attnum;
          

          【讨论】:

            猜你喜欢
            • 2022-10-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多