I am looking to return a view name and all record ID's where billingAddress != shippingAddress to further review. I need to query all views in one database. This is my thought process and if their is a better way or faster way to write the query by all means help me out!
What I am stuck on is how to return the view name with the recordID?
Create Table #T (ID Int Identity Not Null, ViewNames VARCHAR(1000)
Create Table #2 (viewNames varchar(1000))
Insert Into #T (ViewNames)
Select '['+C.Table_Catalog+'].['+C.Table_Schema+'].['+C.Table_Name+']' TableName
FROM Information_Schema.Columns c
Join information_schema.Tables T on C.Table_Catalog = T.Table_Catalog
AND C.Table_Schema = T.Table_Schema
AND C.Table_Name = T.Table_Name
Where T.Table_Type = 'View'
Group By '['+C.Table_Catalog+'].['+C.Table_Schema+'].['+C.Table_Name+']'
---Now this is the piece that I am stuck on as I do not know how to insert the view name into the table as well on each iteration
Declare #N int, #Str nvarchar(2000), #viewname nvarchar(2000), #MaxID int
Set #N = 1
Select #MaxID = Max(ID)
From #T
While (#N<#MaxID)
Begin
Select #viewname= viewname
From #T
Set #Str = ' Insert Into #2(viewname)
Select Top 1 '''+#viewname+'''
From '+#viewname+'
where exists(Select recordID from '+#viewname+' where [shipaddress] != [billaddress] ) '
Exec sp_eecutesql #str
Set #N = #N + 1
End
Select * from #t
Try changing your dynamic query like this.
You said you wanted the view name, and record id, so you need to add a column to #2
SET #Str = 'INSERT INTO #2(viewname, recordid)
SELECT ''' + quotename(#viewname) + ''', recordID
FROM '+ quotename(#viewname) + '
WHERE [shipaddress] != [billaddress]'
EXEC sp_executesql #str
Unless you're sure of the object names, you should try and use quotename when building up dynamic SQL
You do have a problem in your logic though...
You are missing a where clause in the query that assigns the value to #viewname
Try this...
SELECT #viewname= viewname
FROM #T
WHERE ID = #N
I do not understand sql returns set of rows so your variable #viewname can not be assigned value row by row. By default your #viewname will be assigned last row of table T.
Related
I'm trying to build a stored procedure that will query multiple database depending on the databases required.
For example:
SP_Users takes a list of #DATABASES as parameters.
For each database it needs to run the same query and union the results together.
I believe a CTE could be my best bet so I have something like this at the moment.
SET #DATABASES = 'DB_1, DB_2' -- Two databases in a string listed
-- I have a split string function that will extract each database
SET #CURRENT_DB = 'DB_1'
WITH UsersCTE (Name, Email)
AS (SELECT Name, Email
FROM [#CURRENT_DB].[dbo].Users),
SELECT #DATABASE as DB, Name, Email
FROM UsersCTE
What I don't want to do is hard code the databases in the query. The steps I image are:
Split the parameter #DATABASES to extract and set the #CURRENT_DB Variable
Iterate through the query with a Recursive CTE until all the #DATABASES have been processed
Union all results together and return the data.
Not sure if this is the right approach to tackling this problem.
Using #databases:
As mentioned in the comments to your question, variables cant be used to dynamically select a database. Dynamic sql is indicated. You can start by building your template sql statement:
declare #sql nvarchar(max) =
'union all ' +
'select ''#db'' as db, name, email ' +
'from [#db].dbo.users ';
Since you have sql server 2016, you can split using the string_split function, with your #databases variable as input. This will result in a table with 'value' as the column name, which holds the database names.
Use the replace function to replace #db in the template with value. This will result in one sql statement for each database you passed into #databases. Then, concatenate the statements back together. Unfortunately, in version 2016, there's no built in function to do that. So we have to use the famous for xml trick to join the statements, then we use .value to convert it to a string, and finally we use stuff to get rid of the leading union all statement.
Take the results of the concatenated output, and overwrite the #sql variable. It is ready to go at this point, so execute it.
I do all that is described in this code:
declare #databases nvarchar(max) = 'db_1,db_2';
set #sql = stuff(
(
select replace(#sql, '#db', value)
from string_split(#databases, ',')
for xml path(''), type
).value('.[1]', 'nvarchar(max)')
, 1, 9, '');
exec(#sql);
Untested, of course, but if you print instead of execute, it seems to give the proper sql statement for your needs.
Using msForEachDB:
Now, if you didn't want to have to know which databases had 'users', such as if you're in an environment where you have a different database for every client, you can use sp_msForEachDb and check the structure first to make sure it has a 'users' table with 'name' and 'email' columns. If so, execute the appropriate statement. If not, execute a dummy statement. I won't describe this one, I'll just give the code:
declare #aggregator table (
db sysname,
name int,
email nvarchar(255)
);
insert #aggregator
exec sp_msforeachdb '
declare #sql nvarchar(max) = ''select db = '''''''', name = '''''''', email = '''''''' where 1 = 2'';
select #sql = ''select db = ''''?'''', name, email from ['' + table_catalog + ''].dbo.users''
from [?].information_schema.columns
where table_schema = ''dbo''
and table_name = ''users''
and column_name in (''name'', ''email'')
group by table_catalog
having count(*) = 2
exec (#sql);
';
select *
from #aggregator
I took the valid advice from others here and went with this which works great for what I need:
I decided to use a loop to build the query up. Hope this helps someone else looking to do something similar.
CREATE PROCEDURE [dbo].[SP_Users](
#DATABASES VARCHAR(MAX) = NULL,
#PARAM1 VARCHAR(250),
#PARAM2 VARCHAR(250)
)
BEGIN
SET NOCOUNT ON;
--Local variables
DECLARE
#COUNTER INT = 0,
#SQL NVARCHAR(MAX) = '',
#CURRENTDB VARCHAR(50) = NULL,
#MAX INT = 0,
#ERRORMSG VARCHAR(MAX)
--Check we have databases entered
IF #DATABASES IS NULL
BEGIN
RAISERROR('ERROR: No Databases Provided,
Please Provide a list of databases to execute procedure. See stored procedure:
[SP_Users]', 16, 1)
RETURN
END
-- SET Number of iterations based on number of returned databases
SET #MAX = (SELECT COUNT(*) FROM
(SELECT ROW_NUMBER() OVER (ORDER BY i.value) AS RowNumber, i.value
FROM dbo.udf_SplitVariable(#DATABASES, ',') AS i)X)
-- Build SQL Statement
WHILE #COUNTER < #MAX
BEGIN
--Set the current database
SET #CURRENTDB = (SELECT X.Value FROM
(SELECT ROW_NUMBER() OVER (ORDER BY i.value) AS RowNumber, i.value
FROM dbo.udf_SplitVariable(#DATABASES, ',') AS i
ORDER BY RowNumber OFFSET #COUNTER
ROWS FETCH NEXT 1 ROWS ONLY) X);
SET #SQL = #SQL + N'
(
SELECT Name, Email
FROM [' + #CURRENTDB + '].[dbo].Users
WHERE
(Name = #PARAM1 OR #PARAM1 IS NULL)
(Email = #PARAM2 OR #PARAM2 IS NULL)
) '
+ N' UNION ALL '
END
PRINT #CURRENTDB
PRINT #SQL
SET #COUNTER = #COUNTER + 1
END
-- remove last N' UNION ALL '
IF LEN(#SQL) > 11
SET #SQL = LEFT(#SQL, LEN(#SQL) - 11)
EXEC sp_executesql #SQL, N'#CURRENTDB VARCHAR(50),
#PARAM1 VARCHAR(250),
#PARAM2 VARCHAR(250)',
#CURRENTDB,
#PARAM1 ,
#PARAM2
END
Split Variable Function
CREATE FUNCTION [dbo].[udf_SplitVariable]
(
#List varchar(8000),
#SplitOn varchar(5) = ','
)
RETURNS #RtnValue TABLE
(
Id INT IDENTITY(1,1),
Value VARCHAR(8000)
)
AS
BEGIN
--Account for ticks
SET #List = (REPLACE(#List, '''', ''))
--Account for 'emptynull'
IF LTRIM(RTRIM(#List)) = 'emptynull'
BEGIN
SET #List = ''
END
--Loop through all of the items in the string and add records for each item
WHILE (CHARINDEX(#SplitOn,#List)>0)
BEGIN
INSERT INTO #RtnValue (value)
SELECT Value = LTRIM(RTRIM(SUBSTRING(#List, 1, CHARINDEX(#SplitOn, #List)-1)))
SET #List = SUBSTRING(#List, CHARINDEX(#SplitOn,#List) + LEN(#SplitOn), LEN(#List))
END
INSERT INTO #RtnValue (Value)
SELECT Value = LTRIM(RTRIM(#List))
RETURN
END
This question already has answers here:
A table name as a variable
(10 answers)
Closed 4 years ago.
I am trying to create tables dynamically using the information in another table.
For example there is a table (say table1) which has information about the list of tables to be created. I would like to use this table1 to dynamically create new tables using the schema St. and including _New def in the end of the name i.e. I would like to create a table 'St.TableA_New' instead of the table name 'TableA' in table1. Here is the code I used.
declare #table1 table(idx int identity(1,1), table_name varchar(50))
insert into #table1 (table_name)
select'TableA' union
select'TableB' union
select'TableC'
DECLARE #COUNT INT = 1;
WHILE #COUNT <= (select count(*) from #table1)
BEGIN
Declare #table_name varchar(200) = (select table_name from #table1 where idx=#COUNT);
Declare #new_table varchar(50) = 'St.+'#table_name+'_New';
IF OBJECT_ID(#new_table) IS NOT NULL
DROP TABLE #new_table;
CREATE TABLE #new_table
WITH
(
DISTRIBUTION = ROUND_ROBIN,
HEAP
)
AS
SELECT *
FROM [Ext].[#table_name]
OPTION (LABEL = '');
SET #COUNT = #COUNT + 1
END;
The error says 'incorrect syntax near '#newtable.' Expecting '.',ID,IF,or QUOTED_ID' at the 'DROP TABLE #new_table;' line. What should I do to create all the tables dynamically using the names from 'table1' table?
You can use sp_executesql to do this. Just undo the comment below. You may also need to add code for the schema name.
declare #table1 table(idx int identity(1,1), table_name varchar(50))
insert into #table1 (table_name) values ('TableA'), ('TableB'), ('TableC');
Declare #table_name varchar(200)
, #new_table varchar(50)
, #sql nvarchar(1000);
DECLARE #COUNT INT = 1;
WHILE #COUNT <= (select count(*) from #table1)
BEGIN
select #table_name = table_name from #table1 where idx=#COUNT;
set #new_table = #table_name + '_New';
set #sql = concat('drop table if exists ', quotename(#new_table), ';');
set #sql = #sql + 'CREATE TABLE ' + quotename(#new_table) + ' WITH(DISTRIBUTION = ROUND_ROBIN, HEAP) AS SELECT * FROM ' + quotename(#table_name) + ' OPTION (LABEL = '''')';
print #sql;
--exec sys.sp_executesql #sql;
SET #COUNT = #COUNT + 1
END;
The question is quite extensive, please bear with me. I have a single mapping table with the following structure:
This particular table is used in the process of generating a hierarchy. The order and position of the columns in the table indicate the order of hierarchy (Organization, Category, Continent, Country.. etc.) Each entity in this hierarchy has a related table with associated Id and Name. For example, there is a Country table with CountryId and CountryName. Note that since the MappingTable's values are all nullable there are no foreign key constraints.
I want to generate a procedure that will do the following:
Based on conditions provided, retrieve values of the next entity in the hierarchy. For example, if the OrganizationId and CategoryId are given, the values of ContinentId that satisfy said condition need to be retrieved.
Also, if the value of ContinentId is NULL, then the values of CountryId need to be retrieved. Here, given the condition OrganizationId = 1 and CategoryId = 1 the procedure should return the list of RegionId.
In addition to retrieving the RegionId, the corresponding RegionName should be retrieved from the Region Table.
So far, the procedure looks something like this - just a few things to explain here.
ALTER PROCEDURE [dbo].[GetHierarchy]
(
#MappingTableName VARCHAR(30),
#Position VARCHAR(5),
-- Given in the form of Key-value pairs 'OrganizationId:1,CategoryId:1'
#InputData VARCHAR(MAX),
#Separator CHAR(1),
#KeyValueSeperator CHAR(1)
)
AS
BEGIN
DECLARE #Sql NVARCHAR(MAX)
DECLARE #Result NVARCHAR(MAX)
DECLARE #Sql1 NVARCHAR(MAX);
DECLARE #TableName NVARCHAR(30)
DECLARE #Exists bit
SELECT #TableName = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #MappingTableName AND ORDINAL_POSITION = #position
SET #TableName = SUBSTRING(#TableName,0,LEN(#TableName) - 1)
-- Returns a dynamic query like "SELECT ContinentId from Continent WHERE OrganizationId = 1 and CategoryId = 1".
SELECT #Sql = [dbo].[KeyValuePairs](#TableName, #InputData, #Separator, #KeyValueSeperator)
SET #Sql1 = N'SET #Exists = CASE WHEN EXISTS(' + #Sql + N' AND ' + #TableName + N'Id IS NOT NULL) THEN 1 ELSE 0 END'
PRINT #Sql
EXEC sp_executesql #Sql1,
N'#Exists bit OUTPUT',
#Exists = #Exists OUTPUT
IF(#Exists = 1)
BEGIN
SET #Sql1 = 'SELECT ' + #TableName + 'Id, ' + #TableName + 'Name FROM '+ #TableName+' WHERE ' + #TableName +'Id IN (' + #Sql + ')';
PRINT #Sql1
EXECUTE sp_executesql #SQL1
END
ELSE
BEGIN
--PRINT 'NOT EXISTS'
DECLARE #nextPosition INT
SELECT #nextPosition = CAST(#position AS INT)
SET #nextPosition = #nextPosition + 1
SET #Position = CONVERT(VARCHAR(5), CAST(#position AS INT))
EXEC [dbo].[GetHierarchy] #MappingTableName, #Position, #InputData, #Separator, #KeyValueSeperator
END
END
The logic of this procedure is such that, I get the name of the column at a particular position (based on the conditions here, it is Continent) and generate the dynamic query to retrieve the next column's values based on the condition of the input condition (I am using a separate function to do this for me).
Once retrieved, I run the query to check if it returns any rows. If the query returns rows, then I retrieve the corresponding ContinentName from the Continent table. If no rows are returns, I recursively call the procedure again with the next position as the input.
On the business side of things, it seems like a two step process. But, as a procedure it is quite complex, extensive and - not to mention, recursive. Is there an easier way to do this? I am not familiar with CTEs - can the same logic be implemented using CTEs?
This is quite similar to what is asked here: Working with a dynamic hierarchy SQL Server
Might be the little lengthy approach. Try this
DECLARE #T TABLE
(
SeqNo INT IDENTITY(1,1),
CatId INT,
Country INT,
StateId INT,
DistId INT
)
DECLARE #State TABLE
(
StateId INT,
StateNm VARCHAR(20)
)
DECLARE #Country TABLE
(
CountryId INT,
CountryNm VARCHAR(20)
)
INSERT INTO #State
VALUES(3,'FL')
INSERT INTO #Country
VALUES(2,'USA')
INSERT INTO #T(CatId)
VALUES(1)
INSERT INTO #T(CatId,Country)
VALUES(1,2)
INSERT INTO #T(CatId,StateId)
VALUES(1,3)
;WITH CTE
AS
(
SELECT
*,
IdVal = COALESCE(Country,StateId,DistId),
IdCol = COALESCE('Country '+CAST(Country AS VARCHAR(50)),'StateId '+CAST(StateId AS VARCHAR(50)),'DistId '+CAST(DistId AS VARCHAR(50)))
FROM #T
WHERE CatId = 1
),C2
AS
(
SELECT
SeqNo,
CatId,
Country,
StateId,
DistId,
IdVal,
IdCol = LTRIM(RTRIM(SUBSTRING(IdCol,1,CHARINDEX(' ',IdCol))))
FROM CTE
)
SELECT
C2.SeqNo,
C2.CatId,
S.StateNm,
C.CountryNm
FROM C2
LEFT JOIN #State S
ON C2.IdCol ='StateId'
AND C2.IdVal = S.StateId
LEFT JOIN #Country C
ON C2.IdCol ='Country '
AND C2.IdVal = c.CountryId
I am trying to log data changes in MS SQL with trigger. I want to create a new History table in every month. After I found the answer how to change table name Dynamically I can't access the DELETED and INSERTED tables anymore. It says invalid object name.
ALTER TRIGGER [dbo].[teszttablatrigger] ON [teszt].[dbo].[teszt] FOR DELETE, INSERT, UPDATE AS
declare #hist nvarchar(40)
set #hist='teszthistory_' + CAST(YEAR(getdate()) as NCHAR(4))+ '_' + (case when Month(GETDATE())<10 then '0' + CAST (Month(GETDATE()) as NCHAR(1))
when Month(GETDATE())>=10 then CAST (Month(GETDATE()) as NCHAR(2)) end)
declare #DynamicSql1 nvarchar(2000)
declare #DynamicSql2 nvarchar(2000)
set #DynamicSql1 = N'IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N''[History][dbo].[#hist]'')
AND OBJECTPROPERTY(id, N''IsUserTable'') = 1)
CREATE TABLE [History].[dbo].[#hist] ( kulcs int, szoveg varchar(40), modtip varchar(40), datum datetime default getdate())'
Exec sp_executesql #DynamicSql1, N'#hist nvarchar(40)', #hist=#hist
set #DynamicSql2 = N'INSERT INTO [History].[dbo].[#hist] (kulcs, szoveg, modtip)
SELECT kulcs, szoveg, ''delete''
FROM DELETED
INSERT INTO [History].[dbo].[#hist] (kulcs, szoveg, modtip)
SELECT kulcs, szoveg, ''insert''
FROM INSERTED'
Exec sp_executesql #DynamicSql2, N'#hist nvarchar(40)', #hist=#hist
Thanks for the answers in advance.
Dynamic sql is executed in his own scope, so you can't acces inserted/deleted objects.
You could write a SQLCLR trigger in C# look this example SQLCLR Trigger
but I think the easiest way is to use a temp table to write changes to, so the dynamic part is fixed.
Take a look:
DROP TRIGGER [test_history]
GO
CREATE TRIGGER [test_history] ON [test_table]
FOR DELETE, INSERT, UPDATE
AS
BEGIN
declare #date datetime = getdate()
declare #guid uniqueidentifier = newid()
declare #hist nvarchar(40)= 'test_history_' + CAST(YEAR(#date ) as VARCHAR(4))+ '_' + right('0' + CAST(Month(#date) as VARCHAR(2)), 2)
DECLARE #T1 BIT = 0
SELECT top 1 #T1 = 1 FROM sys.tables WHERE [TYPE] = 'U' AND name = 'test_history_9999_99'
IF #T1 = 1 TRUNCATE table test_history_9999_99
DECLARE #T2 BIT = 0
SELECT top 1 #T2 = 1 FROM sys.tables WHERE [TYPE] = 'U' AND name = #hist
IF #T1=0 BEGIN
SELECT ID, [desc], #date DATE_TIME, cast('delete' as varchar(20)) as operation, CAST(#guid AS varchar(64)) BATCH
INTO test_history_9999_99
FROM DELETED
END else begin
INSERT INTO test_history_9999_99
SELECT ID, [desc], #date, cast('delete' as varchar(20)) as operation, CAST(#guid AS varchar(64)) BATCH
FROM DELETED
end
INSERT INTO test_history_9999_99
SELECT ID, [desc], #date, cast('insert' as varchar(20)) as operation, CAST(#guid AS varchar(64)) BATCH
FROM inserted
IF #T2 = 0 BEGIN
EXEC sp_rename 'test_history_9999_99', #hist
END ELSE BEGIN
declare #DynamicSql nvarchar(2000)
SET #DynamicSql = 'INSERT INTO ' + #hist + ' SELECT * FROM test_history_9999_99;'
Exec sp_executesql #DynamicSql
END
END
My test_table contains only two columns ID and [Desc].
In the history tables I have added a DATETIME column with change date and a UNIQUEIDENTIFIER column so you can group all changes in a batch if you INSERT/UPDATE many records with a single operation
Tanks for the answer #MtwStark. Now it works, I can check if the table exists, and create it if not. And have eaccess to the DELETED and INSERTED tables.
I'm not sure, if in your solution I have to create the test_history_9999_99 table in advance. Because when I used your trigger I've got an error about column insertion (I didn't understand the error completly).
Now my code looks like this. I'm not sure if it can handle INSERT/UPDATE many records with a single operation. Probably I still need to insert this code for it? CAST(#guid AS varchar(64)) BATCH . I'm not sure what it really does, I have to look into it deeper.
CREATE TRIGGER [dbo].[teszttablatrigger] ON [teszt].[dbo].[teszt] FOR DELETE, INSERT, UPDATE AS
declare #hist nvarchar(40)
set #hist='teszthistory_' + CAST(YEAR(getdate()) as NCHAR(4))+ '_' + (case when Month(GETDATE())<10 then '0' + CAST (Month(GETDATE()) as NCHAR(1))
when Month(GETDATE())>=10 then CAST (Month(GETDATE()) as NCHAR(2)) end)
select * into #ins from inserted
select * into #del from deleted
declare #DynamicSql nvarchar(2000)
DECLARE #T2 BIT = 0
SELECT top 1 #T2 = 1 FROM sys.tables WHERE [TYPE] = 'U' AND name = #hist
if #T2=0 begin
set #DynamicSql = N'CREATE TABLE [' + #hist + '] ( kulcs int, szoveg varchar(40), modtip varchar(40), datum datetime default getdate())'
Exec sp_executesql #DynamicSql
end
set #DynamicSql = N'INSERT INTO ' + #hist + ' (kulcs, szoveg, modtip)
SELECT kulcs, szoveg, ''delete''
FROM #del
INSERT INTO ' + #hist + ' (kulcs, szoveg, modtip)
SELECT kulcs, szoveg, ''insert''
FROM #ins'
Exec sp_executesql #DynamicSql
Try refreshing intellisense. Ctrl+Shift+R see if that might help. Or do a database table refresh.
If you have SQL Server enterprise (check your version) Then better way will be to enable CDC.
https://msdn.microsoft.com/en-us/library/cc645937(v=sql.110).aspx
I am trying to write a windows service, which will send automatic emails. all the tables which require email sending have common columns 'templateid' and 'emailstatus'. I want to iterate through all the tables and get the tables which has column name 'templateid'.
Now that i have the list of tables with column name 'templateid' get the data from each table whose email status is 'false' and save it in a temporary table.
if 'table1' has 4 rows of data, the temporary table should have 4 rows. after iterating through the next table the row collection should be added to the same temporary table.
IF (SELECT object_id('TempDB..#TEMPTABLE')) IS NOT NULL
BEGIN
DROP TABLE #TEMPTABLE
END
CREATE TABLE #TEMPTABLE(
[ID] INTEGER IDENTITY(1,1) NOT NULL,
[TABLE_NAME] VARCHAR(1000)
)
INSERT INTO #TEMPTABLE(TABLE_NAME)
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'TEMPLATEID'
SELECT * FROM #TEMPTABLE
DECLARE #ROWCOUNT INT
SET #ROWCOUNT = (SELECT COUNT(ID) FROM #TEMPTABLE)
DECLARE #I INT
SET #I=1
WHILE(#I<=#ROWCOUNT)
BEGIN
DECLARE #TABLENAME VARCHAR(500)
SELECT #TABLENAME=TABLE_NAME FROM #TEMPTABLE WHERE ID=#I
EXEC('SELECT * FROM '+#TABLENAME)
SET #I=#I+1
END
i found the above query which is giving me all the tables. after that i am clueless how to proceed further as i am not good with sql server.
Not sure you are still looking for an answer but the following code will give you a temporary table with just the tables that have a column named 'templateid'. From here you would need a cursor as Tanner suggested to loop through each table and then insert records from each table (into your final target table) where email status = 'false'.
Here is the code that gets you the temp tables with columns named 'templateid' along with a sample for your cursor:
declare #max_tables int
declare #max_columns int
declare #sql nvarchar(400)
declare #x int
declare #y int
declare #table varchar(50)
declare #columns varchar(800)
declare #tablename varchar(100)
create table #c ([Table] varchar(50),[Columns] varchar(800))
select ROW_NUMBER() OVER(ORDER BY name) AS Row, name
into #table_list
from sys.objects
where type_desc = 'USER_TABLE'
order by name
set #max_tables = (select count(*) from sys.objects where type_desc = 'USER_TABLE')
set #y = 0
while #y < #max_tables
begin
set #y = #y + 1
set #table = (select name from #table_list where row = #y)
create table #t (c int)
set #sql = 'select count(*) as c from Information_schema.Columns where table_name = ''' + #table + ''''
insert into #t exec sp_executesql #sql
set #max_columns = (select top 1 c from #t)
DROP TABLE #t
set #x = 0
set #columns = ''
while #x < #max_columns
begin
set #x = #x + 1
set #columns = #columns + (select column_name from Information_schema.Columns where table_name = #table and ordinal_position = #x)
if #x < #max_columns set #columns = #columns + ', '
end
insert into #c select #table,#columns
end
select * into #tables from #c c
where c.Columns like '%templateid%'
declare my_cursor cursor for
select table from #t
open my_cursor
fetch next from my_cursor into #tablename
while ##fetch_status = 0
begin
--do something here to retrieve your data from each table and
--insert into target table
end
close my_cursor
deallocate my_cursor
DROP TABLE #c,#tables,#table_List