57

I'd like to determine the primary key of a table using TSQL (stored procedure or system table is fine). Is there such a mechanism in SQL Server (2005 or 2008)?

OMG Ponies
  • 325,700
  • 82
  • 523
  • 502
rein
  • 32,967
  • 23
  • 82
  • 106

10 Answers10

80

This should get you started:

SELECT 
    *
FROM 
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
    JOIN 
    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu 
        ON tc.CONSTRAINT_NAME = ccu.Constraint_name
WHERE 
    tc.TABLE_NAME = 'TableName' AND 
    tc.CONSTRAINT_TYPE = 'Primary Key'
Paul
  • 4,160
  • 3
  • 30
  • 56
Stuart Ainsworth
  • 12,792
  • 41
  • 46
  • `ON tc.CONSTRAINT_NAME = ccu.CONSTRAINT_NAME AND tc.CONSTRAINT_SCHEMA = ccu.CONSTRAINT_SCHEMA` for multiple schemas – Bohdan Jan 11 '21 at 10:29
50

How about

sp_pkeys 'TableName'
Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
  • stellar! I'm seeing much better performance from this than from the table joins through information_schema – Mike M May 28 '15 at 19:04
  • 1
    This would be much handier if it were a table valued function that you could select from – xr280xr Aug 08 '17 at 15:22
  • Can't do anything with the result because it's not a function. – Emperor Eto Dec 02 '19 at 20:55
  • If you need a table, you can insert the results of a stored procedure into a table. First define the table `declare @PrimaryKey table (TABLE_QUALIFIER nvarchar(100), TABLE_OWNER nvarchar(100), TABLE_NAME nvarchar(100), COLUMN_NAME nvarchar(100), KEY_SEQ int, PK_NAME nvarchar(100))` and then `insert into @PrimaryKey exec sp_pkeys 'TABLE_NAME'` – Alexander Higgins Dec 02 '20 at 16:18
22

Here's one based on system tables from SQL 2005 (99% sure it'd work in 2008). This will list all PKs for all user-defined tables, with all columns and some extra fluff that could be removed. Add parameters to pick out a table at a time.

SELECT
   schema_name(ta.schema_id)  SchemaName
  ,ta.name  TableName
  ,ind.name
  ,indcol.key_ordinal Ord
  ,col.name  ColumnName
  ,ind.type_desc
  ,ind.fill_factor
 from sys.tables ta
  inner join sys.indexes ind
   on ind.object_id = ta.object_id
  inner join sys.index_columns indcol
   on indcol.object_id = ta.object_id
    and indcol.index_id = ind.index_id
  inner join sys.columns col
   on col.object_id = ta.object_id
    and col.column_id = indcol.column_id
 where ind.is_primary_key = 1
 order by
   ta.name
  ,indcol.key_ordinal
Philip Kelley
  • 39,426
  • 11
  • 57
  • 92
20
SELECT ccu.COLUMN_NAME, ccu.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc
    INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS ccu
        ON tc.CONSTRAINT_NAME = ccu.CONSTRAINT_NAME
WHERE tc.TABLE_CATALOG = 'Your_Catalog'    -- replace with your catalog
    AND tc.TABLE_SCHEMA = 'dbo'            -- replace with your schema
    AND tc.TABLE_NAME = 'Your_Table'       -- replace with your table name
    AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
LukeH
  • 263,068
  • 57
  • 365
  • 409
7
exec [sys].[sp_primary_keys_rowset] @table_name= 'TableName'
Jacob G
  • 3,645
  • 1
  • 20
  • 25
4
EXEC sp_Pkeys @tableName
chugh97
  • 9,602
  • 25
  • 89
  • 136
3

You're better off using INFORMATION_SCHEMA.KEY_COLUMN_USAGE, as you can access the key ordering information (ORDINAL_POSITION) which is very important to know.

SELECT 
    kcu.*
FROM 
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
    INNER JOIN 
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
        ON  tc.TABLE_NAME = kcu.TABLE_NAME AND 
            tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
ORDER BY 
    tc.TABLE_NAME,
    tc.CONSTRAINT_NAME,
    kcu.ORDINAL_POSITION
Paul
  • 4,160
  • 3
  • 30
  • 56
sqlconsumer.net
  • 455
  • 3
  • 10
2

The simplest way is this!

select object_id from sys.objects 
where parent_object_id = OBJECT_ID(N'FACounty')
and [type] = N'PK'
JT Turner
  • 502
  • 2
  • 14
2

Can't add a comment, not enough rep points, but this is in response to those saying sp_Pkeys is not usable. Doesn't have to be a function as mentioned in another comment to an answer.

DECLARE @tbl TABLE
(
  Table_Qualifier varchar(30), 
  Table_Owner varchar(30), 
  Table_Name varchar(50), 
  Column_Name varchar(30), 
  Key_Seq int,
  PK_Name varchar(50)
)

insert into @tbl EXEC sp_Pkeys 'tablename'

select * from @tbl
Ruben Helsloot
  • 12,582
  • 6
  • 26
  • 49
S Wagar
  • 21
  • 1
0

If you already know the name of the key you're interested in, following works:

-- Assuming you have schema "Example" and the primary key name is "PK_Item"
-- Notice that name of table is irrelevant here but is "Foobar" here
IF (OBJECT_ID('Example.PK_ITEM') IS NULL)
BEGIN
    ALTER TABLE [Example].Foobar ADD CONSTRAINT
    PK_Item PRIMARY KEY ...
END
Pasi Savolainen
  • 2,460
  • 1
  • 22
  • 35