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 / 140632
Accepted
5crammed
5crammed
Asked: 2016-06-08 07:49:03 +0800 CST2016-06-08 07:49:03 +0800 CST 2016-06-08 07:49:03 +0800 CST

Por que um valor de chave primária mudaria?

  • 772

Eu tenho pesquisado o conceito de ROWGUID recentemente e me deparei com esta questão. Essa resposta deu uma visão, mas me levou a uma toca de coelho diferente com a menção de alterar o valor da chave primária.

Meu entendimento sempre foi que uma chave primária deve ser imutável, e minha pesquisa desde a leitura desta resposta forneceu apenas respostas que refletem o mesmo que uma prática recomendada.

Em que circunstâncias um valor de chave primária precisaria ser alterado após a criação do registro?

database-design primary-key
  • 8 8 respostas
  • 11157 Views

8 respostas

  • Voted
  1. Best Answer
    Hannah Vernon
    2016-06-08T07:53:33+08:002016-06-08T07:53:33+08:00

    Se você estiver usando o nome de uma pessoa como chave primária e seu nome for alterado, você precisará alterar a chave primária. É para isso que ON UPDATE CASCADEé usado, uma vez que basicamente transfere a alteração em cascata para todas as tabelas relacionadas que possuem relacionamentos de chave estrangeira com a chave primária.

    Por exemplo:

    USE tempdb;
    GO
    
    CREATE TABLE dbo.People
    (
        PersonKey VARCHAR(200) NOT NULL
            CONSTRAINT PK_People
            PRIMARY KEY CLUSTERED
        , BirthDate DATE NULL
    ) ON [PRIMARY];
    
    CREATE TABLE dbo.PeopleAKA
    (
        PersonAKAKey VARCHAR(200) NOT NULL
            CONSTRAINT PK_PeopleAKA
            PRIMARY KEY CLUSTERED
        , PersonKey VARCHAR(200) NOT NULL
            CONSTRAINT FK_PeopleAKA_People
            FOREIGN KEY REFERENCES dbo.People(PersonKey)
            ON UPDATE CASCADE
    ) ON [PRIMARY];
    
    INSERT INTO dbo.People(PersonKey, BirthDate)
    VALUES ('Joe Black', '1776-01-01');
    
    INSERT INTO dbo.PeopleAKA(PersonAKAKey, PersonKey)
    VALUES ('Death', 'Joe Black');
    

    A SELECTcontra ambas as tabelas:

    SELECT *
    FROM dbo.People p
        INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;
    

    Retorna:

    insira a descrição da imagem aqui

    Se atualizarmos a PersonKeycoluna e executarmos novamente o SELECT:

    UPDATE dbo.People
    SET PersonKey = 'Mr Joe Black'
    WHERE PersonKey = 'Joe Black';
    
    SELECT *
    FROM dbo.People p
        INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;
    

    Nós vemos:

    insira a descrição da imagem aqui

    Observando o plano da UPDATEinstrução acima, vemos claramente que ambas as tabelas são atualizadas por uma única instrução de atualização em virtude da chave estrangeira definida como ON UPDATE CASCADE:

    insira a descrição da imagem aqui clique na imagem acima para vê-la com mais clareza

    Por fim, limparemos nossas tabelas temporárias:

    DROP TABLE dbo.PeopleAKA;
    DROP TABLE dbo.People;
    

    A maneira preferida de fazer isso usando chaves substitutas seria:

    USE tempdb;
    GO
    
    CREATE TABLE dbo.People
    (
        PersonID INT NOT NULL IDENTITY(1,1)
            CONSTRAINT PK_People
            PRIMARY KEY CLUSTERED
        , PersonName VARCHAR(200) NOT NULL
        , BirthDate DATE NULL
    ) ON [PRIMARY];
    
    CREATE TABLE dbo.PeopleAKA
    (
        PersonAKAID INT NOT NULL IDENTITY(1,1)
            CONSTRAINT PK_PeopleAKA
            PRIMARY KEY CLUSTERED
        , PersonAKAName VARCHAR(200) NOT NULL
        , PersonID INT NOT NULL
            CONSTRAINT FK_PeopleAKA_People
            FOREIGN KEY REFERENCES dbo.People(PersonID)
            ON UPDATE CASCADE
    ) ON [PRIMARY];
    
    INSERT INTO dbo.People(PersonName, BirthDate)
    VALUES ('Joe Black', '1776-01-01');
    
    INSERT INTO dbo.PeopleAKA(PersonID, PersonAKAName)
    VALUES (1, 'Death');
    
    SELECT *
    FROM dbo.People p
        INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;
    
    UPDATE dbo.People
    SET PersonName = 'Mr Joe Black'
    WHERE PersonID = 1;
    

    Para completar, o plano para a declaração de atualização é muito simples e mostra uma vantagem para chaves substitutas, ou seja, apenas uma única linha precisa ser atualizada em oposição a todas as linhas que contêm a chave em um cenário de chave natural:

    insira a descrição da imagem aqui

    SELECT *
    FROM dbo.People p
        INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;
    
    DROP TABLE dbo.PeopleAKA;
    DROP TABLE dbo.People;
    

    A saída das duas SELECTdeclarações acima são:

    insira a descrição da imagem aqui

    Essencialmente, o resultado é aproximadamente o mesmo. Uma grande diferença é que a chave natural ampla não é repetida em todas as tabelas onde ocorre a chave estrangeira. No meu exemplo, estou usando uma VARCHAR(200)coluna para conter o nome da pessoa, o que exige o uso de um VARCHAR(200) em todos os lugares . Se houver muitas linhas e muitas tabelas contendo a chave estrangeira, isso resultará em muita memória desperdiçada. Observe que não estou falando sobre o desperdício de espaço em disco, pois a maioria das pessoas diz que o espaço em disco é tão barato que é essencialmente gratuito. A memória, porém, é cara e merece ser valorizada. O uso de um número inteiro de 4 bytes para a chave economizará uma grande quantidade de memória quando você considerar o tamanho médio do nome de cerca de 15 caracteres.

    Tangencial à questão sobre como e por que as chaves podem mudar é a questão sobre por que escolher chaves naturais em vez de chaves substitutas, que é uma questão interessante e talvez mais importante, especialmente onde o desempenho é uma meta de design. Veja minha pergunta aqui sobre isso.


    1 - http://weblogs.sqlteam.com/mladenp/archive/2009/10/06/Why-I-prefer-surrogate-keys-instead-of-natural-keys-in.aspx

    • 26
  2. Byron Jones
    2016-06-08T12:35:56+08:002016-06-08T12:35:56+08:00

    Embora você possa usar uma chave natural e/ou mutável como seu PK, em minha experiência isso leva a problemas, que muitas vezes podem ser evitados pelo uso de um PK que atenda a estas condições:

     Guaranteed Unique, Always Exists, Immutable, and Concise.
    

    Por exemplo, muitas empresas nos EUA tentam usar números de seguridade social como números de identificação pessoal (e PKs) em seus sistemas. Em seguida, eles se deparam com os seguintes problemas - erros de entrada de dados que levam a vários registros que precisam ser reparados, pessoas que não possuem um SSN, pessoas cujo SSN foi alterado pelo governo, pessoas que possuem SSNs duplicados.

    Eu já vi cada um desses cenários. Também já vi empresas que não queriam que seus clientes fossem "apenas um número", o que significava que seu PK acabava sendo 'primeiro+meio+último+DOB+zip' ou algo semelhante. Embora eles adicionassem campos suficientes para quase garantir a exclusividade, suas consultas eram horríveis e atualizar qualquer um desses campos significava perseguir problemas de consistência de dados.

    Na minha experiência, um PK gerado pelo próprio banco de dados é quase sempre uma solução melhor.

    Eu recomendo este artigo para indicações adicionais: http://www.agiledata.org/essays/keys.html

    • 9
  3. Jon Raynor
    2016-06-08T12:13:07+08:002016-06-08T12:13:07+08:00

    A chave primária pode ser alterada quando a sincronização está envolvida. Este pode ser o caso quando você tem um cliente desconectado e sincroniza os dados com o servidor em determinados intervalos.

    Alguns anos atrás, trabalhei em um sistema em que todos os dados de evento na máquina local tinham IDs de linha negativos, como -1, -2 etc. Quando os dados eram sincronizados com o servidor, o ID da linha no servidor era aplicado ao cliente. Digamos que o próximo ID de linha no servidor seja 58. Então -1 se tornaria 58, -2 59 e assim por diante. Essa alteração de ID de linha seria em cascata para todos os registros FK filho na máquina local. O mecanismo também foi usado para determinar quais registros foram sincronizados anteriormente.

    Não estou dizendo que esse foi um bom design, mas é um exemplo da mudança da chave primária com o tempo.

    • 7
  4. Vérace
    2016-06-08T07:56:49+08:002016-06-08T07:56:49+08:00

    Qualquer projeto que envolva mudanças PRIMARY KEYregulares é uma receita para o desastre. A única boa razão para alterá-lo seria uma fusão de dois bancos de dados anteriormente separados.

    Conforme apontado por @MaxVernon, mudanças ocasionais podem ocorrer - então use ON UPDATE CASCADE, embora a maioria dos sistemas hoje em dia use um ID como substituto PRIMARY KEY.

    Puristas como Joe Celko e Fabian Pascal (um site que vale a pena seguir) discordam do uso de chaves substitutas, mas acho que eles perderam essa batalha em particular.

    • 5
  5. jpmc26
    2016-06-08T12:40:53+08:002016-06-08T12:40:53+08:00

    Curiosamente, a pergunta vinculada sobre ROWGUID meio que fornece seu próprio caso de uso: quando você tem chaves primárias conflitantes em bancos de dados que precisam ser sincronizados. Se você tiver dois bancos de dados que precisam ser reconciliados e eles usam sequências para chaves primárias, convém que uma das chaves seja alterada para que permaneça exclusiva.

    Em um mundo ideal, isso nunca aconteceria. Você usaria GUIDs para as chaves primárias para começar. Realisticamente, porém, você pode nem ter um banco de dados distribuído ao começar a projetar, e convertê-lo em GUIDs pode ter sido um esforço que foi priorizado abaixo da distribuição porque foi considerado de maior impacto do que implementar a atualização de chave. Isso pode acontecer se você tiver uma grande base de código que dependa de chaves inteiras e exija uma revisão importante para converter em GUID. Há também o fato de que GUIDs esparsos (GUIDs que não estão muito próximos uns dos outros, o que acontece se você os gerar aleatoriamente como deveria) também podem causar problemas para certos tipos de índices, o que significa que você deseja evitar o uso como chaves primárias (mencionadas por Byron Jones ).

    • 3
  6. nvogel
    2016-06-09T05:11:50+08:002016-06-09T05:11:50+08:00

    A estabilidade é uma propriedade desejável para uma chave, mas é algo relativo e não uma regra absoluta. Na prática, muitas vezes é útil alterar os valores das chaves. Em termos relacionais, os dados são identificáveis ​​apenas por suas (super)chaves. Segue-se que, se houver apenas uma chave em uma determinada tabela, a distinção entre A) alterar um valor de chave ou B) substituir o conjunto de linhas em uma tabela por algum conjunto de linhas semelhante ou diferente contendo outros valores de chave é essencialmente uma questão de semântica e não de lógica.

    Um exemplo mais interessante é o caso de uma tabela com várias chaves onde os valores de uma ou mais dessas chaves podem ter que mudar em relação a outros valores de chave. Veja o exemplo de uma tabela Employee com duas chaves: LoginName e Badge Number. Aqui está uma linha de amostra dessa tabela:

    +---------+--------+
    |LoginName|BadgeNum|
    +---------+--------+
    |ZoeS     |47832   |
    +---------+--------+
    

    Se ZoeS perder seu crachá, talvez ela receba um novo e obtenha um novo número de crachá:

    +---------+--------+
    |LoginName|BadgeNum|
    +---------+--------+
    |ZoeS     |50282   |
    +---------+--------+
    

    Mais tarde, ela pode decidir mudar seu nome de login:

    +---------+--------+
    |LoginName|BadgeNum|
    +---------+--------+
    |ZSmith   |50282   |
    +---------+--------+
    

    Ambos os valores-chave foram alterados - um em relação ao outro. Observe que não faz necessariamente nenhuma diferença qual deles é considerado "primário".

    Na prática, a "imutabilidade", ou seja, nunca alterar um valor, é inatingível ou pelo menos impossível de verificar. Na medida em que a mudança faz alguma diferença, o caminho mais seguro é provavelmente assumir que qualquer chave (ou qualquer atributo) pode precisar ser alterado.

    • 3
  7. paparazzo
    2016-06-08T08:26:00+08:002016-06-08T08:26:00+08:00

    Um cenário possível é, digamos, que você tenha afiliados com ID exclusivo e saiba que eles não serão duplicados entre os afiliados, pois possuem um caráter inicial exclusivo. Os afiliados carregam dados para uma tabela principal. Lá, os registros são processados ​​e, em seguida, atribuídos a um ID mestre. Os usuários precisam acessar os registros assim que são carregados, mesmo que ainda não tenham sido processados. Você deseja que o ID mestre seja baseado no pedido processado e nem sempre processará na ordem em que os registros foram carregados. Eu sei um pouco fabricado.

    • 0
  8. Behrouz Sameny
    2016-06-08T08:08:16+08:002016-06-08T08:08:16+08:00

    Imagine uma situação como quando alguém escolheu o National Insurance Number (NIN) como chave primária e, de alguma forma, um operador insere uma linha com o NIN errado. Depois de inserir o valor, existem duas maneiras de corrigir o erro:

    1. Apague o registro errado e insira um novo
    2. Atualize o valor para o correto e use On Update Cascade se houver uma restrição de integridade referencial nessa coluna
    • -1

relate perguntas

  • Quais são as desvantagens de usar UUID ou GUID como chave primária?

  • É melhor armazenar os valores calculados ou recalculá-los a pedido? [duplicado]

  • Armazenar vs calcular valores agregados

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

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

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