AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 90555
Accepted
John
John
Asked: 2015-01-30 06:30:02 +0800 CST2015-01-30 06:30:02 +0800 CST 2015-01-30 06:30:02 +0800 CST

PostgreSQL SELECT chave primária como "serial" ou "bigserial"

  • 772

Combinei uma maneira de determinar o que data_typeé data_typeusado na sintaxe ao criar uma nova tabela com base na página wiki do PostgreSQL .

Se houver algo errado com minha consulta, preciso realmente saber o que , em um determinado cenário, o prejudicaria no contexto explícito de ter uma consulta ou consultas a serem executadas em um banco de dados/tabela puramente de teste para modificar esse banco de dados/tabela, então execute isto query para testar quaisquer falsos positivos.

SELECT pg_attribute.attname, 
format_type(pg_attribute.atttypid, pg_attribute.atttypmod),
CASE 
WHEN format_type(pg_attribute.atttypid, pg_attribute.atttypmod)='bigint' THEN 'bigserial'
WHEN format_type(pg_attribute.atttypid, pg_attribute.atttypmod)='integer' THEN 'serial'
END AS type
FROM pg_index, pg_class, pg_attribute 
WHERE pg_class.oid = 'delete2'::regclass 
AND indrelid = pg_class.oid 
AND pg_attribute.attrelid = pg_class.oid 
AND pg_attribute.attnum = any(pg_index.indkey) 
AND indisprimary;

Aqui está uma tabela com uma chave primária que não retorna a chave primária com esta consulta:

CREATE TABLE delete_key_bigserial (
  test1 integer,
  id bigserial NOT NULL,
  col1 text,
  col2 text,
  test2 integer
);
postgresql primary-key
  • 1 1 respostas
  • 6659 Views

1 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2015-01-30T09:34:12+08:002015-01-30T09:34:12+08:00

    Sua consulta falharia porque o nome padrão de um número inteiro é "inteiro", não "int". Você pode evitar esse tipo de erro comparando o regtypeOID interno em vez de uma representação de texto. Muitos tipos de dados básicos têm vários nomes de alias, todos eles resolvem para o mesmo tipo registrado interno.
    Além disso, você pode simplificar e melhorar bastante:

    SELECT a.attname
         , CASE a.atttypid
             WHEN 'bigint'::regtype THEN 'bigserial'
             WHEN 'int'::regtype    THEN 'serial'
             ELSE format_type(a.atttypid, a.atttypmod)
           END AS type
    FROM   pg_index     i
    JOIN   pg_attribute a ON a.attrelid = i.indrelid
    WHERE  i.indrelid = 'tbl'::regclass 
    AND    i.indisprimary
    AND    a.attnum = ANY(i.indkey);
    

    Embora isso melhore a consulta, ainda não está fazendo o que você espera .

    Só porque uma coluna inteira é (parte da) chave primária, isso ainda não a torna uma serialcoluna. Aqui está uma avaliação detalhada do que serialé:

    • Renomear tabelas com segurança e limpeza que usam colunas de chave primária serial no Postgres?

    Você não encontra nada para a tabela apresentada, pois está baseando sua consulta em pg_index, que não tem nada a ver com tipos seriais. Uma série não precisa ser indexada, apenas as chaves primárias são indexadas.

    Soluções seguras

    Apenas detecte o tipo serial do PRIMARY KEY:

    SELECT a.attrelid::regclass::text, a.attname
         , CASE a.atttypid
             WHEN 'int'::regtype  THEN 'serial'
             WHEN 'int8'::regtype THEN 'bigserial'
             WHEN 'int2'::regtype THEN 'smallserial'
           END AS serial_type
    FROM   pg_attribute  a
    JOIN   pg_constraint c ON c.conrelid  = a.attrelid
                          AND c.conkey[1] = a.attnum 
    JOIN   pg_attrdef   ad ON ad.adrelid  = a.attrelid
                          AND ad.adnum    = a.attnum
    WHERE  a.attrelid = 'tbl'::regclass   -- table name, optionally schema-qualified
    AND    a.attnum > 0
    AND    NOT a.attisdropped
    AND    a.atttypid = ANY('{int,int8,int2}'::regtype[]) -- integer type
    AND    c.contype = 'p'                 -- PK
    AND    array_length(c.conkey, 1) = 1   -- single column
    AND    pg_get_expr(ad.adbin, ad.adrelid)
         = 'nextval('''
        || (pg_get_serial_sequence (a.attrelid::regclass::text, a.attname))::regclass
        || '''::regclass)';                -- col default = nextval from owned seq
    

    Não retorna nada se o PK não for do tipo serial.

    Dirigindo-se ao comentário de @jpmc26

    Uma verificação simplificada para apenas:

    pg_get_serial_sequence(attr.attrelid::regclass::text, attr.attname) IS NOT NULL
    

    verificaria apenas se existe uma sequência "de propriedade" da coluna, mas não se o padrão da coluna também está definido para extrair números da sequência. A documentação:

    A função provavelmente deveria ter sido chamada pg_get_owned_sequence; seu nome atual reflete o fato de que normalmente é usado com colunas serialou .bigserial


    Para mostrar TODAS as colunas com o tipo de dados adequado - substituído pelo serialtipo apropriado quando aplicável:

    SELECT a.attrelid::regclass::text, a.attname
         , CASE WHEN a.atttypid = ANY ('{int,int8,int2}'::regtype[])
              AND EXISTS (
                 SELECT FROM pg_attrdef ad
                 WHERE  ad.adrelid = a.attrelid
                 AND    ad.adnum   = a.attnum
                 AND    pg_get_expr(ad.adbin, ad.adrelid)
                      = 'nextval('''
                     || (pg_get_serial_sequence (a.attrelid::regclass::text
                                              , a.attname))::regclass
                     || '''::regclass)'
                 )
            THEN CASE a.atttypid
                    WHEN 'int'::regtype  THEN 'serial'
                    WHEN 'int8'::regtype THEN 'bigserial'
                    WHEN 'int2'::regtype THEN 'smallserial'
                 END
            ELSE format_type(a.atttypid, a.atttypmod)
            END AS data_type
    FROM   pg_attribute  a
    WHERE  a.attrelid = 'tbl'::regclass  -- table name, optionally schema-qualified
    AND    a.attnum > 0
    AND    NOT a.attisdropped
    ORDER  BY a.attnum;
    

    A verificação no padrão da coluna pode ser interrompida com configurações exóticas para search_path. Não testei todas as combinações.

    db<>mexa aqui

    • 9

relate perguntas

  • Chaves primárias de caractere x número inteiro

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve