Calculate number of primary and secondary key columns - sql-server

Is there a tool or query that will give me output as the total number of primary and secondary keys in a database table?
UPDATE ANSWER
Please note that secondary key is different from foreign key.
So count of no. of primary keys is possible in 2 ways:-
SELECT *
FROM sys.indexes i
INNER JOIN sys.tables t ON i.object_id = t.object_id AND
t.type = 'U'
LEFT JOIN sys.extended_properties AS EP ON EP.major_id = T.[object_id]
where is_primary_key=1
OR
SELECT COUNT(*) AS 'PRIMARY_KEY_CONSTRAINT'
FROM sys.objects
WHERE type_desc IN ('PRIMARY_KEY_CONSTRAINT')
To count no. of secondary keys use:
SELECT *
FROM sys.indexes i
INNER JOIN sys.tables t ON i.object_id = t.object_id AND
t.type = 'U'
LEFT JOIN sys.extended_properties AS EP ON EP.major_id = T.[object_id]
where is_unique=1 and is_primary_key=0

USE database
SELECT OBJECT_NAME(OBJECT_ID) AS NameofConstraint,
SCHEMA_NAME(schema_id) AS SchemaName,
OBJECT_NAME(parent_object_id) AS TableName
FROM sys.objects
WHERE type_desc IN ('PRIMARY_KEY_CONSTRAINT')
SELECT OBJECT_NAME(OBJECT_ID) AS NameofConstraint,
SCHEMA_NAME(schema_id) AS SchemaName,
OBJECT_NAME(parent_object_id) AS TableName
FROM sys.objects
WHERE type_desc IN ('FOREIGN_KEY_CONSTRAINT')
Simple count
SELECT COUNT(*) AS 'PRIMARY_KEY_CONSTRAINT'
FROM sys.objects
WHERE type_desc IN ('PRIMARY_KEY_CONSTRAINT')
SELECT COUNT(*) AS 'FOREIGN_KEY_CONSTRAINT'
FROM sys.objects
WHERE type_desc IN ('FOREIGN_KEY_CONSTRAINT')

The tool is SQL and this is another method to get what you want. A bit more complex then #kevchadders, but this way you can also make a listing of column names, types, etc
Count Foreign keys
SELECT count(*) from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
WHERE
Col.Constraint_Name = Tab.Constraint_Name
AND Col.Table_Name = Tab.Table_Name
AND Constraint_Type in ( 'FOREIGN KEY')
AND Col.Table_Name in (select name from sysobjects where xtype = 'U')
Count Pirmairy keys
SELECT count(*) from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
WHERE
Col.Constraint_Name = Tab.Constraint_Name
AND Col.Table_Name = Tab.Table_Name
AND Constraint_Type in ('PRIMARY KEY')
AND Col.Table_Name in (select name from sysobjects where xtype = 'U')
For all tables, show the PK and FK
FK
SELECT *, Col.Column_Name from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
WHERE
Col.Constraint_Name = Tab.Constraint_Name
AND Col.Table_Name = Tab.Table_Name
AND Constraint_Type in ('PRIMARY KEY', 'FOREIGN KEY')
AND Col.Table_Name in (select name from sysobjects where xtype = 'U')

You can try this
SELECT 'PRIMARY KEYS' AS KeyType, COUNT(*) AS Total
FROM sys.tables AS TB INNER JOIN
sys.key_constraints AS KC ON KC.parent_object_id = TB.object_id
GROUP BY KC.type
UNION
SELECT 'FOREIGN KEYS' AS KeyType, COUNT(*) AS Total
FROM sys.tables AS TB INNER JOIN
sys.foreign_keys AS FK ON FK.referenced_object_id = TB.object_id
GROUP BY FK.type

Related

How to get column-wise constraints in SQL Server

I am using below query to get constraints on required table:
SELECT
OBJECT_NAME(o.object_id) AS ConstraintName,
SCHEMA_NAME(schema_id) AS SchemaName,
OBJECT_NAME(parent_object_id) AS TableName,
type_desc AS ConstraintType
FROM
sys.objects o
-- INNER JOIN
-- sys.columns c ON o.object_id = c.object_id
WHERE
type_desc LIKE '%CONSTRAINT'
AND OBJECT_NAME(parent_object_id)= 'All_Data_Types'
Successfully getting table-wise constraint details. But, I want column's information as well.
Could someone help me with this?
Thanks in advance
Fast solution for default constraint is
SELECT dc.object_id AS ConstraintID, DC.name AS ConstraintName
, O.object_id AS TableID, O.name AS TableName
, C.object_id AS ColumnID, C.name AS ColName
FROM sys.default_constraints AS DC
LEFT JOIN sys.objects AS O ON O.object_id = DC.parent_object_id
LEFT JOIN sys.columns c ON o.object_id = c.object_id AND DC.parent_column_id = c.column_id
For table constraints you could use something like this:
SELECT KCU.*, TC.CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC ON TC.CONSTRAINT_SCHEMA = KCU.CONSTRAINT_SCHEMA AND TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME
If you are on SQL Server 2012 or later then you can use system view sys.sysconstraints:
Contains mappings of constraints to the objects that own the
constraints within the database.
So, this query:
SELECT *
FROM sys.sysconstraints s
INNER JOIN sys.objects o ON o.object_id = s.constid
theoretically returns the same number of rows as your query. But now you have the additional information about the ID of the column on which the constraint is defined. That is column colid of sys.sysconstraints:
ID of the column on which the constraint is defined.
0 = Table constraint
Thus, using this query:
SELECT OBJECT_NAME(o.object_id) AS ConstraintName,
SCHEMA_NAME(o.schema_id) AS SchemaName,
OBJECT_NAME(o.parent_object_id) AS TableName,
o.type_desc AS ConstraintType,
COALESCE(c.COLUMN_NAME, 'Table constraint') AS ColumnName
FROM sys.sysconstraints s
INNER JOIN sys.objects o ON o.object_id = s.constid
LEFT JOIN INFORMATION_SCHEMA.COLUMNS c ON c.ORDINAL_POSITION = s.colid AND s.colid <> 0
you also get the name the column related to the constraint.
Here is the query. You are using INNER JOIN on wrong column_name of tables.
You used this
INNER JOIN sys.columns c ON o.object_id = c.object_id
I replaced it with
INNER JOIN sys.columns c ON o.parent_object_id = c.object_id
Now you can see the column_name as well as table_name along with constraint_details.
SELECT OBJECT_NAME(o.object_id) AS ConstraintName,
SCHEMA_NAME(schema_id) AS SchemaName,
OBJECT_NAME(parent_object_id) AS TableName,
c.name as ColumnName,
type_desc AS ConstraintType
FROM sys.objects o
INNER JOIN sys.columns c ON o.parent_object_id = c.object_id
WHERE type_desc LIKE '%CONSTRAINT';
Also avoid using the below clause
AND OBJECT_NAME(parent_object_id)= 'All_Data_Types'

How may I find all primary keys in a database and their identity and seed values?

The following query returns a listing of all my database primary keys and additional columns.
SELECT *
FROM sysobjects AS s
WHERE xtype='pk'
None of the aforementioned additional columns are related to a primary key's identity, seed value, increment value, etc.
What query should I use, or how may I find all primary keys in a database and their identity and seed values?
UPDATED
(now uses identity_columns table instead of the IDENT_... functions)
SELECT object_name(i.object_id) tableName,
i.name indexName,
c.name columnName,
c.is_identity,
idc.seed_value,
idc.increment_value,
idc.last_value
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
LEFT OUTER JOIN sys.identity_columns idc ON idc.object_id = c.object_id AND idc.column_id = c.column_id
WHERE i.is_primary_key = 1
Here is an alternate answer b/c I combined selects and added create and modified dates for sorting and schema name for possible dupes between schemas b/c key names are unique:
SELECT schema_name = ( SELECT top 1 pk.CONSTRAINT_SCHEMA FROM information_schema.table_constraints pk INNER JOIN information_schema.key_column_usage c ON c.TABLE_NAME = pk.TABLE_NAME WHERE pk.CONSTRAINT_NAME like '%' + i.name + '%')
,object_name(i.object_id) tableName, i.name indexName, c.name columnName, c.is_identity
,ident_seed(object_name(i.object_id)) seed
,ident_incr(object_name(i.object_id)) increment
,ident_current(object_name(i.object_id)) lastAssignedId
,CreateDate = ( SELECT s.crdate FROM sysobjects s INNER JOIN (SELECT COUNT(1) cnt, xtype FROM sysobjects group by xtype) c ON s.xtype = c.xtype WHERE s.name = i.name)
,ModifiedDate = (SELECT s.refdate FROM sysobjects s INNER JOIN (SELECT COUNT(1) cnt, xtype FROM sysobjects group by xtype) c on s.xtype = c.xtype WHERE s.name = i.name)
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1
ORDER BY ModifiedDate, CreateDate DESC

sql server 2008 - Integer columns with no foreign key

Having inherited a legacy Sql server database, I'd like to list by table all integer columns where there is no foreign key, on the basis that some will be missing an FK, and some will just be integer columns. Can anyone suggest a query to display this information? Clearly there's some human intervention involved here.
Thanks.
You can get it from information_schema. I would start with something like this:
SELECT * from INFORMATION_SCHEMA.COLUMNS c
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
ON
c.TABLE_CATALOG = k.TABLE_CATALOG
AND c.TABLE_SCHEMA = k.TABLE_SCHEMA
AND c.TABLE_NAME = k.TABLE_NAME
AND c.COLUMN_NAME = k.COLUMN_NAME
WHERE c.DATA_TYPE in ('int') AND CONSTRAINT_NAME is null
this one uses sql-server-only views:
select so.name as TableName, col.name as ColumnName
from
sys.objects so
inner join sys.columns col on so.object_id = col.object_id and col.system_type_id in (48,52,56,127)
left outer join sys.foreign_key_columns fkc on fkc.parent_object_id = so.object_id and fkc.parent_column_id = col.column_id
where
so.type='U'
and fkc.constraint_column_id is null
order by so.name

how to get table's schema name

I'm using SQL Server 2008 and have the following query:
SELECT SO1.name AS Tab,
SC1.name AS Col,
SO2.name AS RefTab,
SC2.name AS RefCol,
FO.name AS FKName
FROM dbo.sysforeignkeys FK
INNER JOIN dbo.syscolumns SC1 ON FK.fkeyid = SC1.id AND FK.fkey = SC1.colid
INNER JOIN dbo.syscolumns SC2 ON FK.rkeyid = SC2.id AND FK.rkey = SC2.colid
INNER JOIN dbo.sysobjects SO1 ON FK.fkeyid = SO1.id
INNER JOIN dbo.sysobjects SO2 ON FK.rkeyid = SO2.id
INNER JOIN dbo.sysobjects FO ON FK.constid = FO.id
How do you retrieve the table's schema name?
Thanks for your help
Use OBJECT_SCHEMA_NAME
SELECT
OBJECT_SCHEMA_NAME(f.parent_object_id) AS TableNameSchema, -- this
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id,fc.parent_column_id) AS ColumnName,
OBJECT_SCHEMA_NAME(f.referenced_object_id) AS ReferenceTableNameSchema,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,fc.referenced_column_id) AS ReferenceColumnName,
f.name AS ForeignKey
FROM
sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id
As per Sql Server 2008:
SELECT Object_name(f.parent_object_id)
AS
TableName,
Col_name(fc.parent_object_id, fc.parent_column_id)
AS ColumnName,
Object_name (f.referenced_object_id)
AS ReferenceTableName,
Col_name(fc.referenced_object_id, fc.referenced_column_id)
AS
ReferenceColumnName,
f.name
AS ForeignKey,
Quotename(Schema_name(f.schema_id)) + '.' + Quotename(
Object_name(f.parent_object_id)) AS
schemaname,
Quotename(Schema_name(o.schema_id)) + '.' + Quotename(
Object_name(f.referenced_object_id))
AS ReferenceSchemaName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN sys.objects AS o
ON o.OBJECT_ID = fc.referenced_object_id
If to want to know schema name on basis of object_id then use OBJECT_SCHEMA_NAME(), if you want to get schema name on basis of schema_id then use SCHEMA_NAME().

Get the creation date of a table's column

I found a script to get the column information:
SELECT
crdate as thisFieldIsNotTheCreationOfTheField1 ,
refdate as thisFieldIsNotTheCreationOfTheField2 ,
o.name AS [TableName],
o.type,
c.name AS [ColName],
s.name AS [ColType],
c.prec,
c.scale,
c.isnullable
FROM
dbo.sysobjects AS o
INNER JOIN
dbo.syscolumns AS c ON c.id = o.id
INNER JOIN
dbo.systypes AS s ON c.xtype = s.xtype
WHERE
o.type = 'U' and o.name='TableNa'
ORDER BY
crdate
The column creation datetime isn't found.
How can this be done?
This is what you want :
SELECT obj.create_date
from sys.objects obj
inner join sys.columns col on obj.object_Id=col.object_Id
WHERE col.name = #columnName
and obj.Name=#tableName

Resources