简体   繁体   中英

SQL: How to build a select query with Table_Name and Pivoted Column_Name from Information Schema

I've written some SQL queries of queries that I later use in Cursors to run each line. They take advantage of Information_Schema,Table_Name,Column_name, which I recently just picked up how to do from forums. Below is an example of one Query I use to delete rows from multiple tables with a criteria. I've left out the cursor code as I'm only focused on trying to build the select query.

DECLARE @devCodeDELETE varchar(20);
SET @devCodeDELETE = '001e';

SELECT 'DELETE FROM ' + TABLE_NAME + ' WHERE devCode = '''+ @devCodeDELETE +''';'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME like 'DEV_%';

The above Outputs which is then run through cursor code:

DELETE FROM DEV_assembly WHERE devCode = '001e';
DELETE FROM DEV_comments WHERE devCode = '001e';
DELETE FROM DEV_costhistory WHERE devCode = '001e';
DELETE FROM DEV_dates WHERE devCode = '001e';
DELETE FROM DEV_master WHERE devCode = '001e';
etc...

This has been effective for building batch update queries against multiple tables, since all tables join with column "devCode".

I can't seem to figure out how to write a select query that will pivot (is it a pivot?) column names with it's source table, using Table_Name, Column_Name and Information_Schema. Not even sure if it is possible.

The output I'm trying to achieve for now would be :

table1 table1.c1 table1.c2 table1.c3, etc
table2 table2.c1 table2.c2 table2.c3, table2.c4, table2.c5,etc
table3 table3.c1 table3.c3 table2.c3, table2.c4,etc
etc....

I displayed each line with different numbers of columns to illustrate each tables having different number of columns. If I can get this far, I make the necessary changes to make each line into a query.

Any help would be much appreciated. Thanks in advance.

-UPDATE----

Thanks to the Brian from below I made edits pertaining to my schema:

declare @TableName as varchar(256)
declare @ColumnName as varchar(256)
declare @str as varchar(max)
declare @outstring as varchar(max)

select TABLE_NAME, COLUMN_NAME 
into #temp
from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'DEV_%' AND COLUMN_NAME <> 'devCode' AND COLUMN_NAME NOT LIKE 'ID%'

select distinct TABLE_NAME, CONVERT(varchar(max),'') outstring 
into #tempout
from #temp

Declare TableNames cursor FORWARD_ONLY FOR
select * from #tempout
for update of outstring

open TableNames

fetch Next From TableNames into @TableName, @outstring
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @outstring = ''
    SELECT @outstring = @outstring + ', ' + COLUMN_NAME
    FROM #temp
    WHERE TABLE_NAME = @TableName

    UPDATE #tempout 
    SET outstring = @outstring
    WHERE CURRENT OF TableNames 

    fetch Next From TableNames into @TableName, @ColumnName
END

close TableNames
deallocate TableNames

select 'INSERT INTO ' + TABLE_NAME + '(devCode' + outstring + ') SELECT ''newCode'',' + SUBSTRING(outstring,2,99999) +' FROM ' + TABLE_NAME + ' WHERE devCode = ''oldCode'';' from #tempout

And the output was as desired! That'll go into a another cursor to run each line.

INSERT INTO DEV_assembly(devCode, asmNote, asmUser) SELECT 'newCode', asmNote, asmUser FROM DEV_assembly WHERE devCode = 'oldCode';
INSERT INTO DEV_comments(devCode, comComment, comDate, comStatus, comExternal) SELECT 'newCode', comComment, comDate, comStatus, comExternal FROM DEV_comments WHERE devCode = 'oldCode';
INSERT INTO DEV_costhistory(devCode, costDate, costQuote, costFactory, costNote, costTimeStamp, costSelect) SELECT 'newCode', costDate, costQuote, costFactory, costNote, costTimeStamp, costSelect FROM DEV_costhistory WHERE devCode = 'oldCode';
INSERT INTO DEV_dates(devCode, datesRecord, datesNote, datesDue, datesStatus, datesComplete) SELECT 'newCode', datesRecord, datesNote, datesDue, datesStatus, datesComplete FROM DEV_dates WHERE devCode = 'oldCode';
INSERT INTO DEV_dimensions(devCode, dimNote, dimDimension) SELECT 'newCode', dimNote, dimDimension FROM DEV_dimensions WHERE devCode = 'oldCode';
etc....

You can't do a SQL pivot without knowing the columns in advance... unless you do some dynamic SQL. Even then the number of columns is fixed so you'd have an enormous list of columns, one for every column title in the entire database.

What you can do is run a cursor though all the tables to build up a string with all the columns you need... such as:

declare @TableName as varchar(256)
declare @ColumnName as varchar(256)
declare @str as varchar(max)
declare @outstring as varchar(max)

select TABLE_NAME, COLUMN_NAME 
into #temp
from INFORMATION_SCHEMA.COLUMNS

select distinct TABLE_NAME, CONVERT(varchar(max),'') outstring 
into #tempout
from #temp

Declare TableNames cursor FORWARD_ONLY FOR
select * from #tempout
for update of outstring

open TableNames

fetch Next From TableNames into @TableName, @outstring
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @outstring = ''
    SELECT @outstring = @outstring + ' ' + COLUMN_NAME
    FROM #temp
    WHERE TABLE_NAME = @TableName

    UPDATE #tempout 
    SET outstring = @outstring
    WHERE CURRENT OF TableNames 

    fetch Next From TableNames into @TableName, @ColumnName
END

close TableNames
deallocate TableNames

select * from #tempout

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM