Update table with matching primary keys - sql

I have two tables TABLE1 and TABLE2.
I need to update TABLE1 with the matching primary keys from TABLE2.
Here is my code to get the primary key from TABLE1:
SELECT C.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE C ON C.CONSTRAINT_NAME = T.CONSTRAINT_NAME
WHERE C.TABLE_NAME = 'TABLE1'
AND T.CONSTRAINT_TYPE = 'PRIMARY KEY'
This is the code to get primary key for TABLE2:
SELECT C.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE C ON C.CONSTRAINT_NAME = T.CONSTRAINT_NAME
WHERE C.TABLE_NAME = 'TABLE2'
AND T.CONSTRAINT_TYPE = 'PRIMARY KEY'
And this code is used to update TABLE1:
MERGE INTO <TABLE1>
USING <TABLE2> ON (TABLE1.COLUMN_NAME = TABLE2.COLUMN_NAME)
WHEN MATCHED THEN
UPDATE
SET <TABLE1.COLUMN_NAME> = <TABLE1.COLUMN_NAME>
I need to merge all snippets of code to update the TABLE1, please help me how to get the primary keys and update with a single code.

As #GuidoG recommended, you will probably need to use dynamic SQL to perform this feat. Furthermore, from your question it is hard to figure out how to determine that Table1 and Table2 are related to one another.
Let us suppose that you have a table with table pairs available, and Table1 and Table 2 are one of those pairs. We'll need to figure out what the primary keys of both tables are, and then build the dynamic SQL using this information.
DECLARE #tableCombinations TABLE ([MainTable] NVARCHAR(255), [SubTable] NVARCHAR(255))
INSERT INTO #tableCombinations ([MainTable], [SubTable]) VALUES ('Table1','Table2')
DECLARE #q NVARCHAR(MAX) = ''
;WITH PrimaryKeys AS (
SELECT [Schema_Name] = sch.[name]
, [Table_Name] = tbl.[name]
, [Column_Name] = cols.[name]
FROM [sys].[indexes] i
JOIN [sys].[index_columns] ic ON i.[index_id] = ic.[index_id] AND i.[object_id] = ic.[object_id]
JOIN [sys].[columns] cols ON cols.[object_id] = ic.[object_id] AND cols.[column_id] = ic.[column_id]
JOIN [sys].[tables] tbl ON ic.[object_id] = tbl.[object_id]
JOIN [sys].[schemas] sch ON tbl.[schema_Id] = sch.[schema_id]
WHERE i.[is_primary_key] = 1
)
SELECT #q += 'MERGE INTO ' + QUOTENAME(pkMain.[Schema_Name]) + '.' + QUOTENAME(pkMain.[Table_Name]) +' mt
USING ' + QUOTENAME(pkSub.[Schema_Name]) + '.' + QUOTENAME(pkSub.[Table_Name]) + 'st ON (
mt.' + QUOTENAME(pkMain.[Column_Name]) + ' = st.' + pkSub.[Column_Name] + ')
WHEN MATCHED THEN UPDATE SET mt.' + QUOTENAME(pkMain.[Column_Name]) + ' = st.' + pkSub.[Column_Name] + ';' + CHAR(13) + CHAR(10)
FROM #tableCombinations tc
JOIN [PrimaryKeys] pkMain ON tc.[MainTable] = pkMain.[Table_Name]
JOIN [PrimaryKeys] pkSub ON tc.[SubTable] = pkSub.[Table_Name]
SET #q = REPLACE(#q, ' ', '')
SELECT #q
Of course, if this yields the correct results, you can directly execute this query using [sys].[sp_executesql]. For more reliable results, be sure to include the schema names of the table combinations.

Related

Delete unrelated records in one of some related tables

There is a table MainTable with a column MyField. There are some tables related by foreign keys to MainTable. Their names are unknown.
I need:
to find and delete all rows in MainTable which have no relation to any other table
query should return all MyField values of these deleted rows
Or as an option: query should return all MyField values for rows which are to be deleted.
Thanks!
UpDate1
Sorry I forgot to say I use Sql Server 2005.
MainTable has PK.
Other tables have FK.
Example
create table MainTable
(
ID int IDENTITY primary key,
MyField nvarchar(256)
);
create table OtherTable1
(
ID int IDENTITY primary key,
MainTableID int foreign key references MainTable(ID)
);
create table OtherTable2
(
ID int IDENTITY primary key,
MainTableID int foreign key references MainTable(ID)
);
-- and so on
insert into MainTable (MyField) values('A');
insert into MainTable (MyField) values('BB');
insert into MainTable (MyField) values('CCC');
insert into MainTable (MyField) values('DDDD');
insert into MainTable (MyField) values('FFFFF');
insert into OtherTable1 (MainTableID) values(1);
insert into OtherTable1 (MainTableID) values(2);
insert into OtherTable2 (MainTableID) values(3);
Result i need:
MainTable
ID MyField
4 DDDD
5 FFFFF
Query should return
A
BB
CCC
You need dynamic SQL for this.
You can use the system views to pull out the foreign key information and build up a dynamic statement, either SELECT or DELETE.
DECLARE #sql nvarchar(max) = '
SELECT t.MyField
-- alternately DELETE t
FROM MainTable t
WHERE ' + (
SELECT STRING_AGG(CAST(
'
NOT EXISTS (SELECT 1
FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' t2.
WHERE ' + c.ForeignKeys + ')
'
AS nvarchar(max)), '
AND '
)
FROM sys.tables MyTable
JOIN sys.foreign_keys fk ON fk.referenced_object_id = MyTable.object_id
JOIN sys.tables t ON t.object_id = fk.parent_object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
OUTER APPLY (
SELECT STRING_AGG('t2.' + QUOTENAME(c.name) + ' = t.' + QUOTENAME(cMyTable.name), ' AND ')
FROM sys.foreign_key_columns fkc
JOIN sys.columns c ON c.object_id = fk.parent_object_id AND c.column_id = fkc.parent_column_id
JOIN sys.columns cMyTable ON cMyTable.object_id = MyTable.object_id AND cMyTable.column_id = fkc.referenced_column_id
WHERE fkc.constraint_object_id = fk.object_id
) c(ForeignKeys)
WHERE MyTable.name = 'MainTable'
);
PRINT #sql; -- for testing
EXEC sp_executesql #sql;
db<>fiddle

How to get the relationship between 2 random tables in relational database

My requirement is to Join table A and table D. I know there are tables B and C in between which have PK and FK relationships. I want a query to know the tables B and C and the keys involved in the relationship. I need to know this for the entire database. Database diagram will give me the relationship but I don't have permissions to view the diagram. Moreover, I need to look for each set of tables. That's why I am trying to write a query that does the job for me.
In short, if I provide Table A and Table D to the query then query should give me essential columns required (in our case B.id2,C.id3) to join A and D.
SELECT A.*, D.* FROM A Join B on A.id1 = B.id2 Join C on B.id2 = C.id3 Join D on C.id3 = D.id4
Thanks in advance.
I pulled up the one I wrote at work; looks like I didn't actually bother with the CTE (since they're a royal pain in the butt IMHO). It's a little lengthy since it's just code I ripped from a proc. My version originally didn't include the columns, but I added them in. I just concatenate them as though they were an ON clause, but you can tweak that how you like.
use AdventureWorks2014
go
declare
#BaseTable nvarchar(128) = 'SalesPerson',
#BaseTableSchema nvarchar(128) = 'Sales'
declare
#Depth int = 0,
#RowCount int,
#Ident int
declare #KeyHierarchy table
(
Depth int,
ReferencingTableSchema nvarchar(128),
ReferencingTableName nvarchar(128),
ReferencingObjectId int,
ReferencingTableNameFull as quotename(ReferencingTableSchema) + '.' + quotename(ReferencingTableName),
ReferencedTableSchema nvarchar(128),
ReferencedTableName nvarchar(128),
ReferencedObjectId int,
ReferencedTableNameFull as quotename(ReferencedTableSchema) + '.' + quotename(ReferencedTableName),
MatchingColumns nvarchar(max)
primary key clustered (ReferencingTableSchema, ReferencingTableName)
)
insert into #KeyHierarchy
(
Depth,
ReferencingTableSchema,
ReferencingTableName,
ReferencingObjectId
)
select
Depth = #Depth,
ReferencingTableSchema = #BaseTableSchema,
ReferencingTableName = #BaseTable,
ReferencingObjectId = object_id(#BaseTableSchema + '.' + #BaseTable)
select #RowCount = 1
while #RowCount > 0
begin
insert into #KeyHierarchy
(
Depth,
ReferencedTableSchema,
ReferencedTableName,
ReferencedObjectId,
ReferencingTableSchema,
ReferencingTableName,
ReferencingObjectId,
MatchingColumns
)
select distinct
Depth = #Depth + 1,
ReferencedTableSchema = object_schema_name(f.referenced_object_id),
ReferencedTableName = object_name(f.referenced_object_id),
ReferencedObjectId = f.referenced_object_id,
ReferencingTableSchema = object_schema_name(f.parent_object_id),
ReferencingTableName = object_name(f.parent_object_id),
ReferencingObjectId = f.parent_object_id,
MatchingColumns = stuff
(
(
select
concat
(
' and parent.',
quotename(col_name(c.parent_object_id, c.parent_column_id)),
' = ',
'referenced.',
quotename(col_name(c.referenced_object_id, c.referenced_column_id))
)
from sys.foreign_key_columns c
where f.object_id = c.constraint_object_id
order by c.constraint_column_id
for xml path(''), type
).value('.', 'nvarchar(max)'), 1, 4, ''
)
from #KeyHierarchy k
inner join sys.foreign_keys f
on f.referenced_object_id = k.ReferencingObjectId
and f.parent_object_id not in (select ReferencingObjectId from #KeyHierarchy where Depth < #Depth + 1)
where k.Depth = #Depth
select
#RowCount = ##RowCount,
#Depth += 1
end
select
BaseTable = #BaseTable,
ReferencingTableNameFull,
ReferencedTableNameFull,
MatchingColumns,
Depth
from #KeyHierarchy
order by Depth, ReferencingTableNameFull
This has some problems but it is a start
select t.name [t_name], c.name [c_name], f.*
from sys.foreign_keys f
join sys.tables t
on f.parent_object_id = t.object_id
and f.type = 'F'
left join sys.columns c
on c.object_id = f.referenced_object_id
and c.system_type_id = 56
You can fiddle about from this starting point:
with
ForeignKeys as (
-- All foreign keys with their associated tables and columns.
select fk.name as ConstraintName, fk.object_id as ContraintObjectId,
pt.name as ParentTable, pt.object_id as ParentTableObjectId, pc.name as ParentColumn, pc.column_id as ParentColumnId,
ft.name as ForeignTable, ft.object_id as ForeignTableObjectId, fc.name as ForeignColumn, fc.column_id as ForeignColumnId
from sys.foreign_keys as fk inner join
sys.foreign_key_columns as fkc on fkc.constraint_object_id = fk.object_id inner join
sys.tables as pt on pt.object_id = fkc.parent_object_id inner join
sys.columns as pc on pc.object_id = pt.object_id and pc.column_id = fkc.parent_column_id inner join
sys.tables as ft on ft.object_id = fkc.referenced_object_id inner join
sys.columns as fc on fc.object_id = ft.object_id and fc.column_id = fkc.referenced_column_id ),
RelatedTables as (
-- All ordered pairs of directly related tables.
select distinct ParentTable, ParentTableObjectId, ForeignTable, ForeignTableObjectId
from ForeignKeys ),
RelatedTablesHierarchy as (
-- Hierarchy of related tables.
-- Start from each distinct table that has a foreign key relation ...
select ParentTable, ParentTableObjectId, ForeignTable, ForeignTableObjectId,
Cast( ParentTable + '»' + ForeignTable as NVarChar(4000) ) as Path
from RelatedTables
union all
-- ... and add any other table to which the foreign table is related.
select RTH.ParentTable, RTH.ParentTableObjectId, RT.ForeignTable, RT.ForeignTableObjectId,
Cast( Path + '»' + RT.ForeignTable as NVarChar(4000) )
from RelatedTablesHierarchy as RTH inner join
RelatedTables as RT on RT.ParentTableObjectId = RTH.ForeignTableObjectId
-- NB: Avoid getting caught in reference loops.
where '»' + Path + '»' not like '%»' + RT.ForeignTable + '»%'
)
-- Output the results with Path made a little easier to read.
select Replace( Path, '»', ' » ' ) as Path, ParentTable, ParentTableObjectId, ForeignTable, ForeignTableObjectId
from RelatedTablesHierarchy
order by Path;
The initial query is certainly carrying some extra baggage, but you will need it to determine the table and column names necessary for joins. (Tip: Use QuoteName() when assembling object names into statements.)
NB: The common table expression is resistant to reference loops, e.g. tables that have foreign key references to themselves as well as longer loops involving multiple tables.

Create Sql Server view using table name from sysobjects table

I have around 200 tables. I want to create a view from all these tables. I feel it is inefficient to hardcode all the table names and do an UNION ALL in the view definition.
Instead I am planning to retrieve the table name from sysobjects table like
Select name from sysobjects where name like 'Warehouse_Inventory%'
How can I use these table names and create a view out of it?
Note: I am selecting only 10 columns which are common. If any column is not present in a table, I want to display NULL for it.
This Query may help you..
SELECT 'CREATE VIEW VIEW_NAME AS'
UNION ALL
SELECT 'SELECT * FROM ['+NAME+']
UNION ALL' FROM SYS.TABLES where name like 'Warehouse_Inventory%'
I am not sure why you want to use sys.sysojects instead of other sys views. Also now sure why when you want to union all tables you would want to search by a table name..... I would probably recommend a cursor on tables and temp tables to hold your results if you have 200 tables just do to size of the query but if you really really want to do it via union all here is a way...
Build a list of the 10 columns you want. Then run the query. you may need to tweak and add some cast/convert function to ensure everything is the right datatypes this can be done dynamically with sys.types and sys.columns or just make sure everything is a NVARCHAR(???) by altering my dynamic sql below and move forward.
DECLARE #ListOfColumns AS TABLE (ColumnName VARCHAR(100))
INSERT INTO #ListOfColumns (ColumnName) VALUES ('col1'),('col2'),('col3')
DECLARE #SQLStatement NVARCHAR(MAX)
;WITH cteColumnsTableCross AS (
SELECT
SchemaName = s.name
,t.schema_id
,TableName = t.name
,l.ColumnName
FROm
#ListOfColumns l
CROSS JOIN sys.tables t
INNER JOIN sys.schemas s
ON t.schema_id = s.schema_id
)
, cteColumns AS (
SELECT
x.SchemaName
,x.TableName
,x.ColumnName
,ColumnExists = IIF(c.name IS NOT NULL,1,0)
,RowNum = ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY x.TableName DESC)
--you can add data type by getting from sys.columns and sys.types if desired
FROM
cteColumnsTableCross x
LEFT JOIN sys.tables t
ON x.TableName = t.name
AND x.schema_id = t.schema_id
LEFT JOIN sys.columns c
ON t.object_id = c.object_id
AND x.ColumnName = c.name
)
, cteSelectStatements AS (
SELECT
TableName = t.name
,TableSelect = 'SELECT TableName = ''' + t.name + ''', ' +
STUFF(
(SELECT ', ' + c.ColumnName + ' = ' + IIF(c.ColumnExists = 0,'NULL',c.ColumnName)
FROM
cteColumns c
WHERE t.name = c.Tablename
FOR XML PATH(''))
,1,1,'')
+ ' FROM ' + t.name +
IIF((ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY t.name DESC)) > 1,' UNION ALL ','')
FROM
sys.tables t
)
SELECT #SQLStatement = STUFF(
(SELECT ' ' + TableSelect
FROM
cteSelectStatements
ORDER BY
TableName
FOR XML PATH(''))
,1,1,'')
PRINT #SQLStatement
--EXECUTE #SQLStatement

SQL - Query only the first 25 columns in that table

75 columns in a table - I want to query only the first 25 columns in that table without naming each column name.... can you assist with a SQL query....
I been playing with the following:
Select Table_Name, Count(*) As ColumnCount
From Information_Schema.Columns
Group By Table_Name
Order By Table_Name
Doesn't meet my output........
If a Table has 75 columns, How can I see the first 25 columns without naming each column name? Don't want to delete Columns Only want to see the first 25 columns out of 75 columns in the same table.....TOP is not enable need another work around....
First 25 columns in a table query built into #query and then executed. Substitute correct #target_table value.
DECLARE
#target_table sysname
, #query nvarchar(max)
SET
#target_table = '_dimAreaOverlay'
; with of_interest as
(
SELECT
SS.name AS schemaname
, T.name AS tablename
, SC.name AS columname
FROM
sys.schemas SS
inner join
sys.tables T
ON T.schema_id = SS.schema_id
inner join
sys.columns SC
ON SC.object_id = T.object_id
WHERE
T.name = #target_table
AND SC.column_id < 26
)
, c AS
(
SELECT
STUFF((
SELECT
',' + QUOTENAME(I.columname)
FROM
of_interest I
FOR XML PATH('')), 1,1, '') AS column_list
, OI.tablename
, OI.schemaname
FROM
of_interest OI
GROUP BY
OI.schemaname
, OI.tablename
)
SELECT
#query = 'SELECT '
+ C.column_list
+ ' FROM '
+ QUOTENAME(C.schemaname)
+ '.'
+ QUOTENAME(C.tablename)
FROM C
EXECUTE(#query)
Find the table in Management Studio Object Explorer.
Right click it and choose Script Table As -> Select To -> New Query Editor Window
Delete unwanted columns.

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'