3

Is it possible to string a table columns headers dynamically from information_schema recursively

So if I had 2 tables (or however many) in my database with 5 columns each

Could I get the query to find this tables by schema and then string all the table columns hearders into another table ending up with something like

table name ¦ string 
Table A    ¦ id,columnName1,columnName2 ,columnName3 ,columnName4 ,columnName5
Table b    ¦ id,columnName1,columnName2 ,columnName3 ,columnName4 ,columnName5

(THESE ARE TWO ROWS BTW)

user2181700
  • 147
  • 3
  • 15
  • http://stackoverflow.com/questions/451415/simulating-group-concat-mysql-function-in-microsoft-sql-server-2005 – Filip Apr 24 '13 at 17:53

5 Answers5

4

It can be simpler, no XML:

declare @columns varchar(1000)
set @columns=''

select @columns = @columns + ',' + name
from sys.columns 
where object_id = object_id('MyTable')
Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149
  • 2
    I needed this in query, so that extra comma is a bit annoying, so i've added a check : `@columns + IIF(ROW_NUMBER() OVER (ORDER BY (SELECT 1)) = 1, '', ',') + name` – Pavel Galaton Jan 14 '16 at 07:12
2

Something using FOR XML PATH('') in combination with the sys.columns and sys.tables could work:

SELECT t.name [TableName], 
(
    SELECT name + ','
    FROM sys.columns c
    WHERE c.object_id = t.object_id
    FOR XML PATH('')
) [String]
FROM sys.tables t

It basically takes the columns returned from a query and formats is as XML, where the element tags are defined in the PATH(''). If you leave it blank, though, it will omit the tags and return a string instead.

The documentation on MSDN also has a lot of different examples with other uses for the FOR XML clause.

valverij
  • 4,871
  • 1
  • 22
  • 35
1

Using sys.objects more effective that sys.tables. Possible this be helpful for you -

SELECT 
      table_name = s.name + '.' + o.name
    , [columns] = STUFF((
        SELECT ', ' + c.name
        FROM sys.columns c WITH (NOWAIT)
        WHERE c.[object_id] = o.[object_id]
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM (
    SELECT 
          o.[object_id]
        , o.name
        , o.[schema_id]
    FROM sys.objects o WITH (NOWAIT)
    WHERE o.[type] = 'U'
        AND o.is_ms_shipped = 0
) o
INNER JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id] 
ORDER BY 
      s.name
    , o.name
Md Imran Choudhury
  • 9,343
  • 4
  • 62
  • 60
Devart
  • 119,203
  • 23
  • 166
  • 186
  • You're welcome @user2181700. In case this solution fully suits you, I would be glad if you could confirm it. – Devart Apr 25 '13 at 08:47
0

This will do it (although there may be another way):

;with cte as
(
    Select  TableName = t.TABLE_NAME
            ,ColumnList = Substring((Select ', ' + c2.COLUMN_NAME
                                    From    INFORMATION_SCHEMA.COLUMNS c2
                                    Where   c.TABLE_NAME = c2.TABLE_NAME
                                    For XML Path('')
                                    ), 3, 8000)
            ,ROW_NUMBER() OVER(Partition By t.TABLE_NAME Order By t.TABLE_NAME) RowNumber
    From    INFORMATION_SCHEMA.TABLES t
    join    INFORMATION_SCHEMA.COLUMNS c
        on  t.TABLE_NAME = c.TABLE_NAME
)
Select  TableName
        ,ColumnList
From    cte
Where   RowNumber = 1
Dave Johnson
  • 825
  • 16
  • 27
0

I think you want use this Query for making class files of all the tables in your DB. Hence the answer

if object_id('tempdb..#t') is not null
    drop table #t

SELECT 
T.name Table_name
,ltrim(rtrim(C.name)) Column_name
,TYPE1.name AS [type_name]
,C.max_length length1
into #t
FROM sys.tables T WITH(NOLOCK)
INNER JOIN sys.columns C WITH(NOLOCK) ON T.OBJECT_ID=C.OBJECT_ID
INNER JOIN sys.types AS TYPE1 with(nolock) ON c.user_type_id=TYPE1.user_type_id
ORDER BY T.name

SELECT 
  #t.Table_name,
  STUFF((
    SELECT ', ' + t2.Column_name+' as ' +t2.type_name + '('+ cast(t2.length1 as varchar) + ')'
    FROM #t t2
    WHERE t2.Table_name = #t.Table_name
    FOR XML PATH (''))
,1,2,'') AS Names
FROM #t
GROUP BY #t.Table_name;

Specific answer to your Question

if object_id('tempdb..#t') is not null
    drop table #t

SELECT 
T.name Table_name
,ltrim(rtrim(C.name)) Column_name
into #t
FROM sys.tables T WITH(NOLOCK)
INNER JOIN sys.columns C WITH(NOLOCK) ON T.OBJECT_ID=C.OBJECT_ID
where t.name in ('[Table A]','[Table B]')
ORDER BY T.name

SELECT 
  #t.Table_name,
  STUFF((
    SELECT ', ' + t2.Column_name
    FROM #t t2
    WHERE t2.Table_name = #t.Table_name
    FOR XML PATH (''))
,1,2,'') AS Names
FROM #t
GROUP BY #t.Table_name;
Prahalad Gaggar
  • 11,389
  • 16
  • 53
  • 71
  • I was trying to get this to run but it chops off the first character I'm not sure if its to do with the RTrim but thanks for all your replies guys I didnt expect it at all Cheers – user2181700 Apr 25 '13 at 08:44
  • @user2181700 **LOL** I just forgot the space. Just clicked on edited, and you could see my edited part. – Prahalad Gaggar Apr 25 '13 at 09:17