Related
I was trying to select top 1 column value from the table to have a glimpse of the data, based on the output
(i.e. equivalently,
SELECT c.name FROM st.Name
This query retrieves column names and their data type along with the tables they're in. I am looking for an additional column that shows top 1 record from the columns.
SELECT
st.name 'Table Name',
c.name 'Column Name',
t.name 'Data Type'
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
LEFT OUTER JOIN sys.tables st ON st.object_id = i.object_id
I have been trying to use a dynamic sql, but as it should put the table name in a single quotation as a string, it couldn't work; when I try to avoid that, it just displays the declared variable.
Any idea is much appreciated. Thanks
So the way this works is basically creates a bunch of selects like:
SELECT 'dbo' AS [Schema Name]
, 'Table1' AS [Table Name]
, 'Id' AS [Column Name]
, 'bigint' AS [Data Type]
, (SELECT TOP 1 CONVERT(NVARCHAR(MAX), Id) FROM [dbo].[Table1]) AS [Top 1 Value]
UNION ALL
-- Another table
Values are converted into NVARCHAR(MAX) because column type in an union has to match and I guess that's the best bet.
Here goes:
DECLARE #query NVARCHAR(MAX) = ''
SELECT #Query +=
'SELECT ' + '''' + sch.name + '''' + ' AS [Schema Name],' + CHAR(13)+CHAR(10)
+ '''' + st.name + '''' + ' AS [Table Name],' + CHAR(13)+CHAR(10)
+ '''' + c.name + '''' + ' AS [Column Name],' + CHAR(13)+CHAR(10)
+ '''' + t.name + '''' + ' AS [Data Type],' + CHAR(13)+CHAR(10)
+ '(SELECT TOP 1 CONVERT(NVARCHAR(MAX), ' + c.name + ') FROM ' + QUOTENAME(sch.name) + '.' + QUOTENAME(st.name) + ') AS [Top 1 Value] ' + CHAR(13)+CHAR(10)
+ 'UNION ALL'+CHAR(13)+CHAR(10)
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.tables st ON st.object_id = i.object_id
JOIN sys.schemas sch ON sch.schema_id = st.schema_id
-- Get rid of trailing UNION ALL
SET #Query = LEFT(#Query, LEN(#Query) - LEN('UNION ALLxx'))
PRINT #query
EXEC sp_executesql #query
Consider running with TOP 10 or some such first to make sure it's producing the right results.
you could use a while loop with d sql
-
--drop table #temp
SELECT
CONCAT(s.name,'.',st.name) 'Table Name',
c.name 'Column Name',
t.name 'Data Type',
CAST(null AS datetime) as IND,
cast('' AS varchar(max)) data
INTO #temp
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN sys.tables st ON st.object_id = i.object_id
INNER JOIN sys.schemas s ON s.schema_id = st.schema_id
declare
#TableName varchar(255),
#ColumnName Varchar(255),
#sql varchar(max)
WHILE (SELECT count(*) FROM #temp where IND is null) > 0
begin
SELECT TOP 1
#TableName = [Table Name]
,#ColumnName = [Column Name]
FROM #temp
WHERE IND IS NULL
SET #sql =
'update #temp
set data = (SELECT top 1 [' + #ColumnName + '] from ' + #TableName + '),
IND = getdate()
where [Table Name] = ''' + #TableName + ''' and [Column Name] = ''' + #ColumnName + ''''
exec(#sql)
end
SELECT *
FROM #temp
I have successfully getting the information of tables and columns from below query.
Is there any handy way to get the type name with the description like nvarchar(20), numeric(14,2), varchar(max) etc. instead of lot's of CASE statements?
SELECT
o.name AS TableName,
c.name AS ColumnName,
t.name +
CASE
WHEN t.name LIKE '%char' THEN '(' +
CASE
WHEN c.max_length = -1 THEN 'max'
ELSE CONVERT(varchar(10), c.max_length / CASE WHEN t.name LIKE 'n%' THEN 2 ELSE 1 END)
END + ')'
WHEN t.name IN ('numeric', 'decimal') THEN '(' + CONVERT(varchar(4), c.precision) + ',' + CONVERT(varchar(4), c.scale) + ')'
-- WHEN .... many other types
ELSE ''
END AS TypeName
FROM
sys.objects o
INNER JOIN sys.columns c ON o.object_id = c.object_id
INNER JOIN sys.types t ON t.system_type_id = c.system_type_id AND t.user_type_id = c.user_type_id
WHERE
o.is_ms_shipped = 0
ORDER BY
o.name,
c.column_id
Edit
sp_help nor the information schema return the name not being like nvarchar(20), numeric(14,2), varchar(max)
I use this view to Document the Database.... you could used this and use the data_type and Length/Precision
/****** Object: View [dbo].[vw_DataDictionary] Script Date: 17/07/2015 10:24:04 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER VIEW [dbo].[vw_DataDictionary]
AS
SELECT TOP (100) PERCENT tb.name AS Table_Name, CAST(ept.value AS nvarchar(200)) AS Table_Description, CAST(c.name AS nvarchar(200)) AS Column_Name,
CAST(ep.value AS nvarchar(200)) AS column_Description, t.name AS data_type, c.is_nullable AS Is_Null, object_definition(c.default_object_id) AS default_text,
c.max_length AS Length, c.precision AS numeric_precision, c.scale AS numeric_scale, c.column_id
FROM sys.columns AS c LEFT OUTER JOIN
sys.tables AS tb ON tb.object_id = c.object_id LEFT OUTER JOIN
sys.types AS t ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id LEFT OUTER JOIN
sys.extended_properties AS ept ON ept.major_id = tb.object_id AND ept.minor_id = 0 AND ept.name = 'MS_Description' LEFT OUTER JOIN
sys.extended_properties AS ep ON ep.major_id = c.object_id AND ep.minor_id = c.column_id AND ep.name = 'MS_Description'
WHERE (tb.type = 'U') AND (tb.name <> 'sysdiagrams')
ORDER BY Table_Name, c.column_id
GO
For SQL Server 2008 R2, I have declared the type by CASE as below:
SQL Fiddle
SELECT
DB_NAME() AS DatabaseName,
SCHEMA_NAME(o.schema_id) AS SchemaName,
o.name AS ObjectName,
c.name AS ColumnName,
RTRIM(o.type) AS ObjectType,
t.name AS TypeName,
c.max_length AS Length,
-- The logic is implemented in this column
t.name +
CASE
-- (max) for char type / binary only
WHEN (t.name LIKE '%char%' OR t.name LIKE '%binary') AND c.max_length = -1 THEN '(max)'
-- (n) where n = length / 2 for nchar and nvarchar
WHEN t.name LIKE '%char%' AND LEFT(t.name, 1) = 'n' THEN '(' + CONVERT(varchar, c.max_length / 2) + ')'
-- (n) where n = length
WHEN t.name LIKE '%char%' OR t.name LIKE '%binary' THEN '(' + CONVERT(varchar, c.max_length) + ')'
-- (p,s) where p = precision, s = scale
WHEN t.name IN ('numeric', 'decimal') THEN '(' + CONVERT(varchar, c.precision) + ',' + CONVERT(varchar, c.scale) + ')'
-- (s) where s = scale
WHEN t.name IN ('time', 'datetime2', 'datetimeoffset') THEN '(' + CONVERT(varchar, c.scale) + ')'
ELSE ''
END AS Type
FROM
sys.objects o
inner join sys.columns c on o.object_id = c.object_id
inner join sys.types t on c.system_type_id = t.system_type_id and c.user_type_id = t.user_type_id
WHERE 1 = 1
AND o.is_ms_shipped = 1
This should help you, Adopted from here
DECLARE #tblname VARCHAR(300)
SET #tblname = 'tblname'
SELECT o.list AS ColumnsDescription
FROM sysobjects so
CROSS APPLY (
SELECT ' [' + column_name + '] ' + data_type + CASE data_type
WHEN 'sql_variant'
THEN ''
WHEN 'text'
THEN ''
WHEN 'ntext'
THEN ''
WHEN 'xml'
THEN ''
WHEN 'decimal'
THEN '(' + cast(numeric_precision AS VARCHAR) + ', ' + cast(numeric_scale AS VARCHAR) + ')'
ELSE coalesce('(' + CASE
WHEN character_maximum_length = - 1
THEN 'MAX'
ELSE cast(character_maximum_length AS VARCHAR)
END + ')', '')
END + ' ' + CASE
WHEN EXISTS (
SELECT id
FROM syscolumns
WHERE object_name(id) = so.NAME
AND NAME = column_name
AND columnproperty(id, NAME, 'IsIdentity') = 1
)
THEN 'IDENTITY(' + cast(ident_seed(so.NAME) AS VARCHAR) + ',' + cast(ident_incr(so.NAME) AS VARCHAR) + ')'
ELSE ''
END + ' ' + (
CASE
WHEN IS_NULLABLE = 'No'
THEN 'NOT '
ELSE ''
END
) + 'NULL ' + CASE
WHEN information_schema.columns.COLUMN_DEFAULT IS NOT NULL
THEN 'DEFAULT ' + information_schema.columns.COLUMN_DEFAULT
ELSE ''
END + ', '
FROM information_schema.columns
WHERE table_name = so.NAME
ORDER BY ordinal_position
FOR XML PATH('')
) o(list)
LEFT JOIN information_schema.table_constraints tc ON tc.Table_name = so.NAME
AND tc.Constraint_Type = 'PRIMARY KEY'
CROSS APPLY (
SELECT '[' + Column_Name + '], '
FROM information_schema.key_column_usage kcu
WHERE kcu.Constraint_Name = tc.Constraint_Name
ORDER BY ORDINAL_POSITION
FOR XML PATH('')
) j(list)
WHERE xtype = 'U'
AND NAME = #tblname
You can parse your results as you want.
SELECT
COLUMN_NAME,
CASE
WHEN DATA_TYPE ='decimal' THEN DATA_TYPE+ '('+cast (NUMERIC_PRECISION as Varchar)+ ','+cast (NUMERIC_SCALE as Varchar)+ ')'
WHEN CHARACTER_MAXIMUM_LENGTH is null THEN DATA_TYPE + cast ('' as Varchar)
ELSE DATA_TYPE + '('+ cast (CHARACTER_MAXIMUM_LENGTH as Varchar)+')' END AS QuantityText
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'table_name' and TABLE_SCHEMA = 'dbo'
order by COLUMN_NAME
I have the following code which is supposed to display the column name, data type, size, # of filled columns and the total rows.
The problem that I am running into is that using INFORMATION_SCHEMA.columns I can only display either DATA_TYPE or CHARACTER_MAXIMUM_LENGTH. If I try to SELECT both I get errors:
An expression of non-boolean type specified in a context where a condition is expected, near 'si'.
The code statement is:
DECLARE #TableName VARCHAR(512) = 'state';
DECLARE #SQL VARCHAR(1024);
WITH SQLText AS (
SELECT
ROW_NUMBER() OVER (ORDER BY c.Name) AS RowNum,
'SELECT ''' + c.name + ''',
MAX(b.DATA_TYPE) AS ''Data Type'',
SUM(CASE WHEN ' + c.Name + ' IS NULL THEN 0 ELSE 1 END) AS ''Filled Values'',
COUNT(*) AS ''Total Records''
FROM INFORMATION_SCHEMA.columns b
JOIN ' + #TableName + ' ON b.column_name = ''' + c.name +'''' AS SQLRow
FROM
sys.tables t
INNER JOIN sys.columns c ON c.object_id = t.object_id
JOIN sys.types a ON c.user_type_id = a.user_type_id
WHERE
t.name = #TableName)
Any ideas on how to get both to display?
DECLARE #TableName VARCHAR(512) = 'Settings';
DECLARE #SQL VARCHAR(1024);
WITH SQLText AS (
SELECT
ROW_NUMBER() OVER (ORDER BY c.Name) AS RowNum,
'SELECT ''' + c.name + ''',
MAX(b.DATA_TYPE) AS ''Data Type'',
Max(b.CHARACTER_MAXIMUM_LENGTH) as ''CHARACTER_MAXIMUM_LENGTH'',
SUM(CASE WHEN ' + c.Name + ' IS NULL THEN 0 ELSE 1 END) AS ''Filled Values'',
COUNT(*) AS ''Total Records''
FROM INFORMATION_SCHEMA.columns b
JOIN ' + #TableName + ' ON b.column_name = ''' + c.name +'''' AS SQLRow
FROM
sys.tables t
INNER JOIN sys.columns c ON c.object_id = t.object_id
JOIN sys.types a ON c.user_type_id = a.user_type_id
WHERE
t.name = #TableName)
select * from SQLText
This works for me, tbh though i'd add to get a better idea of the size a column uses.
SUM(CASE WHEN ' + c.Name + ' IS NULL THEN 0 ELSE Datalength(' + c.Name + ') END) AS ''Filled Values'',
I have to do checks between a development and release database and do this manually, which is both slow and not 100% reliable (I only visually inspect the tables).
Is there a quick and easy way to compare table schemas automatically? Maybe even a feature that does this built right into SQL server?
Edit: I'm comparing structure only, thank you for pointing this out.
I'm a fan of SQL DBDiff, which is an open source tool you can use to compare tables, views, functions, users, etc. of two instances of SQL Server databases and generate a change script between the source and destination databases.
There are some commercial products that do this; Visual Studio 2010 Premium Edition can compare schemas.
Some others:
http://www.red-gate.com/products/SQL_Compare/index.htm
http://www.apexsql.com/sql_tools_diff.aspx
Data or structure or both? Try RedGate sql compare or data compare. They both have free trials and are awesome.
http://www.red-gate.com/products/SQL_Compare/index.htm
http://www.red-gate.com/products/SQL_Data_Compare/index.htm
I'm a little late to the game...but this script I made has worked well for me. It'll work across linked servers too if needed.
use master
go
DECLARE #Server1 VARCHAR(100) ='[CARNYSQLTEST1].'; --include a dot at the end
DECLARE #DB1 VARCHAR(100) = '[ZipCrim]';
DECLARE #Table1 VARCHAR(100) = 'IntAction';
DECLARE #Server2 VARCHAR(100) ='[CARNYSQLDEV].'; --include a dot at the end
DECLARE #DB2 VARCHAR(100) = '[ZipCrim]';
DECLARE #Table2 VARCHAR(100) = 'IntAction';
DECLARE #SQL NVARCHAR(MAX);
SET #SQL =
'
SELECT Table1.ServerName,
Table1.DBName,
Table1.SchemaName,
Table1.TableName,
Table1.ColumnName,
Table1.name DataType,
Table1.Length,
Table1.Precision,
Table1.Scale,
Table1.Is_Identity,
Table1.Is_Nullable,
Table2.ServerName,
Table2.DBName,
Table2.SchemaName,
Table2.TableName,
Table2.ColumnName,
Table2.name DataType,
Table2.Length,
Table2.Precision,
Table2.Scale,
Table2.Is_Identity,
Table2.Is_Nullable
FROM
(SELECT ''' + #Server1 + ''' ServerName,
''' + #DB1 + ''' DbName,
SCHEMA_NAME(t.schema_id) SchemaName,
t.Name TableName,
c.Name ColumnName,
st.Name,
c.Max_Length Length,
c.Precision,
c.Scale,
c.Is_Identity,
c.Is_Nullable
FROM ' + #Server1 + #DB1 + '.sys.tables t
INNER JOIN ' + #Server1 + #DB1 + '.sys.columns c ON t.Object_ID = c.Object_ID
INNER JOIN sys.types st ON St.system_type_id = c.System_Type_id AND st.user_type_id = c.user_type_id
WHERE t.Name = ''' + #Table1 + ''') Table1
FULL OUTER JOIN
(SELECT ''' + #Server2 + ''' ServerName,
''' + #DB2 + ''' DbName,
SCHEMA_NAME(t.schema_id) SchemaName,
t.name TableName,
c.name ColumnName,
st.Name,
c.max_length Length,
c.Precision,
c.Scale,
c.Is_Identity,
c.Is_Nullable
FROM ' + #Server2 + #DB2 + '.sys.tables t
INNER JOIN ' + #Server2 + #DB2 + '.sys.columns c ON t.Object_ID = c.Object_ID
INNER JOIN sys.types st ON St.system_type_id = c.System_Type_id AND st.user_type_id = c.user_type_id
WHERE t.Name = ''' + #Table2 + ''') Table2
ON Table1.ColumnName = Table2.ColumnName
ORDER BY CASE WHEN Table1.ColumnName IS NULL THEN 2 ELSE 1 END, Table1.ColumnName
'
EXEC sp_executesql #SQL
Soo,
Googled this:
for structures:
see also:
My previous answers' links doesn't work anymore for some reason, so here's another answer from TechNet:
DECLARE #Sourcedb sysname
DECLARE #Destdb sysname
DECLARE #Tablename sysname
DECLARE #SQL varchar(max)
SELECT #Sourcedb = '<<SourceDatabaseName>>'
SELECT #Destdb = '<<DestinationDatabaseName>>'
SELECT #Tablename = '<<Tablename>>' -- '%' for all tables
SELECT #SQL = ' SELECT Tablename = ISNULL(Source.tablename,Destination.tablename)
,ColumnName = ISNULL(Source.Columnname,Destination.Columnname)
,Source.Datatype
,Source.Length
,Source.precision
,Destination.Datatype
,Destination.Length
,Destination.precision
,[Column] =
Case
When Source.Columnname IS NULL then ''Column Missing in the Source''
When Destination.Columnname IS NULL then ''Column Missing in the Destination''
ELSE ''''
end
,DataType = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND Source.Datatype <> Destination.Datatype THEN ''Data Type mismatch''
END
,Length = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND Source.Length <> Destination.Length THEN ''Length mismatch''
END
,Precision = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND Source.precision <> Destination.precision THEN ''precision mismatch''
END
,Collation = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND ISNULL(Source.collation_name,'''') <> ISNULL(Destination.collation_name,'''') THEN ''Collation mismatch''
END
FROM
(
SELECT Tablename = so.name
, Columnname = sc.name
, DataType = St.name
, Length = Sc.max_length
, precision = Sc.precision
, collation_name = Sc.collation_name
FROM ' + #Sourcedb + '.SYS.objects So
JOIN ' + #Sourcedb + '.SYS.columns Sc
ON So.object_id = Sc.object_id
JOIN ' + #Sourcedb + '.SYS.types St
ON Sc.system_type_id = St.system_type_id
AND Sc.user_type_id = St.user_type_id
WHERE SO.TYPE =''U''
AND SO.Name like ''' + #Tablename + '''
) Source
FULL OUTER JOIN
(
SELECT Tablename = so.name
, Columnname = sc.name
, DataType = St.name
, Length = Sc.max_length
, precision = Sc.precision
, collation_name = Sc.collation_name
FROM ' + #Destdb + '.SYS.objects So
JOIN ' + #Destdb + '.SYS.columns Sc
ON So.object_id = Sc.object_id
JOIN ' + #Destdb + '.SYS.types St
ON Sc.system_type_id = St.system_type_id
AND Sc.user_type_id = St.user_type_id
WHERE SO.TYPE =''U''
AND SO.Name like ''' + #Tablename + '''
) Destination
ON source.tablename = Destination.Tablename
AND source.Columnname = Destination.Columnname '
EXEC (#Sql)
For a free solution, you can use SQL Server Managements Objects to output the DDL script for each table, view, index, SP, UDF, etc. Then you can compare, either in code, or using a diff tool like WinMerge.
If two tables in same database, you can use this query
select c2.table_name,c2.COLUMN_NAME
from [INFORMATION_SCHEMA].[COLUMNS] c2
where table_name='table1'
and c2.COLUMN_NAME not in (select column_name
from [INFORMATION_SCHEMA].[COLUMNS]
where table_name='table1')
you can take a look at http://cdttools.com/2011/10/sql-diff-erence/ its a low cost alternative, will walk schema between two databases and tell you whats changed. You can then use SQL Mgmt studio to generate "script->As Alter" to build change scripts. (caveat: I wrote it)
Modified a bit of BD.'s query, all credit goes to him. (Changed SCHEMA_NAME(schema_id) to sys.schemas join because SCHEMA_NAME(schema_id) works with current db context which is master, changed sorting and changed column names and added the status column)
USE master
GO
DECLARE
#Server1 VARCHAR(100) = 'Server1.', -- don't forget to include a dot at the end
#Server2 VARCHAR(100) = 'Server2.', -- don't forget to include a dot at the end
#DB1 VARCHAR(100) = 'Database1',
#DB2 VARCHAR(100) = 'Database2'
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = '
SELECT
CASE
WHEN s1.[Column] IS NOT NULL
AND s2.[Column] IS NULL
THEN ''New''
WHEN s1.[Column] IS NULL
AND s2.[Column] IS NOT NULL
THEN ''Deleted''
WHEN s1.[Column] IS NOT NULL
AND s2.[Column] IS NOT NULL
AND (s1.[Type] <> s2.[Type]
OR s1.[Length] <> s2.[Length]
OR s1.[Precision] <> s2.[Precision]
OR s1.Scale <> s2.Scale
OR s1.IsNullable <> s2.IsNullable
OR s1.IsIdentity <> s2.IsIdentity
OR s1.IdentitySeed <> s2.IdentitySeed
OR s1.IdentityIncrement <> s2.IdentityIncrement
OR s1.DefaultValue <> s2.DefaultValue)
THEN ''Changed''
ELSE ''Identical''
END [Status],
s1.[Database],
s1.[Schema],
s1.[Table],
s1.[Column],
s1.[Type],
s1.IsCharType,
s1.[Length],
s1.[Precision],
s1.Scale,
s1.IsNullable,
s1.IsIdentity,
s1.IdentitySeed,
s1.IdentityIncrement,
s1.DefaultValue,
s1.[Order],
s2.[Database],
s2.[Schema],
s2.[Table],
s2.[Column],
s2.[Type],
s2.IsCharType,
s2.[Length],
s2.[Precision],
s2.Scale,
s2.IsNullable,
s2.IsIdentity,
s2.IdentitySeed,
s2.IdentityIncrement,
s2.DefaultValue,
s2.[Order]
FROM (
SELECT
''' + #DB1 + ''' AS [Database],
s.name AS [Schema],
t.name AS [Table],
c.name AS [Column],
tp.name AS [Type],
CASE
WHEN tp.collation_name IS NOT NULL
THEN 1
ELSE 0
END AS IsCharType,
CASE
WHEN c.max_length = -1
THEN ''MAX''
ELSE CAST(c.max_length AS VARCHAR(4))
END AS [Length],
c.[precision],
c.scale,
c.is_nullable AS IsNullable,
c.is_identity AS IsIdentity,
CAST(ISNULL(ic.seed_value, 0) AS INT) AS IdentitySeed,
CAST(ISNULL(ic.increment_value, 0) AS INT) AS IdentityIncrement,
dc.definition AS DefaultValue,
c.column_id AS [Order]
FROM ' + #Server1 + #DB1 + '.sys.tables t
INNER JOIN ' + #Server1 + #DB1 + '.sys.schemas s ON s.schema_id = t.schema_id
INNER JOIN ' + #Server1 + #DB1 + '.sys.columns c ON c.object_id = t.object_id
INNER JOIN ' + #Server1 + #DB1 + '.sys.types tp ON tp.system_type_id = c.system_type_id
LEFT OUTER JOIN ' + #Server1 + #DB1 + '.sys.identity_columns ic ON ic.object_id = t.object_id AND ic.name = c.name
LEFT OUTER JOIN ' + #Server1 + #DB1 + '.sys.default_constraints dc ON dc.object_id = c.default_object_id
) s1
FULL OUTER JOIN (
SELECT
''' + #DB2 + ''' AS [Database],
s.name AS [Schema],
t.name AS [Table],
c.name AS [Column],
tp.name AS [Type],
CASE
WHEN tp.collation_name IS NOT NULL
THEN 1
ELSE 0
END AS IsCharType,
CASE
WHEN c.max_length = -1
THEN ''MAX''
ELSE CAST(c.max_length AS VARCHAR(4))
END AS [Length],
c.[precision],
c.scale,
c.is_nullable AS IsNullable,
c.is_identity AS IsIdentity,
CAST(ISNULL(ic.seed_value, 0) AS INT) AS IdentitySeed,
CAST(ISNULL(ic.increment_value, 0) AS INT) AS IdentityIncrement,
dc.definition AS DefaultValue,
c.column_id AS [Order]
FROM ' + #Server2 + #DB2 + '.sys.tables t
INNER JOIN ' + #Server2 + #DB2 + '.sys.schemas s ON s.schema_id = t.schema_id
INNER JOIN ' + #Server2 + #DB2 + '.sys.columns c ON c.object_id = t.object_id
INNER JOIN ' + #Server2 + #DB2 + '.sys.types tp ON tp.system_type_id = c.system_type_id
LEFT OUTER JOIN ' + #Server2 + #DB2 + '.sys.identity_columns ic ON ic.object_id = t.object_id AND ic.name = c.name
LEFT OUTER JOIN ' + #Server2 + #DB2 + '.sys.default_constraints dc ON dc.object_id = c.default_object_id
) s2
ON s2.[Schema] = s1.[Schema]
AND s2.[Table] = s1.[Table]
AND s2.[Column] = s1.[Column]
ORDER BY
CASE WHEN s1.[Database] IS NULL THEN s2.[Database] ELSE s1.[Database] END,
CASE WHEN s1.[Schema] IS NULL THEN s2.[Schema] ELSE s1.[Schema] END,
CASE WHEN s1.[Table] IS NULL THEN s2.[Table] ELSE s1.[Table] END,
CASE WHEN s1.[Order] IS NULL THEN s2.[Order] ELSE s1.[Order] END
'
EXEC sp_executesql #SQL
You can use the SQL Management studio tools to "Generate scripts" from both databases. Then use your favorite text comparison tool to see any differences.
In the old days, this worked great, but in SQL 2005 the generate script code changed and the objects were no longer created in the same order, so the text comparison is less useful. I have not tested this in more recent versions of SQL so it may have been fixed. You can also try http://exportsqlscript.codeplex.com/ which I have used with good success to output the DDL as scripts for source code control and comparing versions.
References:
https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=332400&wa=wsignin1.0
http://social.msdn.microsoft.com/Forums/en-US/sqltools/thread/505fd238-e0dc-42ae-8a54-2dceace81bb3/
http://exportsqlscript.codeplex.com/
I have a SQL Server database and I want to know what columns and types it has. I'd prefer to do this through a query rather than using a GUI like Enterprise Manager. Is there a way to do this?
You can use the sp_columns stored procedure:
exec sp_columns MyTable
There are a few methods to get metadata about a table:
EXEC sp_help tablename
Will return several result sets, describing the table, it's columns and constraints.
The INFORMATION_SCHEMA views will give you the information you want, though unfortunately you have to query the views and join them manually.
Just in case you don't want to use stored proc, here's a simple query version
select *
from information_schema.columns
where table_name = 'aspnet_Membership'
order by ordinal_position
You can use following: sp_help tablename
Example: sp_help Customer
OR Use Shortcut Keys
Select the desired table and press ALT+F1.
Example: Customer Press ALT+F1.
Use this Query
Select * From INFORMATION_SCHEMA.COLUMNS Where TABLE_NAME = 'TABLENAME'
In addition to the ways shown in other answers, you can use
SELECT TOP 0 * FROM table_name
This will give you the name of each column with no results in them, and completes almost instantly with minimal overhead.
Please use the following sql query; this worked for my case.
select * FROM INFORMATION_SCHEMA.Columns where table_name = 'tablename';
Just select table and press Alt+F1,
it will show all the information about table like Column name, datatype, keys etc.
The SQL Server equivalent to Oracle's describe command is the stored proc sp_help
The describe command gives you the information about the column names, types, length, etc.
In SQL Server, let's say you want to describe a table 'mytable' in schema 'myschema' in the database 'mydb', you can do following:
USE mydb;
exec sp_help 'myschema.mytable';
I wrote an sql*plus DESC(RIBE) like select (displays the column comments, too) in t-sql:
USE YourDB
GO
DECLARE #objectName NVARCHAR(128) = 'YourTable';
SELECT
a.[NAME]
,a.[TYPE]
,a.[CHARSET]
,a.[COLLATION]
,a.[NULLABLE]
,a.[DEFAULT]
,b.[COMMENTS]
-- ,a.[ORDINAL_POSITION]
FROM
(
SELECT
COLUMN_NAME AS [NAME]
,CASE DATA_TYPE
WHEN 'char' THEN DATA_TYPE + '(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + ')'
WHEN 'numeric' THEN DATA_TYPE + '(' + CAST(NUMERIC_PRECISION AS VARCHAR) + ', ' + CAST(NUMERIC_SCALE AS VARCHAR) + ')'
WHEN 'nvarchar' THEN DATA_TYPE + '(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + ')'
WHEN 'varbinary' THEN DATA_TYPE + '(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + ')'
WHEN 'varchar' THEN DATA_TYPE + '(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + ')'
ELSE DATA_TYPE
END AS [TYPE]
,CHARACTER_SET_NAME AS [CHARSET]
,COLLATION_NAME AS [COLLATION]
,IS_NULLABLE AS [NULLABLE]
,COLUMN_DEFAULT AS [DEFAULT]
,ORDINAL_POSITION
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = #objectName
) a
FULL JOIN
(
SELECT
CAST(value AS NVARCHAR) AS [COMMENTS]
,CAST(objname AS NVARCHAR) AS [NAME]
FROM
::fn_listextendedproperty ('MS_Description', 'user', 'dbo', 'table', #objectName, 'column', default)
) b
ON a.NAME COLLATE YourCollation = b.NAME COLLATE YourCollation
ORDER BY
a.[ORDINAL_POSITION];
The above mentioned select can be used in a system marked stored procedure and it can be called from any database of your instance on a simple way:
USE master;
GO
IF OBJECT_ID('sp_desc', 'P') IS NOT NULL
DROP PROCEDURE sp_desc
GO
CREATE PROCEDURE sp_desc (
#tableName nvarchar(128)
) AS
BEGIN
DECLARE #dbName sysname;
DECLARE #schemaName sysname;
DECLARE #objectName sysname;
DECLARE #objectID int;
DECLARE #tmpTableName varchar(100);
DECLARE #sqlCmd nvarchar(4000);
SELECT #dbName = PARSENAME(#tableName, 3);
IF #dbName IS NULL SELECT #dbName = DB_NAME();
SELECT #schemaName = PARSENAME(#tableName, 2);
IF #schemaName IS NULL SELECT #schemaName = SCHEMA_NAME();
SELECT #objectName = PARSENAME(#tableName, 1);
IF #objectName IS NULL
BEGIN
PRINT 'Object is missing from your function call!';
RETURN;
END;
SELECT #objectID = OBJECT_ID(#dbName + '.' + #schemaName + '.' + #objectName);
IF #objectID IS NULL
BEGIN
PRINT 'Object [' + #dbName + '].[' + #schemaName + '].[' + #objectName + '] does not exist!';
RETURN;
END;
SELECT #tmpTableName = '#tmp_DESC_' + CAST(##SPID AS VARCHAR) + REPLACE(REPLACE(REPLACE(REPLACE(CAST(CONVERT(CHAR, GETDATE(), 121) AS VARCHAR), '-', ''), ' ', ''), ':', ''), '.', '');
--PRINT #tmpTableName;
SET #sqlCmd = '
USE ' + #dbName + '
CREATE TABLE ' + #tmpTableName + ' (
[NAME] nvarchar(128) NOT NULL
,[TYPE] varchar(50)
,[CHARSET] varchar(50)
,[COLLATION] varchar(50)
,[NULLABLE] varchar(3)
,[DEFAULT] nvarchar(4000)
,[COMMENTS] nvarchar(3750));
INSERT INTO ' + #tmpTableName + '
SELECT
a.[NAME]
,a.[TYPE]
,a.[CHARSET]
,a.[COLLATION]
,a.[NULLABLE]
,a.[DEFAULT]
,b.[COMMENTS]
FROM
(
SELECT
COLUMN_NAME AS [NAME]
,CASE DATA_TYPE
WHEN ''char'' THEN DATA_TYPE + ''('' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + '')''
WHEN ''numeric'' THEN DATA_TYPE + ''('' + CAST(NUMERIC_PRECISION AS VARCHAR) + '', '' + CAST(NUMERIC_SCALE AS VARCHAR) + '')''
WHEN ''nvarchar'' THEN DATA_TYPE + ''('' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + '')''
WHEN ''varbinary'' THEN DATA_TYPE + ''('' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + '')''
WHEN ''varchar'' THEN DATA_TYPE + ''('' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + '')''
ELSE DATA_TYPE
END AS [TYPE]
,CHARACTER_SET_NAME AS [CHARSET]
,COLLATION_NAME AS [COLLATION]
,IS_NULLABLE AS [NULLABLE]
,COLUMN_DEFAULT AS [DEFAULT]
,ORDINAL_POSITION
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = ''' + #objectName + '''
) a
FULL JOIN
(
SELECT
CAST(value AS NVARCHAR) AS [COMMENTS]
,CAST(objname AS NVARCHAR) AS [NAME]
FROM
::fn_listextendedproperty (''MS_Description'', ''user'', ''' + #schemaName + ''', ''table'', ''' + #objectName + ''', ''column'', default)
) b
ON a.NAME COLLATE Hungarian_CI_AS = b.NAME COLLATE Hungarian_CI_AS
ORDER BY
a.[ORDINAL_POSITION];
SELECT * FROM ' + #tmpTableName + ';'
--PRINT #sqlCmd;
EXEC sp_executesql #sqlCmd;
RETURN;
END;
GO
EXEC sys.sp_MS_marksystemobject sp_desc
GO
To execute the procedure type:
EXEC sp_desc 'YourDB.YourSchema.YourTable';
If you want to get a description an object of the current database (and schema) simple type:
EXEC sp_desc 'YourTable';
As sp_desc is a system marked procedure, you can even leave the exec command, too (not recommended anyway):
sp_desc 'YourTable';
You can use the sp_help 'TableName'
try it:
EXEC [ServerName].[DatabaseName].dbo.sp_columns 'TableName'
and you can get some table structure information, such as:
TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE, TYPE_NAME...
In addition to above questions, if we have table in DB like db_name.dbo.table_name, we may use following steps
Connect with DB
USE db_name;
Use EXEC sp_help and don't forget to put table name as 'dbo.tablename' if you have dbo as schema.
exec sp_help 'dbo.table_name'
This should work!
I tried this and it's working for me
exec sp_help TABLE_NAME
First connect to your DB,
use DB_name
Then
exec sp_help 'Production.Et_Issue'
here 'production' is the schema name. If you dont have a schema,
you may simply write sp_help table_name
The problem with those answers is that you're missing the key info.
While this is a bit messy this is a quick version I came up with to make sure it contains the same info the MySQL Describe displays.
Select SC.name AS 'Field', ISC.DATA_TYPE AS 'Type', ISC.CHARACTER_MAXIMUM_LENGTH AS 'Length', SC.IS_NULLABLE AS 'Null', I.is_primary_key AS 'Key', SC.is_identity AS 'Identity'
From sys.columns AS SC
LEFT JOIN sys.index_columns AS IC
ON IC.object_id = OBJECT_ID('dbo.Expenses') AND
IC.column_id = SC.column_id
LEFT JOIN sys.indexes AS I
ON I.object_id = OBJECT_ID('dbo.Expenses') AND
IC.index_id = I.index_id
LEFT JOIN information_schema.columns ISC
ON ISC.TABLE_NAME = 'Expenses'
AND ISC.COLUMN_NAME = SC.name
WHERE SC.object_id = OBJECT_ID('dbo.Expenses')
This is the code I use within the EntityFramework Reverse POCO Generator (available here)
Table SQL:
SELECT c.TABLE_SCHEMA AS SchemaName,
c.TABLE_NAME AS TableName,
t.TABLE_TYPE AS TableType,
c.ORDINAL_POSITION AS Ordinal,
c.COLUMN_NAME AS ColumnName,
CAST(CASE WHEN IS_NULLABLE = 'YES' THEN 1
ELSE 0
END AS BIT) AS IsNullable,
DATA_TYPE AS TypeName,
ISNULL(CHARACTER_MAXIMUM_LENGTH, 0) AS [MaxLength],
CAST(ISNULL(NUMERIC_PRECISION, 0) AS INT) AS [Precision],
ISNULL(COLUMN_DEFAULT, '') AS [Default],
CAST(ISNULL(DATETIME_PRECISION, 0) AS INT) AS DateTimePrecision,
ISNULL(NUMERIC_SCALE, 0) AS Scale,
CAST(COLUMNPROPERTY(OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME)), c.COLUMN_NAME, 'IsIdentity') AS BIT) AS IsIdentity,
CAST(CASE WHEN COLUMNPROPERTY(OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME)), c.COLUMN_NAME, 'IsIdentity') = 1 THEN 1
WHEN COLUMNPROPERTY(OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME)), c.COLUMN_NAME, 'IsComputed') = 1 THEN 1
WHEN DATA_TYPE = 'TIMESTAMP' THEN 1
ELSE 0
END AS BIT) AS IsStoreGenerated,
CAST(CASE WHEN pk.ORDINAL_POSITION IS NULL THEN 0
ELSE 1
END AS BIT) AS PrimaryKey,
ISNULL(pk.ORDINAL_POSITION, 0) PrimaryKeyOrdinal,
CAST(CASE WHEN fk.COLUMN_NAME IS NULL THEN 0
ELSE 1
END AS BIT) AS IsForeignKey
FROM INFORMATION_SCHEMA.COLUMNS c
LEFT OUTER JOIN (SELECT u.TABLE_SCHEMA,
u.TABLE_NAME,
u.COLUMN_NAME,
u.ORDINAL_POSITION
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE u
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
ON u.TABLE_SCHEMA = tc.CONSTRAINT_SCHEMA
AND u.TABLE_NAME = tc.TABLE_NAME
AND u.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY') pk
ON c.TABLE_SCHEMA = pk.TABLE_SCHEMA
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.COLUMN_NAME = pk.COLUMN_NAME
LEFT OUTER JOIN (SELECT DISTINCT
u.TABLE_SCHEMA,
u.TABLE_NAME,
u.COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE u
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
ON u.TABLE_SCHEMA = tc.CONSTRAINT_SCHEMA
AND u.TABLE_NAME = tc.TABLE_NAME
AND u.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY') fk
ON c.TABLE_SCHEMA = fk.TABLE_SCHEMA
AND c.TABLE_NAME = fk.TABLE_NAME
AND c.COLUMN_NAME = fk.COLUMN_NAME
INNER JOIN INFORMATION_SCHEMA.TABLES t
ON c.TABLE_SCHEMA = t.TABLE_SCHEMA
AND c.TABLE_NAME = t.TABLE_NAME
WHERE c.TABLE_NAME NOT IN ('EdmMetadata', '__MigrationHistory')
Foreign Key SQL:
SELECT FK.name AS FK_Table,
FkCol.name AS FK_Column,
PK.name AS PK_Table,
PkCol.name AS PK_Column,
OBJECT_NAME(f.object_id) AS Constraint_Name,
SCHEMA_NAME(FK.schema_id) AS fkSchema,
SCHEMA_NAME(PK.schema_id) AS pkSchema,
PkCol.name AS primarykey,
k.constraint_column_id AS ORDINAL_POSITION
FROM sys.objects AS PK
INNER JOIN sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS k
ON k.constraint_object_id = f.object_id
INNER JOIN sys.indexes AS i
ON f.referenced_object_id = i.object_id
AND f.key_index_id = i.index_id
ON PK.object_id = f.referenced_object_id
INNER JOIN sys.objects AS FK
ON f.parent_object_id = FK.object_id
INNER JOIN sys.columns AS PkCol
ON f.referenced_object_id = PkCol.object_id
AND k.referenced_column_id = PkCol.column_id
INNER JOIN sys.columns AS FkCol
ON f.parent_object_id = FkCol.object_id
AND k.parent_column_id = FkCol.column_id
ORDER BY FK_Table, FK_Column
Extended Properties:
SELECT s.name AS [schema],
t.name AS [table],
c.name AS [column],
value AS [property]
FROM sys.extended_properties AS ep
INNER JOIN sys.tables AS t
ON ep.major_id = t.object_id
INNER JOIN sys.schemas AS s
ON s.schema_id = t.schema_id
INNER JOIN sys.columns AS c
ON ep.major_id = c.object_id
AND ep.minor_id = c.column_id
WHERE class = 1
ORDER BY t.name
I like this format:
name DataType Collation Constraints PK FK Comment
id int NOT NULL IDENTITY PK Order Line Id
pid int NOT NULL tbl_orders Order Id
itemCode varchar(10) Latin1_General_CI_AS NOT NULL Product Code
So I have used this:
DECLARE #tname varchar(100) = 'yourTableName';
SELECT col.name,
CASE typ.name
WHEN 'nvarchar' THEN 'nvarchar('+CAST((col.max_length / 2) as varchar)+')'
WHEN 'varchar' THEN 'varchar('+CAST(col.max_length as varchar)+')'
WHEN 'char' THEN 'char('+CAST(col.max_length as varchar)+')'
WHEN 'nchar' THEN 'nchar('+CAST((col.max_length / 2) as varchar)+')'
WHEN 'binary' THEN 'binary('+CAST(col.max_length as varchar)+')'
WHEN 'varbinary' THEN 'varbinary('+CAST(col.max_length as varchar)+')'
WHEN 'numeric' THEN 'numeric('+CAST(col.precision as varchar)+(CASE WHEN col.scale = 0 THEN '' ELSE ','+CAST(col.scale as varchar) END) +')'
WHEN 'decimal' THEN 'decimal('+CAST(col.precision as varchar)+(CASE WHEN col.scale = 0 THEN '' ELSE ','+CAST(col.scale as varchar) END) +')'
ELSE typ.name
END DataType,
ISNULL(col.collation_name,'') Collation,
CASE WHEN col.is_nullable = 0 THEN 'NOT NULL ' ELSE '' END + CASE WHEN col.is_identity = 1 THEN 'IDENTITY' ELSE '' END Constraints,
ISNULL((SELECT 'PK'
FROM sys.key_constraints kc INNER JOIN
sys.tables tb ON tb.object_id = kc.parent_object_id INNER JOIN
sys.indexes si ON si.name = kc.name INNER JOIN
sys.index_columns sic ON sic.index_id = si.index_id AND sic.object_id = si.object_id
WHERE kc.type = 'PK'
AND tb.name = #tname
AND sic.column_id = col.column_id),'') PK,
ISNULL((SELECT (SELECT name FROM sys.tables st WHERE st.object_id = fkc.referenced_object_id)
FROM sys.foreign_key_columns fkc INNER JOIN
sys.columns c ON c.column_id = fkc.parent_column_id AND fkc.parent_object_id = c.object_id INNER JOIN
sys.tables t ON t.object_id = c.object_id
WHERE t.name = tab.name
AND c.name = col.name),'') FK,
ISNULL((SELECT value
FROM sys.extended_properties
WHERE major_id = tab.object_id
AND minor_id = col.column_id),'') Comment
FROM sys.columns col INNER JOIN
sys.tables tab ON tab.object_id = col.object_id INNER JOIN
sys.types typ ON typ.system_type_id = col.system_type_id
WHERE tab.name = #tname
AND typ.name != 'sysname'
ORDER BY col.column_id;
use
SELECT COL_LENGTH('tablename', 'colname')
None of other solution worked for me.
SELECT C.COLUMN_NAME, C.IS_NULLABLE, C.DATA_TYPE, TC.CONSTRAINT_TYPE, C.COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS AS C
FULL JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS CC ON C.COLUMN_NAME = CC.COLUMN_NAME
FULL JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC ON CC.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
WHERE C.TABLE_NAME = '<Table Name>';
Sample Output
If you are using FirstResponderKit from Brent Ozar team, you can run this query also:
exec sp_blitzindex #tablename='MyTable'
It will return all information about table:
indexes with their usage statistics(reads, writes, locks, etc), space
used and other
missing indexes
columns
foreign keys
statistics contents
Of course it's not a system and not so universal stp like sp_help or sp_columns, but it returns all possible information about your table and I think it's worth creating it at your environment and mentioning it here.
Just double click on the table name and press Alt+F1
CREATE PROCEDURE [dbo].[describe]
(
#SearchStr nvarchar(max)
)
AS
BEGIN
SELECT
CONCAT([COLUMN_NAME],' ',[DATA_TYPE],' ',[CHARACTER_MAXIMUM_LENGTH],' ',
(SELECT CASE [IS_NULLABLE] WHEN 'NO' THEN 'NOT NULL' ELSE 'NULL' END),
(SELECT CASE WHEN [COLUMN_DEFAULT] IS NULL THEN '' ELSE CONCAT(' DEFAULT ',[COLUMN_DEFAULT]) END)
) AS DESCRIPTION
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE #SearchStr
END
The query below will provide similar output as the info() function in python, Pandas library.
USE [Database_Name]
IF OBJECT_ID('tempdo.dob.#primary_key', 'U') IS NOT NULL DROP TABLE #primary_key
SELECT
CONS_T.TABLE_CATALOG,
CONS_T.TABLE_SCHEMA,
CONS_T.TABLE_NAME,
CONS_C.COLUMN_NAME,
CONS_T.CONSTRAINT_TYPE,
CONS_T.CONSTRAINT_NAME
INTO #primary_key
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS CONS_T
JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS CONS_C ON CONS_C.CONSTRAINT_NAME= CONS_T.CONSTRAINT_NAME
SELECT
SMA.name AS [Schema Name],
ST.name AS [Table Name],
SC.column_id AS [Column Order],
SC.name AS [Column Name],
PKT.CONSTRAINT_TYPE,
PKT.CONSTRAINT_NAME,
SC.system_type_id,
STP.name AS [Data Type],
SC.max_length,
SC.precision,
SC.scale,
SC.is_nullable,
SC.is_masked
FROM sys.tables AS ST
JOIN sys.schemas AS SMA ON SMA.schema_id = ST.schema_id
JOIN sys.columns AS SC ON SC.object_id = ST.object_id
JOIN sys.types AS STP ON STP.system_type_id = SC.system_type_id
LEFT JOIN #primary_key AS PKT ON PKT.TABLE_SCHEMA = SMA.name
AND PKT.TABLE_NAME = ST.name
AND PKT.COLUMN_NAME = SC.name
ORDER BY ST.name ASC, SMA.name ASC