Ajouter une clé primaire à une table existante

194

J'ai une table existante appelée Persion. Dans ce tableau, j'ai 5 colonnes:

  • persionId
  • Pname
  • PMid
  • Description
  • Pamt

Lorsque j'ai créé cette table, j'ai défini PersionIdetPname comme clé primaire .

Je veux maintenant inclure une colonne de plus dans la clé primaire - PMID. Comment puis-je écrire une ALTERdéclaration pour ce faire? (J'ai déjà 1000 enregistrements dans le tableau)

geai
la source
8
Êtes-vous sûr? cela signifie que vous êtes autorisé à avoir des doublons personIddans votre table. Cela signifie à son tour que si vous vous joignez à partir d'une table de type transaction (plusieurs) à cette table sur cette seule clé, vous obtiendrez des enregistrements en double, conduisant à un «double comptage» des enregistrements de transaction.
Nick.McDermaid
6
en effet, c'est une TRÈS mauvaise idée. Votre PK devrait être sur "persionId", c'est tout
Patrick Honorez
1
Je pensais qu'une seule colonne dans une table devrait être définie comme clé primaire?
CHarris
1
@ChristopheHarris, il est parfois judicieux d'avoir plus d'une colonne comme clé primaire. Une table de relations un-à-plusieurs ou plusieurs-à-plusieurs aura probablement 2 colonnes de clé étrangère ou plus constituant la clé primaire, car il n'est possible d'identifier de manière unique un enregistrement que si vous connaissez les valeurs de l'ensemble de la clé primaire Colonnes. Cependant, dans le cas du PO, il est peu probable que ce soit vraiment ce qu'il voulait.
Kristen Hammack
2
@Kristen Hammack Même dans le cas des relations M2M, il est probablement préférable que la table intermédiaire ait une clé primaire distincte, puis place une contrainte ensemble unique sur les deux clés étrangères.
kloddant

Réponses:

191

supprimer la contrainte et la recréer

alter table Persion drop CONSTRAINT <constraint_name>

alter table Persion add primary key (persionId,Pname,PMID)

Éditer:

vous pouvez trouver le nom de la contrainte en utilisant la requête ci-dessous:

select OBJECT_NAME(OBJECT_ID) AS NameofConstraint
FROM sys.objects
where OBJECT_NAME(parent_object_id)='Persion'
and type_desc LIKE '%CONSTRAINT'
Joe G Joseph
la source
80

Je pense que quelque chose comme ça devrait fonctionner

-- drop current primary key constraint
ALTER TABLE dbo.persion 
DROP CONSTRAINT PK_persionId;
GO

-- add new auto incremented field
ALTER TABLE dbo.persion 
ADD pmid BIGINT IDENTITY;
GO

-- create new primary key constraint
ALTER TABLE dbo.persion 
ADD CONSTRAINT PK_persionId PRIMARY KEY NONCLUSTERED (pmid, persionId);
GO
TI
la source
1
La non-mise en cluster est probablement une bonne option dans le cas des PK composites pour les performances à la date d'insertion si cela est important pour vous.
Shiv
36
-- create new primary key constraint
ALTER TABLE dbo.persion 
ADD CONSTRAINT PK_persionId PRIMARY KEY NONCLUSTERED (pmid, persionId);

est une meilleure solution car vous contrôlez la dénomination de la clé_principale.


C'est mieux que de simplement utiliser

ALTER TABLE Persion ADD PRIMARY KEY(persionId,Pname,PMID)

qui crée des noms aléatoires et peut causer des problèmes lors de l'écriture de scripts ou de la comparaison de bases de données

user3675542
la source
3
+1 pour mettre en évidence la fonction pour nommer votre clé primaire. Lorsque vous exécutez des scripts de mise à jour qui recréent des PK, il est préférable de frapper les PK nommés plutôt que d'interroger le schéma d'informations pour déterminer le nom
e_i_pi
27

Si vous ajoutez une contrainte de clé primaire

ALTER TABLE <TABLE NAME> ADD CONSTRAINT <CONSTRAINT NAME> PRIMARY KEY <COLUMNNAME>  

par exemple:

ALTER TABLE DEPT ADD CONSTRAINT PK_DEPT PRIMARY KEY (DEPTNO)
K GANGA
la source
13

Il y a déjà une clé primaire dans votre table. Vous ne pouvez pas simplement ajouter une clé primaire, sinon cela entraînera une erreur. Parce qu'il y a une clé primaire pour la table sql.

Tout d'abord, vous devez supprimer votre ancienne clé primaire.

MySQL:

ALTER TABLE Persion
DROP PRIMARY KEY;

SQL Server / Oracle / MS Access:

ALTER TABLE Persion
DROP CONSTRAINT 'constraint name';

Vous devez trouver le nom de la contrainte dans votre table. Si vous aviez donné un nom de contrainte lors de la création de la table, vous pouvez facilement utiliser le nom de la contrainte (ex: PK_Persion).

Deuxièmement, ajoutez la clé primaire.

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Persion ADD PRIMARY KEY (PersionId,Pname,PMID);

ou le meilleur ci-dessous

ALTER TABLE Persion ADD CONSTRAINT PK_Persion PRIMARY KEY (PersionId,Pname,PMID);

Cela peut définir le nom de la contrainte par développeur. Il est plus facile de maintenir la table.

Je suis devenu un peu confus quand j'ai regardé toutes les réponses. Je recherche donc un document pour trouver chaque détail. J'espère que cette réponse pourra aider d'autres débutants SQL.

Référence: https://www.w3schools.com/sql/sql_primarykey.asp

劉鎮 瑲
la source
4

La contrainte PRIMARY KEY identifie de manière unique chaque enregistrement d'une table de base de données. Les clés primaires doivent contenir des valeurs UNIQUES et la colonne ne peut pas contenir de valeurs NULL.

  -- DROP current primary key 
  ALTER TABLE tblPersons DROP CONSTRAINT <constraint_name>
  Example:
  ALTER TABLE tblPersons 
  DROP CONSTRAINT P_Id;


  -- ALTER TABLE tblpersion
  ALTER TABLE tblpersion add primary key (P_Id,LastName)
Mike Clark
la source
4

Nécromancement.
Juste au cas où quelqu'un aurait un aussi bon schéma pour travailler avec moi ...
Voici comment le faire correctement:

Dans cet exemple, le nom de la table est dbo.T_SYS_Language_Forms et le nom de la colonne est LANG_UID

-- First, chech if the table exists...
IF 0 < (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE = 'BASE TABLE'
    AND TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'T_SYS_Language_Forms'
)
BEGIN
    -- Check for NULL values in the primary-key column
    IF 0 = (SELECT COUNT(*) FROM T_SYS_Language_Forms WHERE LANG_UID IS NULL)
    BEGIN
        ALTER TABLE T_SYS_Language_Forms ALTER COLUMN LANG_UID uniqueidentifier NOT NULL 

        -- No, don't drop, FK references might already exist...
        -- Drop PK if exists (it is very possible it does not have the name you think it has...)
        -- ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT pk_constraint_name 
        --DECLARE @pkDropCommand nvarchar(1000) 
        --SET @pkDropCommand = N'ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT ' + QUOTENAME((SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
        --WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
        --AND TABLE_SCHEMA = 'dbo' 
        --AND TABLE_NAME = 'T_SYS_Language_Forms' 
        ----AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
        --))
        ---- PRINT @pkDropCommand 
        --EXECUTE(@pkDropCommand) 
        -- Instead do
        -- EXEC sp_rename 'dbo.T_SYS_Language_Forms.PK_T_SYS_Language_Forms1234565', 'PK_T_SYS_Language_Forms';

        -- Check if they keys are unique (it is very possible they might not be)        
        IF 1 >= (SELECT TOP 1 COUNT(*) AS cnt FROM T_SYS_Language_Forms GROUP BY LANG_UID ORDER BY cnt DESC)
        BEGIN

            -- If no Primary key for this table
            IF 0 =  
            (
                SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
                WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
                AND TABLE_SCHEMA = 'dbo' 
                AND TABLE_NAME = 'T_SYS_Language_Forms' 
                -- AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
            )
                ALTER TABLE T_SYS_Language_Forms ADD CONSTRAINT PK_T_SYS_Language_Forms PRIMARY KEY CLUSTERED (LANG_UID ASC)
            ;

        END -- End uniqueness check
        ELSE
            PRINT 'FSCK, this column has duplicate keys, and can thus not be changed to primary key...' 
    END -- End NULL check
    ELSE
        PRINT 'FSCK, need to figure out how to update NULL value(s)...' 
END 
Stefan Steiger
la source
Très bon point à propos de «ne laissez pas tomber, les références FK peuvent déjà exister». Les autres réponses n'ont pas fonctionné pour moi à cause de cela.
sgryzko
2

Veuillez essayer ceci-

ALTER TABLE TABLE_NAME DROP INDEX `PRIMARY`, ADD PRIMARY KEY (COLUMN1, COLUMN2,..);
Samir
la source
1

Essayez d'utiliser ce code:

ALTER TABLE `table name` 
    CHANGE COLUMN `column name` `column name` datatype NOT NULL, 
    ADD PRIMARY KEY (`column name`) ;
Rekha Rajan
la source
1
ALTER TABLE TABLE_NAME ADD PRIMARY KEY(`persionId`,`Pname`,`PMID`)
Harry Singh
la source