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 / 313950
Accepted
sev
sev
Asked: 2022-07-01 06:32:21 +0800 CST2022-07-01 06:32:21 +0800 CST 2022-07-01 06:32:21 +0800 CST

Gerando um ID da sequência de chave primária sem adicionar uma linha

  • 772

Eu tenho as duas tabelas a seguir onde armazeno usuários e seus endereços. Tenho um problema relacionado com a ordem em que recebo e consigo guardar os dados do utilizador. A princípio, o usuário fornecerá apenas o endereço e, em seguida, será direcionado para um serviço externo. Para abrir este serviço, preciso fornecer meu ID de usuário interno. O serviço verifica seu endereço de e-mail e me envia a resposta.

CREATE TABLE IF NOT EXISTS public."user"
(
    id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
    email character varying COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY (id),
    CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE (email)
)

CREATE TABLE IF NOT EXISTS public.adresses
(
    id integer NOT NULL DEFAULT nextval('address_id_seq'::regclass),
    address character varying COLLATE pg_catalog."default" NOT NULL,
    "userId" integer,
    CONSTRAINT "PK_bec464dd8d54c39c54fd32e2334" PRIMARY KEY (id),
    CONSTRAINT "FK_35472b1fe48b6330cd349709564" FOREIGN KEY ("userId")
        REFERENCES public."user" (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)
  • Posso gerar o ID do usuário a partir da sequência de outra forma que não seja inserir um e-mail na tabela e, no final, inserir o ID e o e-mail ao mesmo tempo?
  • Posso salvar o endereço na tabela de endereços referenciando uma chave estrangeira que ainda não foi adicionada aos usuários?
postgresql sequence
  • 1 1 respostas
  • 118 Views

1 respostas

  • Voted
  1. Best Answer
    Vérace
    2022-07-01T11:36:44+08:002022-07-01T11:36:44+08:00

    Para responder a essa pergunta, fiz o seguinte (todo o código abaixo está disponível no violino aqui ):

    CREATE SEQUENCE user_id_seq;
    CREATE SEQUENCE address_id_seq;
    

    e as tabelas:

    CREATE TABLE user_
    (
        id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
        email character varying COLLATE pg_catalog."default" NOT NULL,
        CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY (id),
        CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE (email)
    );
    

    e

    CREATE TABLE address
    (
        id integer NOT NULL DEFAULT nextval('address_id_seq'::regclass),
        address character varying COLLATE pg_catalog."default" NOT NULL,
        user_id integer,
        CONSTRAINT "PK_bec464dd8d54c39c54fd32e2334" PRIMARY KEY (id),
        CONSTRAINT "FK_35472b1fe48b6330cd349709564" FOREIGN KEY (user_id)
            REFERENCES user_ (id) MATCH SIMPLE
            ON UPDATE NO ACTION
            ON DELETE NO ACTION
    );
    

    Usamos a RETURNINGcláusula do PostgreSQL com uma expressão de tabela comum (CTE - também conhecida como WTIHcláusula).

    Um exemplo simples:

    WITH insert_user AS
    (
      INSERT INTO user_ (email) VALUES ('[email protected]')
      RETURNING id
    )
    SELECT *  FROM insert_user;
    

    Resultado:

    id  email
    1   [email protected]
    

    Assim, podemos ver que podemos obter o id da INSERTinstrução dentro do CTE.

    Agora, vamos dar um passo adiante da seguinte forma:

    BEGIN TRANSACTION;
    WITH insert_user AS
    (
      INSERT INTO user_ (email) VALUES ('[email protected]')
      RETURNING id
    )
    INSERT INTO address (address, user_id)
    SELECT '1, Long Street, Somewhere', (SELECT id FROM insert_user)
    COMMIT;
    

    Usamos uma transação - apenas no caso de haver um problema na etapa da primeira INSERTpara a segunda.

    SELECT * FROM user_;
    and
    SELECT * FROM address;
    

    Resultados:

    id  email
    2   [email protected]
    and
    id         address            user_id
    1   1, Long Street, Somewhere       2
    

    Vemos que o user_idde 2 está na addresstabela - tendo vindo do INSERTpara dentro da user_tabela no CTE.

    Você tem INSERT um valor para emailo usuário por causa da NOT NULLrestrição na user_definição da tabela! Você pode remover a restrição, mas vejo pouco sentido nisso.

    Alguns pontos a serem observados:

    • você usa CHARACTER VARYING- o tipo de dados do PostgreSQL TEXTé mais adequado para isso .

    • COLLATE pg_catalog."default"é redundante - se não for especificado, o agrupamento será o padrão.

    • você usa identificadores entre aspas, ou seja - muito melhor usar a convenção de nomenclatura recomendada"userId" do PostgreSQL e transformar isso em - ou seja, snake_case!user_id

    • você tem os nomes mais bizarros para restrições que eu já vi!

      CONSTRAINT "PK_bec464dd8d54c39c54fd32e2334" PRIMARY KEY (id),

      e

      CONSTRAINT "FK_35472b1fe48b6330cd349709564" FOREIGN KEY ("userId")... REFERENCES...

      A única razão para isso é que foi tirado de algum outro sistema que dá esses nomes horríveis. Muito melhor ter address_pk_idou algo semelhante (ou seja, significativo). Uma mensagem de erro informando que a restrição "PK_bec464dd8d54c39c54fd32e2334" foi violada não vai dizer muito a ninguém! Além disso, transmitir isso por telefone será difícil - muito melhor usar um nome simples com o qual os usuários possam se relacionar.

    Para responder as perguntas:

    1ª pergunta:

    • Can I generate the user ID from the sequence in some other way than entering an email in to the table and in the end enter both the ID and the email at the same time?

    Você poderia fazer o seguinte:

    SELECT nextval('user_id_seq');
    

    Resultado:

    nextval
          3
    

    e, em seguida, INSERTna tabela de endereços junto com um endereço. Mas, qual é o ponto? Você precisa ter alguma maneira de relacionar um determinado usuário a um determinado endereço - e você faz isso agrupando seu SEQUENCEvalor em uma transação - primeiro INSERTna user_tabela e depois usando esse valor da RETURNINGcláusula para criar o endereço.

    2ª pergunta:

    • Can I save the address in the addresses table referencing a foreign key which has not yet been added to users?

    Não! O ponto principal de FOREIGN KEYs é que você não pode inserir nada na tabela de endereços que não tenha um user_idretorno válido no idcampo da user_tabela.

    Você poderia largar as restrições e ter alguma bagunça processual medonha para acompanhar o que foi e o que não foi INSERTeditado onde e quando - mas novamente, por quê? Seu banco de dados fará todo o trabalho de acompanhar tudo isso se você permitir!

    • 1

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • 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