I'm looking to list each table in my database and the corresponding column headers with it. Is there a way for SQL to do this and alphabetize the column names in the process?
Something along the formatting lines of:
Table1 Col1name Col2name Col3name ...
Table2 Col1name Col2name Col3name ...
...
Thanks!
SELECT
[schema] = s.name,
[table] = t.name,
[column] = c.name
FROM
sys.tables AS t
INNER JOIN
sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
INNER JOIN
sys.columns AS c
ON t.[object_id] = c.[object_id]
ORDER BY
t.name,
c.name;
And here is why I wouldn't use INFORMATION_SCHEMA for anything in SQL Server 2005+:
The case against INFORMATION_SCHEMA views
SQL Server has an undocumented Stored procedure called sp_MSforeachtable which you can use to iterate through all the tables in a database
Once you know the tablename, you can use Information schema views or info schema view for Columns to see all the columns in the table
This should get you going in the right direction. Really depends on how you want your output:
SELECT t.table_name, STUFF((SELECT distinct ',' + c.COLUMN_NAME
FROM DATABASENAME.INFORMATION_SCHEMA.COLUMNS c WHERE c.TABLE_NAME =t.table_name
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') as Columns
FROM DATABASENAME.INFORMATION_SCHEMA.TABLES t
ORDER BY t.TABLE_NAME, Columns
If using sys.tables and sys.columns as #Aaron points out, then this should work as well:
SELECT t.name, STUFF((SELECT distinct ', ' + c.name
FROM sys.COLUMNS c WHERE t.object_id = c.object_id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') as Columns
FROM sys.TABLES t
ORDER BY t.name, Columns
Good luck.
try this
declare #xml as xml
declare #max_cols int
declare #i int
declare #query as varchar(max)
declare #query_OA2 as varchar(max)
select #max_cols = MAX(n)
from( select COUNT(name) as n
from sys.columns
group by object_id
)V
select #i = 1, #query_OA2 = ''
while #i <= #max_cols
begin
set #query_OA2 = #query_OA2 +', C.elements.value(''./name['+CAST(#i as varchar(max))+']'',''varchar(max)'') as [Column '+CAST(#i as varchar(max))+']'
set #i = #i+1
end
select #query_OA2 = STUFF(#query_OA2,1,1,'')
select #query = 'select t.name as [table]
,OA2.*
from sys.tables t
outer apply (select (select (select c.name from sys.columns c
where c.object_id = t.object_id
order by c.column_id
for xml path(''''),type) for xml path(''columns''),type) as cols
)OA
outer apply (select '+#query_OA2+'
from OA.cols.nodes(''columns'')C(elements)
)OA2
order by t.name'
exec (#query)
part of the resultset I achieved
table Column 1 Column 2 Column 3
Veixxxxx cd_exxx cd_veixxx nr_apxxxxxx
Verxxxx cd_verxxx de_verxxx de_muxxxx
doing a pivot trick...?
declare #max_cols int
declare #i int
declare #query as varchar(max)
declare #query2 as varchar(max)
select #max_cols = MAX(n)
from( select COUNT(COLUMN_NAME) as n
from INFORMATION_SCHEMA.COLUMNS
group by table_name
)V
select #i = 1, #query2 = ''
while #i <= #max_cols
begin
set #query2 = #query2 +', Col_'+CAST(#i as varchar(max))
set #i = #i+1
end
select #query2 = STUFF(#query2,1,1,'')
select #query =
'select *
from (
select T.TABLE_NAME,T.COLUMN_NAME,''Col_''+cast(T.ORDINAL_POSITION as varchar(max)) as pos
from INFORMATION_SCHEMA.COLUMNS T
)V
PIVOT (max(V.COLUMN_NAME) for pos in ('+#query2+'))U'
exec(#query)
resultset achieved was the same as the xml method
TABLE_NAME Col_1 Col_2 Col_3
Veixxxxx cd_exxx cd_veixxx nr_apxxxxxx
Verxxxx cd_verxxx de_verxxx de_muxxxx
Related
I am using a stored procedure with one parameter (#tablename) to generate a table of attributes about the table named via the parameter.
I call the stored procedure as follows
EXEC sp_Schema_Presentation #tablename = 'UserID'
And run the stored procedure (at the bottom of this post).
I have created a #DynamicSQL string in order to use my #tablename parameter. However, the SELECT statement, in which it's used, also creates the #TEMP table.
The rest of the query uses this #TEMP table so I DECLARE its structure at the top.
However, when I run the stored procedure, the #TEMP table is empty
If I hard code the #tablename, the query will work. Any ideas how I can fix this?
Thanks
CREATE TABLE #TEMP
(
SampleKey nvarchar(MAX),
SampleData nvarchar(MAX)
)
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL = N'SELECT B.*
INTO dbo.#TEMP
FROM (
SELECT * FROM ' + #Tablename + N' ORDER BY 1 DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY
) A
CROSS APPLY (
SELECT [Key] AS SampleKey
,Value AS SampleData
FROM OpenJson( (SELECT A.* FOR JSON Path, Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
) B'
Full stored procedure in SQL Server 2016:
ALTER PROCEDURE [dbo].[sp_Schema_Presentation]
#TableName nvarchar(MAX)
AS
BEGIN
CREATE TABLE #TEMP
(
SampleKey nvarchar(MAX),
SampleData nvarchar(MAX)
)
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL = N'SELECT B.*
INTO dbo.#TEMP
FROM (
SELECT * FROM ' + #Tablename + N' ORDER BY 1 DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY
) A
CROSS APPLY (
SELECT [Key] AS SampleKey
,Value AS SampleData
FROM OpenJson( (SELECT A.* FOR JSON Path, Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
) B'
DECLARE #Columns as NVARCHAR(MAX)
SELECT #Columns = COALESCE(#Columns + ', ','') + QUOTENAME(COLUMN_NAME)
FROM
(
SELECT COLUMN_NAME FROM PRESENTATION_PP.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N''' + #TableName + '''
) AS B
EXECUTE sp_executesql #DynamicSQL
SELECT a.COLUMN_NAME,
CASE WHEN a.COLUMN_NAME LIKE '%[_]_key' THEN a.COLUMN_NAME
ELSE REPLACE(a.COLUMN_NAME,'_',' ') END AS DISPLAY_NAME,
a.DATA_TYPE, COALESCE(a.CHARACTER_MAXIMUM_LENGTH, a.NUMERIC_PRECISION) AS SIZE,
CASE WHEN NUMERIC_SCALE IS NULL THEN 0
ELSE NUMERIC_SCALE END AS SCALE,
a.IS_NULLABLE AS NULLABLE,
CASE WHEN i.is_primary_key IS NOT NULL THEN 'YES'
ELSE 'NO' END AS PK,
#TEMP.SampleData
FROM PRESENTATION_PP.INFORMATION_SCHEMA.COLUMNS a
LEFT JOIN
sys.columns c ON a.COLUMN_NAME = c.name
LEFT JOIN
sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT JOIN
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
LEFT JOIN
#TEMP ON a.COLUMN_NAME COLLATE SQL_Latin1_General_CP1_CI_AI = #TEMP.SampleKey COLLATE SQL_Latin1_General_CP1_CI_AI
WHERE TABLE_NAME = #TableName AND c.object_id = OBJECT_ID(#TableName)
SELECT * FROM #TEMP
DROP TABLE #TEMP
END
Create the #Temp table first, and then INSERT INTO not Select ... Into #Temp
CREATE TABLE #TEMP (SampleKey nvarchar(MAX), SampleData nvarchar(MAX))
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL = N'
Insert Into #Temp
SELECT B.*
FROM (
SELECT * FROM ' + #Tablename + N' ORDER BY 1 DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY
) A
CROSS APPLY (
SELECT [Key] AS SampleKey
,Value AS SampleData
FROM OpenJson( (SELECT A.* FOR JSON Path, Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
) B
'
Exec(#DynamicSQL)
Select * from #Temp
I have database with 7,000 tables, most of these have a column DataAreaId, but not all tables, since some are global.
I would like to list all tables that have the column DataAreaId and their row count where the column DataAreaId contains "FR".
So for one table it would be:
SELECT COUNT(*)
FROM Table
WHERE DataAreaId = 'FR'
Any suggestions?
You can use the following
CREATE TABLE T1(
Dataareaid VARCHAR(45)
);
CREATE TABLE T2(
Dataareaid VARCHAR(45)
);
INSERT INTO T1 VALUES
('FR'),
('ALG'),
('FR');
DECLARE #SQL NVARCHAR(max) = N'';
SELECT #SQL = (
SELECT CONCAT(
N'UNION ALL ',
N'SELECT ''',
t.name,
N''' AS TableName, ',
N'Cnt = (SELECT COUNT(1)',
' FROM ',
QUOTENAME(t.name),
N' WHERE [Dataareaid] = ''FR'')'
)
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'Dataareaid'
FOR XML PATH('')
)
SET #SQL = STUFF(#SQL, 1, 10, N'');
EXEC sp_executesql #SQL;
Returns:
+-----------+-----+
| TableName | Cnt |
+-----------+-----+
| T1 | 2 |
| T2 | 0 |
+-----------+-----+
Live Demo
One way to do this is to query all tables containing that column, and build a query statement for each
select 'union all select ' + QUOTENAME(t.name,N'''') + ', count(1) from ' + t.name + ' where Dataareaid = ''FR'''
from sys.columns c
join sys.tables t ON c.object_id = t.object_id
where c.name = 'Dataareaid'
each row would look like this
union all select 'SomeTable', count(1) from SomeTable where Dataareaid = 'FR'
Now just put all statements together and remove the first union all
My answer gets the column metadata, executes the statement in a loop and publishes the results to a table variable:
if object_id('tempdb..#LoopList') is not null
drop table #LoopList
select
s.[name] as SchemaName
,t.[name] as TableName
,row_number() over (order by t.[object_id] asc) as RowNumber
into #LoopList
from sys.columns as c
inner join sys.tables as t
on c.[object_id] = t.[object_id]
inner join sys.schemas as s
on t.[schema_id] = s.[schema_id]
where c.[name] = 'Dataareaid'
declare
#a int = 1
,#b int = (select max(RowNumber) from #LoopList)
,#c nvarchar(max)
,#d nvarchar(max)
,#e int
declare #count table (RowCounter int)
declare #resultsTable table (TableName nvarchar(500), RowCounter int)
while #a <= #b
begin
delete from #count
set #c = concat ((select quotename(SchemaName) from #LoopList where RowNumber = #a)
,'.'
,(select quotename(TableName) from #LoopList where RowNumber = #a)
)
set #d = concat(N'select count(*) from '
,#c
,N' where Dataareaid = ''FR'''
)
insert into #count (
RowCounter
)
exec sp_executesql #d
set #e = (select top 1 RowCounter from #count)
insert into #resultsTable (
TableName
,RowCounter
)
values (#c,#e)
set #a += 1;
end
select * from #resultsTable
I am trying to get the maximum value MAX(ID) for each table I have which contains ID on my DB "Table_Example" and one schema_name in specific.
A single example:
SELECT MAX(ID) FROM Schema_name.Table_name1
This retrieve the maximum ID value that is located on Table_name1, but I have 84 tables. I would like to know the max of each table only in one column.
This is the code where I am working on currently:
I am using information_schema.columns to get the names of the tables automatic and the schema each table belongs to in order to get the whole DB IDs max(id) in one column.
USE TABLE_EXAMPLE
GO
DECLARE #ID NVARCHAR(MAX) --int
SET #ID = (SELECT DISTINCT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'SCHEMA_NAME' AND COLUMN_NAME IN ('ID') AND DATA_TYPE = 'INT')
SELECT #ID FROM (SELECT ('SCHEMA_NAME'+'.'+TABLE_NAME) AS TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'SCHEMA_NAME' AND COLUMN_NAME = 'ID' AND DATA_TYPE='INT') AS W
This Script retrieve wrong data but I think I am a bit closed to get the values, but I am not sure what I am doing wrong.
Could someone give me any good approach? Or any better option to get it done?
If you are wanting the max value in your identity columns, regardless of the names of those columns, then this is a very simple way of doing it. This will give you the Table Name, the name of the Identity Column, and the max value of that column:
SELECT sys.tables.name AS [Table Name],
sys.identity_columns.name AS [Column Name],
last_value AS [Last Value]
FROM sys.identity_columns
INNER JOIN sys.tables
ON sys.identity_columns.object_id = sys.tables.object_id
ORDER BY last_value DESC
This enumerate all tables with column Id and MAX value of this ID:
DECLARE #query nvarchar(MAX);
SELECT #query = COALESCE(#query + char(10)+'UNION ALL '+char(10)+'SELECT '''+QUOTENAME(s.name)+'.'+QUOTENAME(T.name)+''' [Table], MAX(Id) [Max] FROM '+QUOTENAME(s.name)+'.'+QUOTENAME(T.name),
'SELECT '''+QUOTENAME(s.name)+'.'+QUOTENAME(T.name)+''' [Table], MAX(Id) [Max] FROM '+QUOTENAME(s.name)+'.'+QUOTENAME(T.name))
FROM sys.schemas S
JOIN sys.tables T ON S.schema_id=T.schema_id
JOIN sys.columns C ON T.object_id=C.object_id
WHERE C.name='Id';
EXEC(#query);
Try like this,
This would give you the script.
SELECT DISTINCT 'SELECT MAX(' + + COLUMN_NAME + ') as ' + table_name + 'MaxId FROM ' + table_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND COLUMN_NAME IN ('ID')
CREATE TABLE #MaxValues (SchemaName SYSNAME , TableName SYSNAME , MaxID INT)
GO
Declare #SchemaName SYSNAME = 'dbo' --<-- Pass you schema name to this variable
,#ColumnName SYSNAME = 'ID' --<-- Column Name
,#DataType SYSNAME = 'INT' --<-- Data type
DECLARE #TableName SYSNAME , #SchmaName SYSNAME
, #Sql NVARCHAR(MAX) , #ColName SYSNAME;
Declare Cur CURSOR LOCAL FAST_FORWARD FOR
SELECT s.name , t.name , c.name
FROM sys.columns c
Inner join sys.tables t on c.object_id = t.object_id
Inner join sys.schemas s on s.schema_id = t.schema_id
Inner join sys.types tp on tp.user_type_id = c.user_type_id
WHERE s.name = #SchemaName
AND c.name = #ColumnName
AND tp.name = #DataType
OPEN Cur
FETCH NEXT FROM Cur INTO #SchmaName , #TableName , #ColName
WHILE (##FETCH_STATUS =0)
BEGIN
SET #Sql = N'INSERT INTO #MaxValues (SchemaName, TableName, MaxID )'
+ N' SELECT #SchmaName ,#TableName, MAX(' + QUOTENAME(#ColName) + N') '
+ N' FROM ' + QUOTENAME(#SchmaName) + '.' + QUOTENAME(#TableName)
Exec sp_executesql #Sql
,N'#SchmaName SYSNAME , #TableName SYSNAME'
,#SchmaName
,#TableName
FETCH NEXT FROM Cur INTO #SchmaName , #TableName , #ColName
END
CLOSE Cur
DEALLOCATE Cur
SELECT * FROM #MaxValues
Perhaps a little dynamic SQL
Edit This will return the Table Name(s) and Max ID in one dataset
Declare #SQL varchar(max) = '>>>'
Select #SQL = #SQL + SQL
From (
Select SQL='Union All Select TableName='''+concat('[',Table_Schema,'].[',Table_Name,']')+''',MaxID=max(ID) From '+concat('[',Table_Schema,'].[',Table_Name,'] ')
From INFORMATION_SCHEMA.COLUMNS
Where Column_Name = 'ID'
) A
Set #SQL=Replace(#SQL,'>>>Union All ','')
Exec(#SQL)
This script will list all the max ids. It is assuming your first column is the ID, regardless of its name.
DECLARE #Script AS VARCHAR(MAX) = ''
SELECT #Script = #Script + 'SELECT MAX(' + COLUMN_NAME + ') AS ID FROM ' + c.TABLE_NAME + ' UNION ALL ' + CHAR(13)+CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS c
INNER JOIN INFORMATION_SCHEMA.TABLES t ON c.TABLE_NAME = t.TABLE_NAME
WHERE c.ORDINAL_POSITION = 1 and t.TABLE_TYPE = 'BASE TABLE' and c.TABLE_SCHEMA = 'dbo' and c.DATA_TYPE = 'int'
SELECT #Script = LEFT(#Script, LEN(#Script) - 12)
EXEC (#Script)
Can anyone please help me with the query to list all the tables in all the databases in a single server?.
Thanks in advance.
Use sp_MSforeachdb to iterate through all databases and INFORMATION_SCHEMA.TABLES to query the tables in each:
sp_MSforeachdb 'USE [?]; SELECT * FROM INFORMATION_SCHEMA.TABLES'
AS stated here by
Try with dynamic query
You need a query for each database against sys.tables.
select 'master' as DatabaseName,
T.name collate database_default as TableName
from master.sys.tables as T
union all
select 'tempdb' as DatabaseName,
T.name collate database_default as TableName
from tempdb.sys.tables as T
union all
select 'model' as DatabaseName,
T.name collate database_default as TableName
from model.sys.tables as T
union all
select 'msdb' as DatabaseName,
T.name collate database_default as TableName
from msdb.sys.tables as T
You can use sys.databases to build and execute the query dynamically.
declare #SQL nvarchar(max)
set #SQL = (select 'union all
select '''+D.name+''' as DatabaseName,
T.name collate database_default as TableName
from '+quotename(D.name)+'.sys.tables as T
'
from sys.databases as D
for xml path(''), type).value('substring((./text())[1], 13)', 'nvarchar(max)')
--print #SQL
exec (#SQL)
IF OBJECT_ID('tempdb.dbo.#tbl') IS NOT NULL
DROP TABLE #tbl
CREATE TABLE #tbl (
database_id SYSNAME
, tbl_name SYSNAME
, sch_name SYSNAME
, [rows] INT
)
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = STUFF((
SELECT '
USE [' + d.name + ']
INSERT INTO #tbl
SELECT DB_NAME(), o.name, s.name, p.[rows]
FROM sys.objects o
JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
LEFT JOIN (
SELECT p.[object_id], [rows] = SUM(p.[rows])
FROM sys.partitions p
WHERE p.index_id < 2
GROUP BY p.[object_id]
) p ON p.[object_id] = o.[object_id]
WHERE o.[type] = ''U''
AND o.is_ms_shipped = 0;'
FROM sys.databases d
WHERE d.[state] = 0
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
EXEC sys.sp_executesql #SQL
SELECT * FROM #tbl
I would like to find all the tables in my database where the columns "Column1" & "Column2" contain a specific case sensitive string 'aBcD'.Is there a way to do it ?
I came up with the following query . Any suggestions ?
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 = 'Column1' or c.name = 'Column2' and
/* column contents is 'aBcD' */ ?
One solution could be to iterate over all found tables and check their content like this:
DECLARE cur CURSOR FOR
SELECT t.name, c.name
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'Column1' or c.name = 'Column2'
OPEN cur
CREATE TABLE #output(tablename nvarchar(255), columnname nvarchar(255))
DECLARE #sql nvarchar(max), #tab nvarchar(max), #col nvarchar(max)
FETCH NEXT FROM cur INTO #tab, #col
WHILE(##FETCH_STATUS = 0) BEGIN
SET #sql = N'
IF(SELECT COUNT(*)
FROM '+#tab+'
WHERE '+#col+' = N''aBcD''
COLLATE Latin1_General_CS_AS) > 0
INSERT INTO #output(tablename, columname)
VALUES(N'''+#tab+''',N'''+#col+''')'
EXEC(#sql)
FETCH NEXT FROM cur INTO #tab, #col
END
SELECT * FROM #output
-- Cleanup
CLOSE cur
DEALLOCATE cur
DROP TABLE #output
My buddy Chris Morris at sqlservercentral.com posted this a few years ago. I modified it slightly to be a little more flexible. This will generate a series of select statements which is much faster than using a cursor. If you wanted to you could shove the results of this into a variable and execute it. Or you can just copy and paste several of these into another query window and run them.
DECLARE #MySearchCriteria VARCHAR(500)
SET #MySearchCriteria = '''This user registration has been rejected''' --you do need all these quotation marks because this string is injected to another string.
SELECT 'SELECT ' + c.columnlist + '] FROM [' + t.name + '] WHERE ' + w.whereclause + ';' as SelectStatement
FROM sys.tables t
CROSS APPLY (
SELECT STUFF((
SELECT '], [' + c.Name AS [text()]
FROM sys.columns c
join sys.types t2 on t2.user_type_id = c.user_type_id
WHERE t.object_id = c.object_id
AND c.collation_name IS NOT NULL
AND c.max_length > 6
and t2.name not in ('text', 'ntext')
FOR XML PATH('')
), 1, 2, '' )
) c (columnlist)
CROSS APPLY (
SELECT STUFF((
SELECT ' OR [' + c.Name + '] IN (' + #MySearchCriteria + ')' AS [text()]
FROM sys.columns c
join sys.types t2 on t2.user_type_id = c.user_type_id
WHERE t.object_id = c.object_id
AND c.collation_name IS NOT NULL
AND c.max_length > 6
and t2.name not in ('text', 'ntext')
FOR XML PATH('')
), 1, 4, '' )
) w (whereclause)
where c.columnlist is not null
ORDER BY t.name