T-SQL List Tables, Columns - sql-server

In T-SQL (SQL Server 2000). How can I list all tables and columns in a database?
Also, in a separate query is there a way to list all columns along with data type and constraints (NULLS, etc). Thanks.

Please check out the information schema.
select *
from MyDatabaseName.information_schema.columns
order by table_name, ordinal_position

Many ways to do it. Below are couple of ways that you can list :
Option 1:
SELECT db_name() as DATABASE_NAME, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION,
COLUMN_DEFAULT, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH,
NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE,
DATETIME_PRECISION
FROM INFORMATION_SCHEMA.COLUMNS
Option 2:
DECLARE #SQL VARCHAR(8000)
SELECT #SQL = ''
SELECT #SQL = #SQL + 'UNION
SELECT ''' + name + ''' [DataBaseName], t.name [TableName], c.name [ColumnName], st.name [DataType] FROM ' + name + '..sysobjects t INNER JOIN ' + name + '..syscolumns c ON t.id = c.id INNER JOIN '+ name + '..systypes st on c.xtype = st.xtype where t.xtype = ''U'''
FROM master..sysdatabases
WHERE name IN ('databasename1', 'databaseName2') -- change here !!
SELECT #SQL = RIGHT(#SQL, LEN(#SQL)-5) + ' ORDER BY 1, 2, 3'
EXEC(#SQL)
Option 3:
select db_name() as database_name
,table_name = sysobjects.name
,column_name = syscolumns.name
,datatype = systypes.name
,length = syscolumns.length
from sysobjects
inner join syscolumns on sysobjects.id = syscolumns.id
inner join systypes on syscolumns.xtype = systypes.xtype
where sysobjects.xtype = 'U'
order by sysobjects.name
,syscolumns.colid

Related

Iterate through all DBs - Get constraints in all tables

I'm trying to iterate through all databases by listing all table constraints. I've achieved the following:
DECLARE #sql nvarchar(max) = ''
SET #sql =
'
USE ?
select con.[name] as constraint_name,
schema_name(t.schema_id) + ''.'' + t.[name] as [table],
col.[name] as column_name,
con.[definition],
case when con.is_disabled = 0
then ''Active''
else ''Disabled''
end as [status]
from sys.check_constraints con
left outer join sys.objects t
on con.parent_object_id = t.object_id
left outer join sys.all_columns col
on con.parent_column_id = col.column_id
and con.parent_object_id = col.object_id
order by con.name
'
PRINT #sql
EXEC sp_MSforeachdb #sql
I would like to have the query UNION all of my results in one clean select.
Can anyone help?
Using SQL Server 2016.
One way is to insert the intermediate results into a temp table. Below is an example that also includes the database name in the results.
CREATE TABLE #results (
[database_name] sysname
,[constraint_name] nvarchar(128)
,[table] nvarchar(257)
,[column_name] nvarchar(128)
,[definition] nvarchar(max)
,[status] varchar(8)
);
DECLARE #sql nvarchar(max) = ''
SET #sql =
N'
USE [?];
INSERT INTO #results
select
N''?'' as database_name,
con.[name] as constraint_name,
schema_name(t.schema_id) + ''.'' + t.[name] as [table],
col.[name] as column_name,
con.[definition],
case when con.is_disabled = 0
then ''Active''
else ''Disabled''
end as [status]
from sys.check_constraints con
left outer join sys.objects t
on con.parent_object_id = t.object_id
left outer join sys.all_columns col
on con.parent_column_id = col.column_id
and con.parent_object_id = col.object_id;
';
PRINT #sql;
EXEC sp_MSforeachdb #sql;
SELECT * FROM #results;

How to find matching columns in multiple tables in a SQL Server database?

How to find matching columns in multiple tables in a SQL Server database?
I have a SQL Server database with over 30 tables, is there a way to filter and/or produce a list of the common columns amongst the tables rather than going through each manually?
Maybe some code?
As explained in the comments, you want to use system table sys.columns to achieve your goal.
This query lists all column names that are present more than once in the database, along with the number of occurences :
SELECT name, COUNT(*)
FROM sys.columns
GROUP BY name
HAVING COUNT(*) > 1
You can join the results with sys.tables to recover the corresponding tables, like :
SELECT
C.name AS ColumnName,
T.name AS TableName
FROM
(SELECT name FROM sys.columns GROUP BY name HAVING COUNT(*) > 1 ) A
JOIN sys.columns C on C.name = A.name
JOIN sys.tables T ON T.object_id = C.object_id
ORDER BY
C.name,
T.name
I'd use something easy like this:
SELECT [Unique name #] = DENSE_RANK() OVER(ORDER BY c.name)
, [Column] = c.name
, [Column type] = t.name
, [Column max length] = c.max_length
, [Column precision] = c.precision
, [Table schema] = OBJECT_SCHEMA_NAME(c.object_id)
, [Table name] = OBJECT_NAME(c.object_id)
FROM sys.columns as c
INNER JOIN sys.systypes as t ON t.type = c.system_type_id
WHERE OBJECTPROPERTY(c.object_id,'IsTable') = 1
and OBJECT_SCHEMA_NAME(c.object_id) != 'sys'
ORDER BY c.name;
With this query you have all the columns with same name in different tables of your DB:
select object_name(c.id) + '.' + c.name + ' '
+ t.name
+ case when t.xtype = t.xusertype then '' else '[' + tr.name end
+ case
when tr.name in ('bit', 'tinyint', 'smallint', 'int', 'bigint',
'float', 'money', 'smallmoney', 'real', 'date', 'time',
'datetime', 'datetime2', 'smalldatetime', 'timestamp')
then ''
else
case when isNull(c.prec,0)=0 then ''
else '('
+ case when c.prec = - 1 then 'MAX' else cast(c.prec as varchar) end
+ case when c.scale is null then '' else ',' + cast(c.scale as varchar) end
+ ')'
end
end
+ case when t.xtype = t.xusertype then '' else ']' end
+ case when t.collationId <> c.collationId
then ' collate ' + c.collation collate Latin1_General_BIN else '' end
+ case c.isnullable when 0 then ' not null' else '' end
+ case c.colstat
when 1 then ' identity(' + Cast(Ident_seed(o.name) as varchar)
+ ',' + cast(Ident_incr(o.name) as varchar) + ')'
else ''
end
+ case when cm.text is null then ''
else ' default '
+ case when patindex('% as %', cm.text) > 0
then rtrim(substring(cm.text, patindex('% as %', cm.text) + 4, len(cm.text)))
else substring(cm.text, 2, len(cm.text) - 2)
end
end
as Columns
from syscolumns c
join systypes t on (t.xusertype = c.xusertype)
left join systypes tr
on (tr.xtype = t.xtype and tr.xusertype = t.xtype)
join sysobjects o
on (o.id = c.id)
left join syscomments cm
on (cm.id = c.cdefault)
where c.name in (
select cl.name
from syscolumns cl
join sysobjects ob on (cl.id = ob.id and ob.xtype = 'U')
group by cl.name
having count(*) > 1
)
order by c.name
this will work:
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'table1name'
intersect
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'table2name';
intersect
...
...
..
...
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'table30name';
sql server equivalent:
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table1'
intersect
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table2'
intersect
.....
....
...
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table30';
Below is the query which will provide you the list of all tables where your "Column" is present.
SELECT c.name AS ColName, t.name AS TableName FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id WHERE c.name LIKE '%ColumnName%';
And based on that you can continue you task you want to perform.
Thumbs up if it is helpful.
select name as 'Column_Name' from syscolumns s1 where id = object_id('table1') and
exists(select 1 from syscolumns s2 where s2.name = s1.name and s2.id = object_id('table2'))
it will return the matched columns

Find Identity columns from another database

Normally with SQL Server you can use the COLUMNPROPERTY function like this to find the Identity columns in a database:
select TABLE_NAME + '.' + COLUMN_NAME, TABLE_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA = 'dbo'
and COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME
But I can't figure out how to get this to work when running the query from another database. E.g. this does not return any results:
Use FirstDatabase
Go
select TABLE_NAME + '.' + COLUMN_NAME, TABLE_NAME
from SecondDatabase.INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA = 'dbo'
and COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME
Object_ID only works in current db, unless you use a 3-part name, but that form is complicated to use. Also, ColumnProperty only works in current db.
select o.name + '.' + c.name, o.name
from test1.sys.columns c
join test1.sys.objects o on c.object_id = o.object_id
join test1.sys.schemas s on s.schema_id = o.schema_id
where s.name = 'dbo'
and o.is_ms_shipped = 0 and o.type = 'U'
and c.is_identity = 1
order by o.name
There is no way to get information with the help of COLUMNPROPERTY from another database. But there is on workaround:
DECLARE #DatabaseName VARCHAR(MAX)
DECLARE #TableName VARCHAR(MAX)
DECLARE #SQL VARCHAR(MAX)
SET #DatabaseName = 'MyDatabase'
SET #TableName = 'MyTable'
SET #SQL = '
SELECT
C.TABLE_NAME,
C.COLUMN_NAME,
S.IS_IDENTITY
FROM ' + #DatabaseName + '.INFORMATION_SCHEMA.COLUMNS AS C
LEFT JOIN ' + #DatabaseName + '.SYS.COLUMNS AS S ON OBJECT_ID(''' + #DatabaseName + '.dbo.' + #TableName + ''') = S.OBJECT_ID AND C.COLUMN_NAME = S.NAME
WHERE S.IS_IDENTITY = 1'
EXEC(#SQL)
This worked for me using a specific database:
USE <database_name>;
GO
SELECT SCHEMA_NAME(schema_id) AS schema_name
, t.name AS table_name
, c.name AS column_name
FROM sys.tables AS t
JOIN sys.identity_columns c ON t.object_id = c.object_id
ORDER BY schema_name, table_name;
GO
In this example, I've constructed a stored procedure in "Database1" that uses dynamic SQL to retrieve column information from a table in "Database2" (using the [INFORMATION_SCHEMA].[COLUMNS] system view residing in "Database2"):
ALTER PROCEDURE [Database1].[Schema1].[ColumnNames] #Database2 nvarchar(128), #Schema2 nvarchar(128), #Table2 nvarchar(128)
AS
BEGIN
DECLARE #Sql nvarchar(1000)
SET #Sql = 'SELECT [COLUMN_NAME], [ORDINAL_POSITION] FROM [' + #Database2 + '].[INFORMATION_SCHEMA].[COLUMNS]
WHERE [TABLE_SCHEMA] = ''' + #Schema2 + ''' AND [TABLE_NAME] = ''' + #Table2 + ''''
EXEC(#Sql)
END
I'm using SQL Server 2019, and I have run into the same challenge. I'm not sure if this fix will work for older versions, but there is a view in each DB called Your-DB-Name.sys.identity_columns. If you select from this view, you'll see the list of identity columns you have defined in that DB.
From that information you should be able to write a join connecting YourDBName.Information_schema.columns such as below:
SELECT *
FROM YourDBName.Information_Schema.columns col
LEFT OUTER JOIN YourDBName.sys.identity_columns idc
ON idc.name = col.COLUMN_NAME AND idc.object_id = object_id('YourDBName..YourTableName')
WHERE col.TABLE_NAME = 'YourTableName' AND col.table_catalog = 'YourDBName';
The YourDbName.sys.identity_columns view contains the following fields that might be useful:
object_id (used to join back to the table in question in case you have multiple tables with the same identity field name)
name (the name of the Identity field)
column_id (the order of the column in your table)
is_identity (tells you if this is an identity field)
seed_value (the initial value of the identity field)
increment_value (how much the identity field goes up with each insert)

How Can I Find All Columns That Contain A String and Null Those Values

My goal is to write a SQL Server script (2008 R2 if it matters) that nulls out all values in all tables where the column name contains "Qualifiers".
E.g. Table A contains columns named "TemperatureQualifiers" and "SalinityQualifiers". For all rows in that table, those values should be set to null. There are also several other tables that have columns with similar names.
This will generate the update statements for you. You can extend this to execute them as dynamic SQL or simply cut/paste the results to another SSMS query window and run them.
select 'update [' + s.name + '].[' + t.name + '] set [' + c.name + '] = NULL'
from sys.columns c
inner join sys.tables t
on c.object_id = t.object_id
inner join sys.schemas s
on t.schema_id = s.schema_id
where c.name like '%Qualifiers%'
and t.type = 'U'
Bit late on this one. This will generate a script that consolidates updates where there are multiple columns in the same table to be updated.
DECLARE #Script nvarchar(MAX);
SET #Script = '';
WITH Cols AS
( SELECT c.object_id,
c.name,
schema_name(t.schema_id) AS SchemaName,
t.name AS TableName
FROM sys.columns c INNER JOIN
sys.tables t ON c.object_id = t.object_id
WHERE c.name LIKE '%Qualifiers%'
AND is_computed=0
AND is_rowguidcol=0
AND is_identity=0
AND is_nullable=1
AND objectproperty(c.object_id, N'IsUserTable')=1
)
,
Tables AS
( SELECT DISTINCT object_id, TableName, SchemaName
FROM Cols
)
,
Statements AS
( SELECT 'UPDATE ' + QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' SET ' + STUFF(
( SELECT ',' + c.name + '=NULL'
FROM Cols c
WHERE c.object_id = t.object_id FOR XML PATH('')
)
, 1, 1, '') AS Statement
FROM Tables t
)
SELECT #Script = #Script + '
' +Statement
FROM Statements
SELECT #Script AS [processing-instruction(x)] FOR XML PATH('')

How do you determine what SQL Tables have an identity column programmatically

I want to create a list of columns in SQL Server 2005 that have identity columns and their corresponding table in T-SQL.
Results would be something like:
TableName, ColumnName
Another potential way to do this for SQL Server, which has less reliance on the system tables (which are subject to change, version to version) is to use the
INFORMATION_SCHEMA views:
select COLUMN_NAME, TABLE_NAME
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME
sys.columns.is_identity = 1
e.g.,
select o.name, c.name
from sys.objects o inner join sys.columns c on o.object_id = c.object_id
where c.is_identity = 1
Another way (for 2000 / 2005/2012/2014):
IF ((SELECT OBJECTPROPERTY( OBJECT_ID(N'table_name_here'), 'TableHasIdentity')) = 1)
PRINT 'Yes'
ELSE
PRINT 'No'
NOTE: table_name_here should be schema.table, unless the schema is dbo.
In SQL 2005:
select object_name(object_id), name
from sys.columns
where is_identity = 1
This query seems to do the trick:
SELECT
sys.objects.name AS table_name,
sys.columns.name AS column_name
FROM sys.columns JOIN sys.objects
ON sys.columns.object_id=sys.objects.object_id
WHERE
sys.columns.is_identity=1
AND
sys.objects.type in (N'U')
List of tables without Identity column based on Guillermo answer:
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (TABLE_SCHEMA = 'dbo') AND (OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 0)
ORDER BY TABLE_NAME
here's a working version for MSSQL 2000. I've modified the 2005 code found here: http://sqlfool.com/2011/01/identity-columns-are-you-nearing-the-limits/
/* Define how close we are to the value limit
before we start throwing up the red flag.
The higher the value, the closer to the limit. */
DECLARE #threshold DECIMAL(3,2);
SET #threshold = .85;
/* Create a temp table */
CREATE TABLE #identityStatus
(
database_name VARCHAR(128)
, table_name VARCHAR(128)
, column_name VARCHAR(128)
, data_type VARCHAR(128)
, last_value BIGINT
, max_value BIGINT
);
DECLARE #dbname sysname;
DECLARE #sql nvarchar(4000);
-- Use an cursor to iterate through the databases since in 2000 there's no sp_MSForEachDB command...
DECLARE c cursor FAST_FORWARD FOR
SELECT
name
FROM
master.dbo.sysdatabases
WHERE
name NOT IN('master', 'model', 'msdb', 'tempdb');
OPEN c;
FETCH NEXT FROM c INTO #dbname;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'Use [' + #dbname + '];
Insert Into #identityStatus
Select ''' + #dbname + ''' As [database_name]
, Object_Name(id.id) As [table_name]
, id.name As [column_name]
, t.name As [data_type]
, IDENT_CURRENT(Object_Name(id.id)) As [last_value]
, Case
When t.name = ''tinyint'' Then 255
When t.name = ''smallint'' Then 32767
When t.name = ''int'' Then 2147483647
When t.name = ''bigint'' Then 9223372036854775807
End As [max_value]
From
syscolumns As id
Join systypes As t On id.xtype = t.xtype
Where
id.colstat&1 = 1 -- this identifies the identity columns (as far as I know)
';
EXECUTE sp_executesql #sql;
FETCH NEXT FROM c INTO #dbname;
END
CLOSE c;
DEALLOCATE c;
/* Retrieve our results and format it all prettily */
SELECT database_name
, table_name
, column_name
, data_type
, last_value
, CASE
WHEN last_value < 0 THEN 100
ELSE (1 - CAST(last_value AS FLOAT(4)) / max_value) * 100
END AS [percentLeft]
, CASE
WHEN CAST(last_value AS FLOAT(4)) / max_value >= #threshold
THEN 'warning: approaching max limit'
ELSE 'okay'
END AS [id_status]
FROM #identityStatus
ORDER BY percentLeft;
/* Clean up after ourselves */
DROP TABLE #identityStatus;
The following query work for me:
select TABLE_NAME tabla,COLUMN_NAME columna
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
order by TABLE_NAME
I think this works for SQL 2000:
SELECT
CASE WHEN C.autoval IS NOT NULL THEN
'Identity'
ELSE
'Not Identity'
AND
FROM
sysobjects O
INNER JOIN
syscolumns C
ON
O.id = C.id
WHERE
O.NAME = #TableName
AND
C.NAME = #ColumnName
This worked for me using Sql Server 2008:
USE <database_name>;
GO
SELECT SCHEMA_NAME(schema_id) AS schema_name
, t.name AS table_name
, c.name AS column_name
FROM sys.tables AS t
JOIN sys.identity_columns c ON t.object_id = c.object_id
ORDER BY schema_name, table_name;
GO
Use this :
DECLARE #Table_Name VARCHAR(100)
DECLARE #Column_Name VARCHAR(100)
SET #Table_Name = ''
SET #Column_Name = ''
SELECT RowNumber = ROW_NUMBER() OVER ( PARTITION BY T.[Name] ORDER BY T.[Name], C.column_id ) ,
SCHEMA_NAME(T.schema_id) AS SchemaName ,
T.[Name] AS Table_Name ,
C.[Name] AS Field_Name ,
sysType.name ,
C.max_length ,
C.is_nullable ,
C.is_identity ,
C.scale ,
C.precision
FROM Sys.Tables AS T
LEFT JOIN Sys.Columns AS C ON ( T.[Object_Id] = C.[Object_Id] )
LEFT JOIN sys.types AS sysType ON ( C.user_type_id = sysType.user_type_id )
WHERE ( Type = 'U' )
AND ( C.Name LIKE '%' + #Column_Name + '%' )
AND ( T.Name LIKE '%' + #Table_Name + '%' )
ORDER BY T.[Name] ,
C.column_id
This worked for SQL Server 2005, 2008, and 2012.
I found that the sys.identity_columns did not contain all my tables with identity columns.
SELECT a.name AS TableName, b.name AS IdentityColumn
FROM sys.sysobjects a
JOIN sys.syscolumns b
ON a.id = b.id
WHERE is_identity = 1
ORDER BY name;
Looking at the documentation page the status column can also be utilized. Also you can add the four part identifier and it will work across different servers.
SELECT a.name AS TableName, b.name AS IdentityColumn
FROM [YOUR_SERVER_NAME].[YOUR_DB_NAME].sys.sysobjects a
JOIN [YOUR_SERVER_NAME].[YOUR_DB_NAME].sys.syscolumns b
ON a.id = b.id
WHERE is_identity = 1
ORDER BY name;
Source:
https://msdn.microsoft.com/en-us/library/ms186816.aspx
By some reason sql server save some identity columns in different tables, the code that work for me, is the following:
select TABLE_NAME tabla,COLUMN_NAME columna
from INFORMATION_SCHEMA.COLUMNS
where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1
union all
select o.name tabla, c.name columna
from sys.objects o
inner join sys.columns c on o.object_id = c.object_id
where c.is_identity = 1
Get all columns with Identity. Modern version for MSSQL 2017+. Locks down to specific database:
SELECT
[COLUMN_NAME]
, [TABLE_NAME]
, [TABLE_CATALOG]
FROM
[INFORMATION_SCHEMA].[COLUMNS]
WHERE
COLUMNPROPERTY(OBJECT_ID(CONCAT_WS('.' ,[TABLE_CATALOG] ,[TABLE_SCHEMA] ,[TABLE_NAME])) ,[COLUMN_NAME] ,'IsIdentity') = 1
ORDER BY
[TABLE_NAME]

Resources