Aggiungi la chiave primaria alla tabella esistente


197

Ho un tavolo esistente chiamato Persion. In questa tabella ho 5 colonne:

  • persionId
  • pname
  • PMID
  • Pdescription
  • PamT

Quando ho creato questa tabella, ho impostato PersionIde Pnamecome chiave primaria .

Ora voglio includere un'altra colonna nella chiave primaria - PMID. Come posso scrivere una ALTERdichiarazione per fare questo? (Ho già 1000 record nella tabella)


8
Sei sicuro? questo significa che puoi avere duplicati personIdnella tua tabella. Questo a sua volta significa che se ti unisci da una tabella di tipi di transazione (molti) a questa tabella solo su questa chiave otterrai record duplicati, portando a un "doppio conteggio" dei record di transazione.
Nick.McDermaid,

6
anzi, questa è un'idea MOLTO negativa. Il tuo PK dovrebbe essere su "persionId", tutto qui
Patrick Honorez,

1
Ho pensato che solo una colonna in una tabella dovesse essere impostata come chiave primaria?
Charris,

1
@ChristopheHarris, a volte ha senso avere più di una colonna come chiave primaria. Una tabella di relazioni uno-a-molti o molti-a-molti avrà probabilmente 2 o più colonne di chiavi esterne che compongono la chiave primaria, poiché è possibile identificare univocamente un record solo se si conoscono i valori di tutta la chiave primaria colonne. Tuttavia, nel caso del PO, è improbabile che sia proprio quello che voleva.
Kristen Hammack,

2
@Kristen Hammack Anche nel caso delle relazioni M2M, è probabilmente meglio che la tabella intermedia abbia una chiave primaria separata e quindi un vincolo univoco insieme sulle due chiavi esterne.
kloddant,

Risposte:


191

eliminare il vincolo e ricrearlo

alter table Persion drop CONSTRAINT <constraint_name>

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

modificare:

puoi trovare il nome del vincolo usando la query seguente:

select OBJECT_NAME(OBJECT_ID) AS NameofConstraint
FROM sys.objects
where OBJECT_NAME(parent_object_id)='Persion'
and type_desc LIKE '%CONSTRAINT'

80

Penso che qualcosa del genere dovrebbe funzionare

-- 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

1
Probabilmente non cluster è una buona opzione nel caso di PK compositi per le prestazioni in base alla data di inserimento, se questo è importante per te.
Shiv,

36
-- create new primary key constraint
ALTER TABLE dbo.persion 
ADD CONSTRAINT PK_persionId PRIMARY KEY NONCLUSTERED (pmid, persionId);

è una soluzione migliore perché hai il controllo sulla denominazione di primary_key.


È meglio che usare semplicemente

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

che genera nomi randomizzati e può causare problemi durante la creazione di script o il confronto di database


3
+1 per evidenziare la funzionalità per assegnare un nome alla chiave primaria. Quando esegui script di aggiornamento che creano drop PK, è preferibile colpire PK nominati piuttosto che interrogare lo schema informativo per capire il nome
e_i_pi

27

Se si aggiunge il vincolo chiave primaria

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

per esempio:

ALTER TABLE DEPT ADD CONSTRAINT PK_DEPT PRIMARY KEY (DEPTNO)

14

C'è già una chiave primaria nella tua tabella. Non puoi semplicemente aggiungere la chiave primaria, altrimenti causeranno errori. Perché esiste una chiave primaria per la tabella sql.

Innanzitutto, devi rilasciare la tua vecchia chiave primaria.

MySQL:

ALTER TABLE Persion
DROP PRIMARY KEY;

SQL Server / Oracle / MS Access:

ALTER TABLE Persion
DROP CONSTRAINT 'constraint name';

Devi trovare il nome del vincolo nella tua tabella. Se hai dato il nome del vincolo quando hai creato la tabella, puoi facilmente usare il nome del vincolo (es: PK_Persion).

In secondo luogo, Aggiungi chiave primaria.

MySQL / SQL Server / Oracle / MS Access:

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

o il migliore qui sotto

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

Questo può impostare il nome del vincolo dallo sviluppatore. È più facile mantenere la tabella.

Mi sono un po 'confuso quando ho cercato tutte le risposte. Quindi cerco un documento per trovare ogni dettaglio. Spero che questa risposta possa aiutare altri principianti di SQL.

Riferimento: https://www.w3schools.com/sql/sql_primarykey.asp


4

Il vincolo PRIMARY KEY identifica in modo univoco ogni record in una tabella del database. Le chiavi primarie devono contenere valori UNICI e la colonna non può contenere valori 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)

4

Necromancing.
Nel caso in cui qualcuno abbia un buono schema con cui lavorare come me ...
Ecco come farlo correttamente:

In questo esempio, il nome della tabella è dbo.T_SYS_Language_Forms e il nome della colonna è 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 

Ottimo punto su "non far cadere, i riferimenti FK potrebbero già esistere". Le altre risposte non hanno funzionato per me per questo.
sgryzko,

2

Per favore prova questo-

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

1

Prova a usare questo codice:

ALTER TABLE `table name` 
    CHANGE COLUMN `column name` `column name` datatype NOT NULL, 
    ADD PRIMARY KEY (`column name`) ;

1
ALTER TABLE TABLE_NAME ADD PRIMARY KEY(`persionId`,`Pname`,`PMID`)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.