SQL - Finding FK details of column - sql

I have some SQL that gets a few details about a table.
SELECT Column_Name, Is_Nullable, Data_Type, Character_Maximum_Length
FROM Information_Schema.Columns
WHERE Table_Name='GenSchool'
This is working ok so far and returns a row per column in the table. What I want however, is for it to also return some Foreign Key details too. For example, GenSchool has a column SchoolType which has a FK to GenSchoolType.Code.
As well as the columns selected above, I need the query to return the FK table and column name of linked table or NULL where the column doesn't have a FK.
This is returned from the query above.
Code NO nvarchar 10
CodeDescription YES nvarchar 80
Deleted NO bit NULL
Type NO nvarchar 20
And I'd like it to return something like
Code NO nvarchar 10 NULL NULL
CodeDescription YES nvarchar 80 NULL NULL
Deleted NO bit NULL NULL NULL
Type NO nvarchar 20 GenSchoolType Code
I've been trying for ages using inner joins on sys tables but I'm not getting anywhere. If you need me to show what I've tried I can.
Thank you in advance.

So I finally worked out the solution.
with fks as (
select fk.name AS 'FKName', o_p.name AS 'ParentNameTable',
c_p.name AS 'ParentNameColumn', o_r.name AS 'ReferencedNameTable',
c_r.name AS 'ReferencedNameColumn', fkc.*
from sys.foreign_key_columns fkc
inner join sys.foreign_keys fk on fk.object_id = fkc.constraint_object_id
inner join sys.objects o_p on o_p.object_id = fkc.parent_object_id
inner join sys.objects o_r on o_r.object_id = fkc.referenced_object_id
inner join sys.columns c_p on c_p.object_id = fkc.parent_object_id and c_p.column_id = fkc.parent_column_id
inner join sys.columns c_r on c_r.object_id = fkc.referenced_object_id and c_r.column_id = fkc.referenced_column_id
)
select c.Table_Name, c.Column_Name, c.Is_Nullable, c.Data_Type,
c.Character_Maximum_Length, COLUMNPROPERTY(OBJECT_ID(#table),
c.Column_Name,'IsIdentity') AS 'Is_Identity',
fks.FKName, fks.ReferencedNameTable, fks.ReferencedNameColumn
from information_schema.columns c
left join fks on c.Table_Name = fks.ParentNameTable and c.Column_Name = fks.ParentNameColumn
where c.table_name = #table
This returns a row per column in the database with the following data
Table Name
Column Name
Nullable
Data Type
Max Length
Identity
FK Name
Table Referenced
Column Referenced
Feel free to use this if it meets your needs.

Join to information_schema.REFERENTIAL_CONSTRAINTS:
SELECT Column_Name, Is_Nullable, Data_Type, Character_Maximum_Length, rc.REFERENCED_TABLE_NAME
FROM Information_Schema.Columns c
left join information_schema.REFERENTIAL_CONSTRAINTS rc on rc.TABLE_NAME = c.TABLE_NAME
WHERE Table_Name='GenSchool'

Here is a query from the MSDN page related to your query.
SELECT TABLE_NAME, CONSTRAINT_NAME , COLUMN_NAME , ORDINAL_POSITION
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE CONSTRAINT_NAME IN (
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS)
ORDER BY TABLE_NAME, ORDINAL_POSITION

did you try sp_fkeys
exec sp_fkeys <TableName>

Related

Column Names from SQL Server

I am trying without success to get column names of my table in SQL Server.
I have tried the following:
SELECT * FROM [myDB].INFORMATION_SCHEMA.COLUMNS where [TABLE_NAME] = N'myTable'
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='myTable'
SELECT COLUMN_NAME , *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable' AND TABLE_SCHEMA='dbo'
SELECT [name] AS [Column Name]
FROM syscolumns
WHERE id = (SELECT id FROM sysobjects WHERE [Name] = 'myTable')
SELECT c.name FROM sys.columns c
INNER JOIN sys.tables t
ON t.object_id = c.object_id
AND t.name = 'myTable'
What is being returned is, what I think is, meta data of the table.
While in fact the actual column names are:
How can I return the column names from 'myTable'?
This solution returned the list I was looking for
SELECT name
FROM sys.columns
WHERE object_id = Object_id('myTable')

how to get table structure with column name in a single row?

Can anyone help me with the query to get table name,column name , column datatype , isprimary etc in single row .
for eg:
My output of employee table with Columns E_Id,E_Name,E_City should be as below
TabName ColumnName datatype isprimary Columnname datatype isprimary Columnname datatype
Employee - E_Id - int - S - E_Name - varchar - N - E_City - varchar
You can use the INFORMATION_SCHEMA system views to get this information for any table.
The following is an example:
SELECT
c.TABLE_NAME,
c.COLUMN_NAME,
c.DATA_TYPE,
CASE WHEN tc.CONSTRAINT_NAME IS NOT NULL THEN 1 ELSE 0 END AS IsPrimary
FROM INFORMATION_SCHEMA.COLUMNS c
LEFT JOIN (
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
ON tc.CONSTRAINT_NAME = ccu.CONSTRAINT_NAME
AND tc.CONSTRAINT_SCHEMA = ccu.CONSTRAINT_SCHEMA
AND tc.CONSTRAINT_CATALOG = ccu.CONSTRAINT_CATALOG
AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
)
ON ccu.COLUMN_NAME = c.COLUMN_NAME
AND ccu.TABLE_NAME = c.TABLE_NAME
AND ccu.TABLE_SCHEMA = c.TABLE_SCHEMA
AND ccu.TABLE_CATALOG = c.TABLE_CATALOG
WHERE c.TABLE_NAME = 'Employee'
You can get table schema from the following,
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'TABLENAME';
GO
(but the output format is not like you want)
source: http://technet.microsoft.com/en-us/library/ms186778.aspx

SQL Server: Return list of columns shared by a group of database tables

I'm inheriting a large report that we would like to automate. I believe most of the data is in a data warehouse that I can access through SQL Server. The issue I have is that I do not have a lot of documentation (data dictionary, schema, etc.) and I want to determine which fields are common among several tables. Normally, when I want to return a list of tables and columns, I would query the information schema. However, in this case, I'm basically looking for a query that is something like:
select table_name, column_name
from (information_schema, others?)
where table_name like 'T_Blah %'
and column_names are equal
I realize I can get to this through the object browser, but once I start getting into a larger number of tables, I would like a quick query-based approach to identifying my fields for joining.
I appreciate any help I can get. I googled this for a while, but I didn't find a solution (or I was oblivious to the fact that I had found one).
As well as information schema you also have the system table syscolumns. Assuming you use the former, something like this should work:
select column_name, count(distinct table_name)
from information_schema.columns
group by column_name
having count(distinct table_name) > 1
Obviously you could restrict by table name/schema if you wanted to look at a subset
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
If I understood yo correctly, you can try this:
SELECT TABLE_NAME, COLUMN_NAME
FROM ( SELECT *, COUNT(*) OVER(PARTITION BY COLUMN_NAME) Quant
FROM INFORMATION_SCHEMA.COLUMNS) A
WHERE TABLE_NAME LIKE 'T_Blah%' AND Quant > 1
ORDER BY COLUMN_NAME, TABLE_NAME
This should work for sql-server. This is just a query I keep on hand, so it is a little more than you requested. But, I kept it in case you want the extra info :). Just remove it if not.
select distinct columns.name, schemas.name + '.' + tables.name
from sys.columns
join sys.tables
on tables.object_id = columns.object_id
join sys.schemas
on schemas.schema_id = tables.schema_id
where tables.name like '%blah%'
order by columns.name, schemas.name + '.' + tables.name
This will yield the column names and data types in a specified table that also appear in other tables followed by a comma separated list of tables in which they appear:
SELECT COLUMN_NAME, DATA_TYPE, REPLACE(REPLACE(REPLACE(
(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (COLUMN_NAME = CommonColumns.COLUMN_NAME) AND (DATA_TYPE = CommonColumns.DATA_TYPE)
FOR XML PATH(''))
, '</TABLE_NAME><TABLE_NAME>', ', '), '<TABLE_NAME>', ''), '</TABLE_NAME>', '')
AS Tables
FROM (SELECT DISTINCT COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'T_Blah%') AS CommonColumns
WHERE (SELECT COUNT(TABLE_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (COLUMN_NAME = CommonColumns.COLUMN_NAME) AND (DATA_TYPE = CommonColumns.DATA_TYPE)) > 1
To have it do this for all tables, simply remove the WHERE TABLE_NAME LIKE 'T_Blah%'.
Or as Aaron recommends, avoid INFORMATION_SCHEMA:
SELECT ColumnName, sys.types.name AS DataType, REPLACE(REPLACE(REPLACE(
(SELECT sys.tables.name AS TableName
FROM sys.columns INNER JOIN
sys.tables ON sys.columns.object_id = sys.tables.object_id
WHERE (sys.tables.type = 'U') AND (sys.columns.name = CommonColumns.ColumnName) AND
(sys.columns.system_type_id = CommonColumns.system_type_id)
FOR XML PATH(''))
, '</TableName><TableName>', ', '), '<TableName>', ''), '</TableName>', '')
AS Tables
FROM (SELECT DISTINCT sys.columns.name AS ColumnName, sys.columns.system_type_id
FROM sys.columns INNER JOIN
sys.tables ON sys.columns.object_id = sys.tables.object_id
WHERE (sys.tables.type = 'U') AND (sys.tables.name LIKE 'T_Blah%')) AS CommonColumns INNER JOIN
sys.types ON sys.types.system_type_id = CommonColumns.system_type_id
WHERE ((SELECT COUNT(sys.tables.object_id) AS TableCount
FROM sys.columns INNER JOIN
sys.tables ON sys.columns.object_id = sys.tables.object_id
WHERE (sys.tables.type = 'U') AND (sys.columns.name = CommonColumns.ColumnName) AND
(sys.columns.system_type_id = CommonColumns.system_type_id)) > 1)
ORDER BY CommonColumns.ColumnName, sys.types.name
To get relations by foreign keys use:
SELECT sys.foreign_keys.name AS ForeignKeyName, OBJECT_NAME(sys.foreign_key_columns.parent_object_id) AS ForeignKeyTableName,
ForeignKeyColumns.name AS ForeignKeyColumnName, OBJECT_NAME(sys.foreign_key_columns.referenced_object_id) AS ReferencedTableName,
ReferencedColumns.name AS ReferencedColumnName
FROM sys.foreign_keys INNER JOIN
sys.foreign_key_columns ON sys.foreign_keys.object_id = sys.foreign_key_columns.constraint_object_id INNER JOIN
sys.columns AS ForeignKeyColumns ON sys.foreign_key_columns.parent_object_id = ForeignKeyColumns.object_id AND
sys.foreign_key_columns.parent_column_id = ForeignKeyColumns.column_id INNER JOIN
sys.columns AS ReferencedColumns ON sys.foreign_key_columns.referenced_object_id = ReferencedColumns.object_id AND
sys.foreign_key_columns.referenced_column_id = ReferencedColumns.column_id
WHERE (OBJECT_NAME(sys.foreign_key_columns.parent_object_id) LIKE 'T_Blah%') OR (OBJECT_NAME(sys.foreign_key_columns.referenced_object_id)
LIKE 'T_Blah%')

SQL Server: Get table primary key using sql query [duplicate]

This question already has answers here:
How do you list the primary key of a SQL Server table?
(28 answers)
Closed 3 years ago.
I want to get a particular table's primary key using SQL query for SQL Server database.
In MySQL I am using following query to get table primary key:
SHOW KEYS FROM tablename WHERE Key_name = 'PRIMARY'
What is equivalent of above query for SQL Server ?.
If There is a query that will work for both MySQL and SQL Server then It will be an ideal case.
I also found another one for SQL Server:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
AND TABLE_NAME = 'TableName' AND TABLE_SCHEMA = 'Schema'
Found another one:
SELECT
KU.table_name as TABLENAME
,column_name as PRIMARYKEYCOLUMN
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU
ON TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
AND KU.table_name='YourTableName'
ORDER BY
KU.TABLE_NAME
,KU.ORDINAL_POSITION
;
I have tested this on SQL Server 2003/2005
Using SQL SERVER 2005, you can try
SELECT i.name AS IndexName,
OBJECT_NAME(ic.OBJECT_ID) AS TableName,
COL_NAME(ic.OBJECT_ID,ic.column_id) AS ColumnName
FROM sys.indexes AS i INNER JOIN
sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID
AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
Found at SQL SERVER – 2005 – Find Tables With Primary Key Constraint in Database
From memory, it's either this
SELECT * FROM sys.objects
WHERE type = 'PK'
AND object_id = OBJECT_ID ('tableName')
or this..
SELECT * FROM sys.objects
WHERE type = 'PK'
AND parent_object_id = OBJECT_ID ('tableName')
I think one of them should probably work depending on how the data is stored
but I am afraid I have no access to SQL to actually verify the same.
SELECT COLUMN_NAME FROM {DATABASENAME}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME LIKE '{TABLENAME}' AND CONSTRAINT_NAME LIKE 'PK%'
WHERE
{DATABASENAME} = your database from your server AND
{TABLENAME} = your table name from which you want to see the primary key.
NOTE : enter your database name and table name without brackets.
select *
from sysobjects
where xtype='pk' and
parent_obj in (select id from sysobjects where name='tablename')
this will work in sql 2005
The code I'll give you works and retrieves not only keys, but a lot of data from a table in SQL Server. Is tested in SQL Server 2k5/2k8, dunno about 2k. Enjoy!
SELECT DISTINCT
sys.tables.object_id AS TableId,
sys.columns.column_id AS ColumnId,
sys.columns.name AS ColumnName,
sys.types.name AS TypeName,
sys.columns.precision AS NumericPrecision,
sys.columns.scale AS NumericScale,
sys.columns.is_nullable AS IsNullable,
( SELECT
COUNT(column_name)
FROM
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE
TABLE_NAME = sys.tables.name AND
CONSTRAINT_NAME =
( SELECT
constraint_name
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
TABLE_NAME = sys.tables.name AND
constraint_type = 'PRIMARY KEY' AND
COLUMN_NAME = sys.columns.name
)
) AS IsPrimaryKey,
sys.columns.max_length / 2 AS CharMaxLength /*BUG*/
FROM
sys.columns, sys.types, sys.tables
WHERE
sys.tables.object_id = sys.columns.object_id AND
sys.types.system_type_id = sys.columns.system_type_id AND
sys.types.user_type_id = sys.columns.user_type_id AND
sys.tables.name = 'TABLE'
ORDER BY
IsPrimaryKey
You can use only the primary key part, but I think that the rest might become handy.
Best regards,
David
This should list all the constraints and at the end you can put your filters
/* CAST IS DONE , SO THAT OUTPUT INTEXT FILE REMAINS WITH SCREEN LIMIT*/
WITH ALL_KEYS_IN_TABLE (CONSTRAINT_NAME,CONSTRAINT_TYPE,PARENT_TABLE_NAME,PARENT_COL_NAME,PARENT_COL_NAME_DATA_TYPE,REFERENCE_TABLE_NAME,REFERENCE_COL_NAME)
AS
(
SELECT CONSTRAINT_NAME= CAST (PKnUKEY.name AS VARCHAR(30)) ,
CONSTRAINT_TYPE=CAST (PKnUKEY.type_desc AS VARCHAR(30)) ,
PARENT_TABLE_NAME=CAST (PKnUTable.name AS VARCHAR(30)) ,
PARENT_COL_NAME=CAST ( PKnUKEYCol.name AS VARCHAR(30)) ,
PARENT_COL_NAME_DATA_TYPE= oParentColDtl.DATA_TYPE,
REFERENCE_TABLE_NAME='' ,
REFERENCE_COL_NAME=''
FROM sys.key_constraints as PKnUKEY
INNER JOIN sys.tables as PKnUTable
ON PKnUTable.object_id = PKnUKEY.parent_object_id
INNER JOIN sys.index_columns as PKnUColIdx
ON PKnUColIdx.object_id = PKnUTable.object_id
AND PKnUColIdx.index_id = PKnUKEY.unique_index_id
INNER JOIN sys.columns as PKnUKEYCol
ON PKnUKEYCol.object_id = PKnUTable.object_id
AND PKnUKEYCol.column_id = PKnUColIdx.column_id
INNER JOIN INFORMATION_SCHEMA.COLUMNS oParentColDtl
ON oParentColDtl.TABLE_NAME=PKnUTable.name
AND oParentColDtl.COLUMN_NAME=PKnUKEYCol.name
UNION ALL
SELECT CONSTRAINT_NAME= CAST (oConstraint.name AS VARCHAR(30)) ,
CONSTRAINT_TYPE='FK',
PARENT_TABLE_NAME=CAST (oParent.name AS VARCHAR(30)) ,
PARENT_COL_NAME=CAST ( oParentCol.name AS VARCHAR(30)) ,
PARENT_COL_NAME_DATA_TYPE= oParentColDtl.DATA_TYPE,
REFERENCE_TABLE_NAME=CAST ( oReference.name AS VARCHAR(30)) ,
REFERENCE_COL_NAME=CAST (oReferenceCol.name AS VARCHAR(30))
FROM sys.foreign_key_columns FKC
INNER JOIN sys.sysobjects oConstraint
ON FKC.constraint_object_id=oConstraint.id
INNER JOIN sys.sysobjects oParent
ON FKC.parent_object_id=oParent.id
INNER JOIN sys.all_columns oParentCol
ON FKC.parent_object_id=oParentCol.object_id /* ID of the object to which this column belongs.*/
AND FKC.parent_column_id=oParentCol.column_id/* ID of the column. Is unique within the object.Column IDs might not be sequential.*/
INNER JOIN sys.sysobjects oReference
ON FKC.referenced_object_id=oReference.id
INNER JOIN INFORMATION_SCHEMA.COLUMNS oParentColDtl
ON oParentColDtl.TABLE_NAME=oParent.name
AND oParentColDtl.COLUMN_NAME=oParentCol.name
INNER JOIN sys.all_columns oReferenceCol
ON FKC.referenced_object_id=oReferenceCol.object_id /* ID of the object to which this column belongs.*/
AND FKC.referenced_column_id=oReferenceCol.column_id/* ID of the column. Is unique within the object.Column IDs might not be sequential.*/
)
select * from ALL_KEYS_IN_TABLE
where
PARENT_TABLE_NAME in ('YOUR_TABLE_NAME')
or REFERENCE_TABLE_NAME in ('YOUR_TABLE_NAME')
ORDER BY PARENT_TABLE_NAME,CONSTRAINT_NAME;
For reference please read thru - http://blogs.msdn.com/b/sqltips/archive/2005/09/16/469136.aspx
Keep in mind that if you want to get exact primary field you need to put TABLE_NAME and TABLE_SCHEMA into the condition.
this solution should work:
select COLUMN_NAME from information_schema.KEY_COLUMN_USAGE
where CONSTRAINT_NAME='PRIMARY' AND TABLE_NAME='TABLENAME'
AND TABLE_SCHEMA='DATABASENAME'
It is also (Transact-SQL) ... according to BOL.
-- exec sp_serveroption 'SERVER NAME', 'data access', 'true' --execute once
EXEC sp_primarykeys #table_server = N'server_name',
#table_name = N'table_name',
#table_catalog = N'db_name',
#table_schema = N'schema_name'; --frequently 'dbo'

How do I find a default constraint using INFORMATION_SCHEMA?

I'm trying to test if a given default constraint exists. I don't want to use the sysobjects table, but the more standard INFORMATION_SCHEMA.
I've used this to check for tables and primary key constraints before, but I don't see default constraints anywhere.
Are they not there? (I'm using MS SQL Server 2000).
EDIT: I'm looking to get by the name of the constraint.
As I understand it, default value constraints aren't part of the ISO standard, so they don't appear in INFORMATION_SCHEMA. INFORMATION_SCHEMA seems like the best choice for this kind of task because it is cross-platform, but if the information isn't available one should use the object catalog views (sys.*) instead of system table views, which are deprecated in SQL Server 2005 and later.
Below is pretty much the same as #user186476's answer. It returns the name of the default value constraint for a given column. (For non-SQL Server users, you need the name of the default in order to drop it, and if you don't name the default constraint yourself, SQL Server creates some crazy name like "DF_TableN_Colum_95AFE4B5". To make it easier to change your schema in the future, always explicitly name your constraints!)
-- returns name of a column's default value constraint
SELECT
default_constraints.name
FROM
sys.all_columns
INNER JOIN
sys.tables
ON all_columns.object_id = tables.object_id
INNER JOIN
sys.schemas
ON tables.schema_id = schemas.schema_id
INNER JOIN
sys.default_constraints
ON all_columns.default_object_id = default_constraints.object_id
WHERE
schemas.name = 'dbo'
AND tables.name = 'tablename'
AND all_columns.name = 'columnname'
You can use the following to narrow the results even more by specifying the Table Name and Column Name that the Default Constraint correlates to:
select * from sysobjects o
inner join syscolumns c
on o.id = c.cdefault
inner join sysobjects t
on c.id = t.id
where o.xtype = 'D'
and c.name = 'Column_Name'
and t.name = 'Table_Name'
There seems to be no Default Constraint names in the Information_Schema views.
use SELECT * FROM sysobjects WHERE xtype = 'D' AND name = #name
to find a default constraint by name
The script below lists all the default constraints and the default values for the user tables in the database in which it is being run:
SELECT
b.name AS TABLE_NAME,
d.name AS COLUMN_NAME,
a.name AS CONSTRAINT_NAME,
c.text AS DEFAULT_VALUE
FROM sys.sysobjects a INNER JOIN
(SELECT name, id
FROM sys.sysobjects
WHERE xtype = 'U') b on (a.parent_obj = b.id)
INNER JOIN sys.syscomments c ON (a.id = c.id)
INNER JOIN sys.syscolumns d ON (d.cdefault = a.id)
WHERE a.xtype = 'D'
ORDER BY b.name, a.name
If you want to get a constraint by the column or table names, or you want to get all the constraints in the database, look to other answers. However, if you're just looking for exactly what the question asks, namely, to "test if a given default constraint exists ... by the name of the constraint", then there's a much easier way.
Here's a future-proof answer that doesn't use the sysobjects or other sys tables at all:
IF object_id('DF_CONSTRAINT_NAME', 'D') IS NOT NULL BEGIN
-- constraint exists, work with it.
END
select c.name, col.name from sys.default_constraints c
inner join sys.columns col on col.default_object_id = c.object_id
inner join sys.objects o on o.object_id = c.parent_object_id
inner join sys.schemas s on s.schema_id = o.schema_id
where s.name = #SchemaName and o.name = #TableName and col.name = #ColumnName
Is the COLUMN_DEFAULT column of INFORMATION_SCHEMA.COLUMNS what you are looking for?
Necromancing.
If you only need to check if a default-constraint exists
(default-constraint(s) may have different name in poorly-managed DBs),
use INFORMATION_SCHEMA.COLUMNS (column_default):
IF NOT EXISTS(
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE (1=1)
AND TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'T_VWS_PdfBibliothek'
AND COLUMN_NAME = 'PB_Text'
AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
EXECUTE('ALTER TABLE dbo.T_VWS_PdfBibliothek
ADD CONSTRAINT DF_T_VWS_PdfBibliothek_PB_Text DEFAULT (N''image'') FOR PB_Text;
');
END
If you want to check by the constraint-name only:
-- Alternative way:
IF OBJECT_ID('DF_CONSTRAINT_NAME', 'D') IS NOT NULL
BEGIN
-- constraint exists, deal with it.
END
And last but not least, you can just create a view called INFORMATION_SCHEMA.DEFAULT_CONSTRAINTS:
CREATE VIEW INFORMATION_SCHEMA.DEFAULT_CONSTRAINTS
AS
SELECT
DB_NAME() AS CONSTRAINT_CATALOG
,csch.name AS CONSTRAINT_SCHEMA
,dc.name AS CONSTRAINT_NAME
,DB_NAME() AS TABLE_CATALOG
,sch.name AS TABLE_SCHEMA
,syst.name AS TABLE_NAME
,sysc.name AS COLUMN_NAME
,COLUMNPROPERTY(sysc.object_id, sysc.name, 'ordinal') AS ORDINAL_POSITION
,dc.type_desc AS CONSTRAINT_TYPE
,dc.definition AS COLUMN_DEFAULT
-- ,dc.create_date
-- ,dc.modify_date
FROM sys.columns AS sysc -- 46918 / 3892 with inner joins + where
-- FROM sys.all_columns AS sysc -- 55429 / 3892 with inner joins + where
INNER JOIN sys.tables AS syst
ON syst.object_id = sysc.object_id
INNER JOIN sys.schemas AS sch
ON sch.schema_id = syst.schema_id
INNER JOIN sys.default_constraints AS dc
ON sysc.default_object_id = dc.object_id
INNER JOIN sys.schemas AS csch
ON csch.schema_id = dc.schema_id
WHERE (1=1)
AND dc.is_ms_shipped = 0
/*
WHERE (1=1)
AND sch.name = 'dbo'
AND syst.name = 'tablename'
AND sysc.name = 'columnname'
*/
WHILE EXISTS(
SELECT * FROM sys.all_columns
INNER JOIN sys.tables ST ON all_columns.object_id = ST.object_id
INNER JOIN sys.schemas ON ST.schema_id = schemas.schema_id
INNER JOIN sys.default_constraints ON all_columns.default_object_id = default_constraints.object_id
WHERE
schemas.name = 'dbo'
AND ST.name = 'MyTable'
)
BEGIN
DECLARE #SQL NVARCHAR(MAX) = N'';
SET #SQL = ( SELECT TOP 1
'ALTER TABLE ['+ schemas.name + '].[' + ST.name + '] DROP CONSTRAINT ' + default_constraints.name + ';'
FROM
sys.all_columns
INNER JOIN
sys.tables ST
ON all_columns.object_id = ST.object_id
INNER JOIN
sys.schemas
ON ST.schema_id = schemas.schema_id
INNER JOIN
sys.default_constraints
ON all_columns.default_object_id = default_constraints.object_id
WHERE
schemas.name = 'dbo'
AND ST.name = 'MyTable'
)
PRINT #SQL
EXECUTE sp_executesql #SQL
--End if Error
IF ##ERROR <> 0
BREAK
END
I don't think it's in the INFORMATION_SCHEMA - you'll probably have to use sysobjects or related deprecated tables/views.
You would think there would be a type for this in INFORMATION_SCHEMA.TABLE_CONSTRAINTS, but I don't see one.
Probably because on some of the other SQL DBMSs the "default constraint" is not really a constraint, you'll not find its name in "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", so your best bet is "INFORMATION_SCHEMA.COLUMNS" as others have mentioned already.
(SQLServer-ignoramus here)
The only a reason I can think of when you have to know the "default constraint"'s name is if SQLServer doesn't support "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..." command. But then you are already in a non-standard zone and you have to use the product-specific ways to get what you need.
How about using a combination of CHECK_CONSTRAINTS and CONSTRAINT_COLUMN_USAGE:
select columns.table_name,columns.column_name,columns.column_default,checks.constraint_name
from information_schema.columns columns
inner join information_schema.constraint_column_usage usage on
columns.column_name = usage.column_name and columns.table_name = usage.table_name
inner join information_schema.check_constraints checks on usage.constraint_name = checks.constraint_name
where columns.column_default is not null
I am using folllowing script to retreive all defaults (sp_binddefaults) and all default constraint with following scripts:
SELECT
t.name AS TableName, c.name AS ColumnName, SC.COLUMN_DEFAULT AS DefaultValue, dc.name AS DefaultConstraintName
FROM
sys.all_columns c
JOIN sys.tables t ON c.object_id = t.object_id
JOIN sys.schemas s ON t.schema_id = s.schema_id
LEFT JOIN sys.default_constraints dc ON c.default_object_id = dc.object_id
LEFT JOIN INFORMATION_SCHEMA.COLUMNS SC ON (SC.TABLE_NAME = t.name AND SC.COLUMN_NAME = c.name)
WHERE
SC.COLUMN_DEFAULT IS NOT NULL
--WHERE t.name = '' and c.name = ''
Object Catalog View : sys.default_constraints
The information schema views INFORMATION_SCHEMA are ANSI-compliant, but the default constraints aren't a part of ISO standard. Microsoft SQL Server provides system catalog views for getting information about SQL Server object metadata.
sys.default_constraints system catalog view used to getting the information about default constraints.
SELECT so.object_id TableName,
ss.name AS TableSchema,
cc.name AS Name,
cc.object_id AS ObjectID,
sc.name AS ColumnName,
cc.parent_column_id AS ColumnID,
cc.definition AS Defination,
CONVERT(BIT,
CASE cc.is_system_named
WHEN 1
THEN 1
ELSE 0
END) AS IsSystemNamed,
cc.create_date AS CreationDate,
cc.modify_date AS LastModifiednDate
FROM sys.default_constraints cc WITH (NOLOCK)
INNER JOIN sys.objects so WITH (NOLOCK) ON so.object_id = cc.parent_object_id
LEFT JOIN sys.schemas ss WITH (NOLOCK) ON ss.schema_id = so.schema_id
LEFT JOIN sys.columns sc WITH (NOLOCK) ON sc.column_id = cc.parent_column_id
AND sc.object_id = cc.parent_object_id
ORDER BY so.name,
cc.name;
A bit of a cleaner way to do this:
SELECT DC.[name]
FROM [sys].[default_constraints] AS DC
WHERE DC.[parent_object_id] = OBJECT_ID('[Schema].[TableName]')
If the target database has, say, over 1M objects, using sys.default_constraints can hit you with 90%+ taken on scanning sys.syscolpars followed by a Key Lookup for the dflt you likely don't care about. On my DB, it takes 1.129s to assemble just 4 rows from the 158 read of the residual I/O impaired 1.12MM rows actually scanned.
Changing to using the current sys.% tables/views, using #Tim's query, the same 4 constraints are acquired in 2ms. Hope someone finds this as useful as I found Tim's:
SELECT ConstraintName = sdc.name
, SchemaName = ssch.name
, TableName = stab.name
, ColumnName = scol.name
FROM sys.objects sdc
INNER JOIN sys.columns scol
ON scol.default_object_id = sdc.object_id
INNER JOIN sys.objects stab
ON stab.object_id = scol.object_id
INNER JOIN sys.schemas ssch
ON ssch.schema_id = stab.schema_id;