SQL-script: How to write ALTER statements to set Primary key on an existing table?
Asked Answered
P

12

264

I have an existing table called Person which already has existing 1000 rows of data. In this table I have 5 fields:

  • personId
  • Pname
  • PMid
  • Pdescription
  • Pamt

The table already has an existing compound-key [PersonId, Pname] as the primary key.

Now I want to modify that existing compound-key to have one more field [PMid].

How can I write an ALTER statement to do this?

Phosphorus answered 3/8, 2012 at 11:17 Comment(8)
Are you sure? this means you are allowed to have duplicate personId in your table. This in turn means if you join from a transaction (many) type table to this table on this key alone you'll get duplicate records, leading to 'double counting' of transaction records.Livengood
indeed, this is a VERY bad idea. Your PK sould be on"persionId", that's itRoseboro
I thought only one column in a table should be set as the primary key?Songster
@ChristopheHarris, sometimes it makes sense to have more than one column as the primary key. A one-to-many or many-to-many relationship table will likely have 2 or more foreign key columns making up the primary key, since it is only possible to uniquely identify a record if you know the values of all of the primary key columns. However, in the OP's case, it's unlikely that this is really what he was wanting.Plaza
@Kristen Hammack Even in the case of M2M relationships, it is probably better to have the intermediate table have a separate primary key and then put a unique together constraint on the two foreign keys.Midtown
@Midtown I think we might be saying the same thing here? I'm talking about, e.g., 2 tables A and B, each with PK Id; then a table C with PK (A.Id, B.Id) for a many-to-many relationship.Plaza
@KristenHammack I don't think so, but I could be mistaken. I am talking about 2 tables A and B, each with PK Id, then a table C with PK id and a unique together index on (A.Id, B.Id). But (A.Id, B.Id) is not the PK - the PK is a separate id column in table C.Midtown
@Midtown ok, so "better" in that case is mostly about whether you actually need that surrogate PK for, e.g., an ORM that can't retrieve data in any other way. Since you've still got the unique index on (A.id, B.id), there is no performance improvement in INSERTs or UPDATEs by adding the extra PK, and it's just extra data to keep up with. Another reason for the surrogate key would be security; if you need to access the relationship record from a web page and don't want users to see actual IDs, then it's useful there too.Plaza
H
253

drop constraint and recreate it

alter table Persion drop CONSTRAINT <constraint_name>

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

edit:

you can find the constraint name by using the query below:

select OBJECT_NAME(OBJECT_ID) AS NameofConstraint
FROM sys.objects
where OBJECT_NAME(parent_object_id)='Persion'
and type_desc LIKE '%CONSTRAINT'
Heer answered 3/8, 2012 at 11:19 Comment(0)
M
109

I think something like this should work

-- 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
Mittiemittimus answered 3/8, 2012 at 11:33 Comment(1)
Probably non-clustered is a good option in the case of composite PKs for performance on insertion date basis if that is important for you.Huggins
S
48
-- create new primary key constraint
ALTER TABLE dbo.persion 
ADD CONSTRAINT PK_persionId PRIMARY KEY NONCLUSTERED (pmid, persionId);

is a better solution because you have control over the naming of the primary_key.


It's better than just using

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

which yeilds randomized names and can cause problems when scripting out or comparing databases

Simonides answered 27/2, 2015 at 13:59 Comment(1)
+1 for highlighting the functinoality to name your primary key. When you're running update scripts that drop-recreate PKs, it's preferable to hit named PKs than have to interrogate the information schema to figure out the nameVicarial
F
31

If you add primary key constraint

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

for example:

ALTER TABLE DEPT ADD CONSTRAINT PK_DEPT PRIMARY KEY (DEPTNO)
Fancher answered 22/2, 2017 at 22:55 Comment(0)
F
27

There is already an primary key in your table. You can't just add primary key,otherwise will cause error. Because there is one primary key for sql table.

First, you have to drop your old primary key.

MySQL:

ALTER TABLE Persion
DROP PRIMARY KEY;

SQL Server / Oracle / MS Access:

ALTER TABLE Persion
DROP CONSTRAINT 'constraint name';

You have to find the constraint name in your table. If you had given constraint name when you created table,you can easily use the constraint name(ex:PK_Persion).

Second,Add primary key.

MySQL / SQL Server / Oracle / MS Access:

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

or the better one below

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

This can set constraint name by developer. It's more easily to maintain the table.

I got a little confuse when i have looked all answers. So I research some document to find every detail. Hope this answer can help other SQL beginner.

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

Fairfax answered 19/12, 2018 at 2:55 Comment(0)
O
6

Necromancing.
Just in case anybody has as good a schema to work with as me...
Here is how to do it correctly:

In this example, the table name is dbo.T_SYS_Language_Forms, and the column name is 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 
Occlusion answered 23/10, 2015 at 9:35 Comment(1)
Very good point about 'don't drop, FK references might already exist'. The other answers didn't work for me because of this.Ibex
P
4

The PRIMARY KEY constraint uniquely identifies each record in a database table. Primary keys must contain UNIQUE values and column cannot contain NULL Values.

  -- 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)
Provence answered 18/2, 2015 at 4:37 Comment(0)
G
2

Please try this-

ALTER TABLE TABLE_NAME DROP INDEX `PRIMARY`, ADD PRIMARY KEY (COLUMN1, COLUMN2,..);
Germaun answered 11/4, 2018 at 14:49 Comment(0)
M
2

alter table[Person] add ID int primary key IDENTITY (1,1)

This will add primary key and indentity seed and populate the new column.

Mona answered 27/5, 2021 at 7:5 Comment(1)
Hi Ashandra. This does not answer the question correctly though. The question is to add one more column to the existing primary key, which your statement does not do.Rub
C
1
ALTER TABLE TABLE_NAME ADD PRIMARY KEY(`persionId`,`Pname`,`PMID`)
Coated answered 6/12, 2016 at 5:35 Comment(0)
M
0

Try using this code:

ALTER TABLE `table name` 
    CHANGE COLUMN `column name` `column name` datatype NOT NULL, 
    ADD PRIMARY KEY (`column name`) ;
Mihalco answered 11/8, 2016 at 14:6 Comment(0)
N
0

I am surprised after all these years the answers to the question had not hit 100% what the question poster was asking.

The problem presented by the poster is: He has an existing table with existing data and existing compound-key. Now the task he wants to accomplish is to execute a script to replace the existing compound-key with a new compound-key.

First concern: the first requirement for fields to be a key is NOT NULL and they together need to be unique, otherwise you will get error when running the alter statement.

For that matter, I think the following is the right answer for the future answer seekers who have the same issue.

-- test your existing data suitable for new key or not
select 1 from Person p group by PMid, PersonId, PName having COUNT(*) > 1
If @@ROWCOUNT > 0 Print 'Not Ok' 
ELSE 
BEGIN
-- delete old key/compound-key
    IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[PK_Person]') ) 
    BEGIN
        ALTER TABLE Person DROP CONSTRAINT PK_Person;
    END;
    BEGIN
    -- add new key/compound-key, fulfil the required non-null quality
        ALTER TABLE [dbo].[Person] ALTER COLUMN PMid NUMERIC(5,0) NOT NULL;  -- 'not null' is required
        ALTER TABLE [dbo].[Person] ALTER COLUMN PersonId NUMERIC(5,0) NOT NULL; -- 'not null' is required
        ALTER TABLE [dbo].[Person] ALTER COLUMN Pname  varchar(32) NOT NULL; -- 'not null' is required
    END
    ALTER TABLE [dbo].[Person] ADD CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
    (
        [PMid] ASC,
        [PersonId] ASC,
        [Pname] ASC
    )WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) 
END
Natika answered 31/8, 2023 at 5:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.