How can I create tables in a loop? - sql

I was trying to create new tables using the identifier through a list.
DECLARE #Counter INT, #TableName NVARCHAR(20)
SET #Counter = 1
WHILE (#Counter <= 20)
BEGIN
SELECT #TableName = TableName FROM [dbo].[TableList] WHERE index = #Counter
SELECT * INTO [dbo].[#TableName.combine] FROM [dbo].[#TableName] t
LEFT JOIN [dbo].[cost] c ON t.x = c.y
SET #Counter = #Counter +1
END
And it keeps saying the object of [dbo].[#TableName] is invalid, but I already have [dbo].[#TableName] as a table.
I looked over the declare table variable, but [dbo].[#TableName] already existed in the database, how can I point to the table that I want?

You need to use dynamic SQL for this.
You can build one big query using STRING_AGG and then execute it
DECLARE #sql nvarchar(max);
SELECT #sql =
STRING_AGG(CAST('
SELECT *
INTO dbo.' + QUOTENAME(tl.TableName + '.combine') + '
FROM dbo.' + QUOTENAME(tl.TableName) + ' t
LEFT JOIN dbo.cost c ON t.x = c.y;
' AS nvarchar(max)), '
' )
FROM dbo.TableList tl;
EXEC sp_executesql #sql;

Related

Dynamic SQL - Use declared VARCHAR in SET SQL string

How to use the declared variable #CodeID inside the SQL string? When I run following statement I get the "Invalid object name (..)" error.
WHILE #FolderID <= #FolderMaxID
BEGIN
SELECT #Db = Db
FROM #Folders
WHERE ID = #FolderID
SET #Sql = N'
DECLARE #CodeID NVARCHAR(256)
SELECT TOP(1) #CodeID=CodeType
FROM ' + #Db + '.bla.Field
WHERE Name= ''Example''
SELECT DISTINCT C.Name
FROM ' + #Db + '.Document
INNER JOIN ' + #Db + '.bla.Code_#CodeID C ON D.ID = C.ID'
EXEC ( #Sql )
SET #FolderID = #FolderID + 1
END
It looks to me that you need two levels of dynamic SQL, with the first level inserting the database name (from #folders), and the second level inserting a constructed table name (based on the CodeType column of the database-local bla.Field table).
I do not know of any way to parameterize database names or table names using sp_executesql, so I'm sticking with build-up dynamic SQL and EXEC (). (If someone makes a case for preferring sp_executesql over EXEC when not useing parameters, then it may be worth the switch.)
Try something like:
WHILE #FolderID <= #FolderMaxID
BEGIN
SELECT #Db = Db
FROM #Folders
WHERE ID = #FolderID
SET #Sql = N'
DECLARE #CodeID NVARCHAR(256)
SELECT TOP(1) #CodeID=CodeType
FROM ' + QUOTENAME(#Db) + '.bla.Field
WHERE Name= ''Example''
DECLARE #Sql2 NVARCHAR(MAX) = N''
SELECT DISTINCT C.Name
FROM ' + QUOTENAME(#Db) + '.bla.Document D
INNER JOIN ' + QUOTENAME(#Db) + '.bla.'' + QUOTENAME(''Code_'' + #CodeID) + '' C ON D.ID = C.ID
''
EXEC #sql2
'
EXEC ( #Sql )
SET #FolderID = #FolderID + 1
END
This implements dynamic SQL within dynamic SQL. Doubled quotes in the outer sql template become single quotes in the inner sql. The original posted code seemed to be missing a schema qualifier and alias for the Document table, so I inserted them ("bla" and "D"). I also added QUOTENAME around the injected names as suggested by Larnu.
The first level of dynamic sql would generate something like:
SELECT TOP(1) #CodeID=CodeType
FROM [db1].bla.Field
WHERE Name= 'Example'
DECLARE #Sql2 NVARCHAR(MAX) = N'
SELECT DISTINCT C.Name
FROM [db1].bla.Document D
INNER JOIN [db1].bla.' + QUOTENAME('Code_' + #CodeID) + ' C ON D.ID = C.ID
'
EXEC #sql2
The second level would generate something like:
SELECT DISTINCT C.Name
FROM [db1].bla.Document D
INNER JOIN [db1].bla.[Code_Table1] C ON D.ID = C.ID
Note that each loop iteration will generate a separate result. If you wish to combine results, you will need to define a #temp table, insert the individual results into that table, and then select the combined results at the end of your script.
Note that I haven't tested the specific code above, so it might need some debugging (add "PRINT #sql2" before the EXEC) if it doesn't work straight out.
ADDENDUM
Per #trenton-ftw comments below, an out parameter can be used to capture the result of the first query so that it may be included in the second query without the need for nesting. Two executions are still required. Below is a revised example.
DECLARE #Folders TABLE (ID INT IDENTITY(1,1), Db sysname)
INSERT #Folders VALUES ('db1'), ('db2')
DECLARE #SearchName NVARCHAR(256) = 'Example'
DECLARE #Db sysname
DECLARE #Sql NVARCHAR(MAX)
DECLARE #CodeID NVARCHAR(256)
DECLARE #FolderMaxID INT = (SELECT MAX(ID) FROM #Folders)
DECLARE #FolderID INT = 1
WHILE #FolderID <= #FolderMaxID
BEGIN
SELECT #Db = Db
FROM #Folders
WHERE ID = #FolderID
SET #Sql = N'
SET #CodeID = #SearchName + ''-Test''
--SELECT TOP(1) #CodeID = CodeType
--FROM ' + QUOTENAME(#Db) + '.bla.Field
--WHERE Name = #SearchName'
PRINT #Sql
EXEC sp_executesql #Sql,
N'#SearchName NVARCHAR(256), #CodeID NVARCHAR(256) OUTPUT',
#SearchName, #CodeID OUTPUT
SET #Sql = N'
--SELECT DISTINCT C.Name
--FROM ' + QUOTENAME(#Db) + '.bla.Document D
-- INNER JOIN ' + QUOTENAME(#Db) + '.bla.' + QUOTENAME('Code_' + #CodeID) + ' C ON D.ID = C.ID'
PRINT #Sql
EXEC sp_executesql #sql
SET #FolderID = #FolderID + 1
END
For demo purposes, I also parameterized the search name as an input parameter and added some temporary code to make it stand-alone testable. A final version would uncomment the actual sql, and remove the print statements and the test #CodeID assignemnt.

How can I return a distinct count of a variable for all tables in my database?

I have a SQL database with 60+ tables, almost all of which are populated with a CLIENTID field. I want to count the number of unique client IDs in each table.
The results I'm looking for are:
TABLE_NAME; CLIENTID_COUNT
dbo.HISTORY; 650
dbo.VISITS; 596
dbo.SALES; 1053
...; ...
This seems like it should be so simple but I've been playing around with cursors for hours and can't figure this one out. Please help!
IF OBJECT_ID('tempdb..#temp_RESULTS') IS NOT NULL DROP TABLE #temp_RESULTS
CREATE TABLE #TEMP_RESULTS
(
TABLENAME VARCHAR(MAX),
CLIENTCNT BIGINT
)
DECLARE #TABLENAME VARCHAR(MAX)
DECLARE #command VARCHAR(MAX)
IF OBJECT_ID('tempdb..#temp_PROCESS') IS NOT NULL DROP TABLE #temp_PROCESS
SELECT * INTO #TEMP_PROCESS FROM sys.tables
WHILE EXISTS(SELECT * FROM [#TEMP_PROCESS])
BEGIN
SET #TABLENAME = (SELECT TOP 1 [NAME] FROM [#TEMP_PROCESS])
SET #command = ('SELECT ''' + #TABLENAME + ''', COUNT(DISTINCT CLIENTID) AS CLIENTCNT FROM ' + #TABLENAME)
SELECT #command
INSERT INTO #TEMP_RESULTS
EXEC(#command)
DELETE FROM [#TEMP_PROCESS] WHERE [NAME] = #TABLENAME
END
SELECT * FROM [#TEMP_RESULTS]
Assuming the column is exactly ClientId in every table, you should be able to use this as is:
DROP TABLE IF EXISTS #clientId
CREATE TABLE #clientId
(
TableName nvarchar(1000),
ClientIdCount bigint
)
DECLARE #TableName nvarchar(1000);
DECLARE #CurrentQuery nvarchar(2000);
DECLARE result_cursor CURSOR local fast_forward FOR
SELECT DISTINCT
'['+TABLE_SCHEMA + '].[' + TABLE_NAME + ']'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
COLUMN_NAME = 'ClientId'
OPEN result_cursor
FETCH NEXT FROM result_cursor into #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #CurrentQuery = 'SELECT ''' + #TableName + ''', COUNT(DISTINCT ClientId) FROM ' + #TableName
--print #CurrentQuery
INSERT INTO
#clientId
(
TableName,
ClientIdCount
)
EXEC(#CurrentQuery)
FETCH NEXT FROM result_cursor into #TableName
END
--end loop
--clean up
CLOSE result_cursor
DEALLOCATE result_cursor
GO
SELECT
*
FROM
#clientId
You could use dynamic sql.
This will read through your system tables, find those that have a ClientID column, and build the text of a query that's in the general shape of 'Select Count(DISTINCT ClientID)' from each table.
DECLARE #SQLQuery as nvarchar(max) = ''
------------------------------------
-- GET THE TABLES THAT HAVE A CLIENTID FROM SCHEMA
SELECT #SQLQuery = #SQLQuery + qryTxt FROM (
SELECT DISTINCT 'SELECT ''' + tables.name + ''', COUNT(DISTINCT CLIENTID) FROM ' + tables.name + ' UNION ' AS qryTxt
FROM sys.columns left join sys.tables on columns.object_id = tables.object_id where columns.name = CLIENTID AND isnull(tables.name, '') <> '') subquery
------------------------------------
-- REMOVE THE LAST 'UNION' KEYWORD FROM SQLQUERY
SET #SQLQuery = left(#sqlQuery, len(#sqlQuery) - 5)
------------------------------------
-- EXECUTE
execute sp_executesql #SQLQuery
I really dislike cursors and loops. Even though this is not going to be much difference for a performance perspective I like to share how you can leverage the system tables and dynamic sql to avoid using a cursor, while loop or temp tables for something like this.
This code is literally all you need to to do this.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'select TableName = ''' + t.name + ''', ClientID_Count = count(distinct clientID)
from ' + QUOTENAME(t.name) + ' UNION ALL '
from sys.tables t
join sys.columns c on c.object_id = t.object_id
where c.name = 'clientID'
select #SQL = left(#SQL, len(#SQL) - 10) --removes the last UNION ALL
select #SQL
--once your comfortable the dynamic sql is correct just uncomment the line below.
--exec sp_executesql #SQL
A similar pattern to other answers here, but this is how I would tackle it:
IF OBJECT_ID('#Tables', 'U') IS NOT NULL
DROP TABLE #Tables;
SELECT ID = IDENTITY(INT, 1, 1),
SchemaName = OBJECT_SCHEMA_NAME([object_id]),
TableName = OBJECT_NAME([object_id]),
ColumnName = name,
DistinctCount = 0
INTO #Tables
FROM sys.columns
WHERE name = 'CLIENTID';
DECLARE #ID INT = 1,
#MaxID INT = (SELECT MAX(ID) FROM #Tables);
WHILE #ID < #MaxID
BEGIN;
DECLARE #SQLCommand VARCHAR(MAX);
SELECT #SQLCommand = FORMATMESSAGE('
UPDATE #Tables SET DistinctCount = (
SELECT COUNT(DISTINCT %s) FROM %s.%s
)
WHERE ID = %i;',
QUOTENAME(ColumnName), QUOTENAME(SchemaName), QUOTENAME(TableName), ID)
FROM #Tables
WHERE ID = #ID;
EXEC (#SQLCommand);
SET #ID += 1;
END;
SELECT *
FROM #Tables;

How to increment column ordinal position in a while function?

Abstract: I have a table with multiple columns and I am trying to implement a while (loop) function to all the columns to pull out the average of each column.
I coded this to attribute a number to each column (to ease the possibility of an incremental method)
Declare #tablename as varchar(128)
Declare #column1 as varchar(128)
Delect #tablename = 'MOMENTUM_Results'
Select #column1 = sc.name
from sysobjects as so inner join syscolumns as sc on so.id = sc.id
where so.name = #tablename and sc.colid = 2
When I print this code it prints the name of the column based on the number I put from 1 to 122.
Code for the loop function:
WHILE ....
BEGIN
SET #SQL = 'SELECT AVG(MR.[' + #column1 + ']) From MOMENTUM_Quintile MQ
Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + #column1 + '] = 1'
END
But I definitely do not have a clue how to integrate this function into the loop so the function goes through all the columns one by one, therefore looking for some advice..
Thank you!
R.H.
Can you not just move your SELECT from sys.Columns into the body of your WHILE loop to get the one you're after? Something like this...
DECLARE #TABLENAME AS VARCHAR(128);
DECLARE #COLUMN1 AS VARCHAR(128);
DECLARE #COUNTER INT;
SET #TABLENAME = 'MOMENTUM_Results';
SET #COUNTER = 1;
WHILE ....
BEGIN
SELECT #COLUMN1 = C.Name
FROM sys.Columns C
WHERE OBJECT_NAME(C.object_id) = #TABLENAME
AND C.column_id = #COUNTER
;
SET #SQL = 'SELECT AVG(MR.[' + #COLUMN1 + ']) From MOMENTUM_Quintile MQ
Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + #COLUMN1 + '] = 1';
... Other Stuff ...
SET #COUNTER = #COUNTER + 1;
END
;
Maybe I didn't properly understand your question, but if you already have everything written out you could just change the placement to select the column names you want.
Of course you can also add additional conditions to make sure you're getting matched columns, or columns by name, or whatever...
EDIT:
You asked about inserting the resultant query into a table. If you already have a table with a column ready to receive the query, then the answer is simple... In the body of your WHILE loop, after retrieving the desired query, simply add an INSERT command:
WHILE ....
BEGIN
SELECT #COLUMN1 = C.Name
FROM sys.Columns C
WHERE OBJECT_NAME(C.object_id) = #TABLENAME
AND C.column_id = #COUNTER
;
SET #SQL = 'SELECT AVG(MR.[' + #COLUMN1 + ']) From MOMENTUM_Quintile MQ
Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + #COLUMN1 + '] = 1';
INSERT INTO <mytable> (<querycolumn>) VALUES (#SQL);
... Other Stuff ...
SET #COUNTER = #COUNTER + 1;
If you need to create the table, you can do that in the head of the script, before declaring anything else, and do the same thing during the WHILE:
DECLARE #TABLENAME AS VARCHAR(128);
DECLARE #COLUMN1 AS VARCHAR(128);
DECLARE #COUNTER INT;
SET #TABLENAME = 'MOMENTUM_Results';
SET #COUNTER = 1;
CREATE TABLE <mytable> (<optional_column1>,<optional_column2>,<querycolumn>);
....
WHILE ....
BEGIN
SELECT #COLUMN1 = C.Name
FROM sys.Columns C
WHERE OBJECT_NAME(C.object_id) = #TABLENAME
AND C.column_id = #COUNTER
;
SET #SQL = 'SELECT AVG(MR.[' + #COLUMN1 + ']) From MOMENTUM_Quintile MQ
Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + #COLUMN1 + '] = 1';
INSERT INTO <mytable> (<querycolumn>) VALUES (#SQL);
... Other Stuff ...
SET #COUNTER = #COUNTER + 1;
First get all the column names in that table into a temporary table(#temp)
Get the count of all columns(#count_of_columns) in that temptable.
declare a variable #count=1
Declare while loop as While(#count<=#count_of_columns)
--> fetch the column name one after another inside this while loop using the following query
SET #column1=(select top 1 column1 from
(select Row_number()over (order by column1) as r_n_n, column1
from #temp) aa
where r_n_n >=#Count)
--> use your actual code here
--> increment the #count variable
set #count = #count + 1
Don't use loops or cursors, if you can avoid them. The devil of procedural thinking is pulling you away from the light of set based approaches deep into pain and misery!
I know the column names in advance, I just did it to ease the way I would loop through each column
NO! This is not easing the way but punishing the poor engine :-)
Is it this you are looking for?
CREATE TABLE dbo.Test(ID INT, VAl1 DECIMAL(14,4), Val2 DECIMAL(14,4), Val3 DECIMAL(14,4));
GO
INSERT INTO dbo.Test VALUES(1,1,10,100),(2,2,20,200),(3,3,30,300);
GO
SELECT AVG(Val1) AS Avg1,AVG(Val2) AS Avg2,AVG(Val3) AS Avg3
FROM dbo.Test;
GO
DROP TABLE dbo.Test;
The result
Avg1 Avg2 Avg3
2.000000 20.000000 200.000000
UPDATE
If you just want to be lazy and avoid typing, you might try something like this:
SELECT ',AVG(' + COLUMN_NAME + ') AS ' + QUOTENAME('AVG_' + COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='dbo' AND TABLE_NAME='Test'
FOR XML PATH('')
The result
,AVG(ID) AS [AVG_ID],AVG(VAl1) AS [AVG_VAl1],AVG(Val2) AS [AVG_Val2],AVG(Val3) AS [AVG_Val3]
With this trick you can build your hard coded statement quite easily :-)

How to avoid the cursor and what is the other way?

I am using the cursor in my stored procedure; I am hoping to remove the cursor from my SP. Please help me come up with a solution for how to avoid the cursor statement to normal update statement with dynamic.
Example Below:
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'Test'(variable) and age = 18(variable)
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'kumar'(variable) and age = 19(variable)
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'babu'(variable) and age = 30(variable)
This is how my cursor will work. 300 Combination dynamically pick the data from table and update into the main table
I am trying to take out the cursor, and update statement should work similar to this, instead of writing 300 update statements, I want to write one update where all the 300 combinations should execute.
Below is my code which needs this solution:
BEGIN
DECLARE #Type VARCHAR(100)
DECLARE #TargetColumn VARCHAR(100)
DECLARE #SourceColumn VARCHAR(100)
DECLARE #SQL varchar(max)
DECLARE a_cursor CURSOR STATIC
FOR
SELECT [Type],[SourceColumn],[TargetColumn] FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn]
OPEN a_cursor
FETCH NEXT FROM a_cursor INTO #Type,#SourceColumn,#TargetColumn
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'UPDATE GCT SET GCT.' + #TargetColumn + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + #SourceColumn + ' = map.[SourceValue]
where map.[Type]=''' + #Type + ''' and map.SourceColumn=''' + #SourceColumn+ ''''
Exec (#SQL)
PRINT #SQL
FETCH NEXT FROM a_cursor INTO #Type,#SourceColumn,#TargetColumn
END
CLOSE a_cursor
DEALLOCATE a_cursor
END
Rather than use an explicit cursor or a cursor cleverly disguised as a while loop, I prefer row concatenation operations for this type of problem.
DECLARE #cmd NVARCHAR(MAX) = N'';
SELECT #cmd += N'
UPDATE GCT
SET GCT.' + QUOTENAME(TargetColumn) + ' = map.TargetValue
FROM dbo.EdsMap AS map
INNER JOIN dbo.Table AS GCT
ON GCT.' + QUOTENAME(SourceColumn) + ' = map.SourceValue
WHERE map.[Type] = ''' + [Type] + '''
AND map.SourceColumn = ''' + [SourceColumn]+ ''';'
FROM ref.tblEdsMap
GROUP BY [Type], SourceColumn, TargetColumn;
EXEC sp_executesql #sql;
When I've done these in the past, I usually make up a transaction to encompass every update that's needed. Something like this:
CREATE TABLE #targets ([Type] VARCHAR(255),[SourceColumn] VARCHAR(255),[TargetColumn] VARCHAR(255));
INSERT INTO #targets
( [Type], [SourceColumn], [TargetColumn] )
SELECT [Type],[SourceColumn],[TargetColumn] FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn];
DECLARE #sql VARCHAR(MAX);
SET #sql = 'BEGIN TRAN' + CHAR(10) + CHAR(13);
SELECT #sql = #sql +
'UPDATE GCT SET GCT.' + [TargetColumn] + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + [SourceColumn] + ' = map.[SourceValue]
where map.[Type]=''' + [Type] + ''' and map.SourceColumn=''' + [SourceColumn]+ ''';' + CHAR(10) + CHAR(13)
FROM #targets
SELECT #sql = #sql + 'COMMIT TRAN'
PRINT #sql
Exec (#SQL)
The update statements are still the same, i.e., you get one update per combination. But now you're running as one transaction batch. You could potentially be fancier with the dynamic SQL, so that you had just one update statement, but in my experience, it's too easy to get bad updates that way.
Doing it this way may not be any faster than a cursor. You'd have to test to be sure. With the examples where I've used this approach, it has generally been a faster approach.
Try using a table variable along with a WHILE loop instead, like so:
BEGIN
DECLARE #Type VARCHAR(100)
DECLARE #TargetColumn VARCHAR(100)
DECLARE #SourceColumn VARCHAR(100)
DECLARE #SQL varchar(max)
DECLARE #SomeTable TABLE
(
ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
Type varchar(100),
SourceColumn varchar(100),
TargetColumn varchar(100)
)
DECLARE #Count int, #Max int
INSERT INTO #SomeTable (Type, SourceColumn, TargetColumn)
SELECT [Type],[SourceColumn],[TargetColumn]
FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn]
SELECT #Count = 1, #Max = COUNT(ID)
FROM #SomeTable
WHILE #Count <= #Max
BEGIN
SELECT
#Type = Type,
#SourceColumn = SourceColumn,
#TargetColumn = TargetColumn
FROM #SomeTable
WHERE ID = #Count
-- Your code
SET #SQL = 'UPDATE GCT SET GCT.' + #TargetColumn + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + #SourceColumn + ' = map.[SourceValue]
where map.[Type]=''' + #Type + ''' and map.SourceColumn=''' + #SourceColumn+ ''''
Exec (#SQL)
PRINT #SQL
SET #Count = #Count + 1
END -- while
END

Drop tables that starts with specific characters

I have multiple table names like g_str_a , g_str_ab , g_str_abc . I would like to drop all those tables that start with g_str on SQL Server 2008.
Will DROP Tables like 'g_str' help?
Please help me with the script.
SELECT
'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + ';'
FROM sys.tables
WHERE name LIKE 'g\_str%' ESCAPE '\'
Then review the script and run it.
You can also concatenate the result into a single string and execute with EXEC if you need an entirely automated solution.
You could use dynamic SQL:
DECLARE #SQL NVARCHAR(MAX) = '';
SELECT #SQL = #SQL + 'DROP TABLE ' + QUOTENAME(SCHEMA_NAME([Schema_ID])) + '.' + QUOTENAME([name]) + ';'
FROM sys.tables
WHERE Name LIKE 'g\_str%' ESCAPE('\');
EXECUTE SP_EXECUTESQL #SQL;
Following query will delete tables automatically:
BEGIN TRANSACTION
DECLARE #tmpTablesToDelete TABLE (
RowNumber INT PRIMARY KEY
,Query NVARCHAR(MAX)
)
INSERT INTO
#tmpTablesToDelete
SELECT
RowNumber = ROW_NUMBER() OVER (ORDER BY (SELECT (0)))
,'DROP TABLE '+schemas.name+'.'+objects.name AS Query
FROM
sys.objects
INNER JOIN
sys.schemas
ON
schemas.schema_id = objects.schema_id
WHERE
type = 'U' AND objects.name like 'g_str%'
DECLARE #Counter INT
SELECT #Counter = MAX(RowNumber) FROM #tmpTablesToDelete
WHILE(#Counter > 0) BEGIN
DECLARE #Query NVARCHAR(MAX)
SELECT #Query = Query FROM #tmpTablesToDelete WHERE RowNumber = #Counter
PRINT #Query
EXEC sp_executesql #statement = #Query
SET #Counter = #Counter - 1
END
COMMIT TRANSACTION