SQL Server rebuilding indexes - script - sql

I'm using a script from #Namphibian, but I have some problems there.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
CREATE TABLE #FragmentedIndexes
(
DatabaseName SYSNAME,
SchemaName SYSNAME,
TableName SYSNAME,
IndexName SYSNAME,
[Fragmentation%] FLOAT
)
INSERT INTO #FragmentedIndexes
SELECT
DB_NAME(DB_ID()) AS DatabaseName,
ss.name AS SchemaName,
OBJECT_NAME (s.object_id) AS TableName,
i.name AS IndexName,
s.avg_fragmentation_in_percent AS [Fragmentation%]
FROM
sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'SAMPLED') s
INNER JOIN
sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
INNER JOIN
sys.objects o ON s.object_id = o.object_id
INNER JOIN
sys.schemas ss ON ss.[schema_id] = o.[schema_id]
WHERE
s.database_id = DB_ID()
AND i.index_id != 0
AND s.record_count > 0
AND o.is_ms_shipped = 0
DECLARE #RebuildIndexesSQL NVARCHAR(MAX)
SET #RebuildIndexesSQL = ''
SELECT
#RebuildIndexesSQL = #RebuildIndexesSQL +
CASE
WHEN [Fragmentation%] > 30
THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
+ QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName) + ' REBUILD;'
WHEN [Fragmentation%] > 10
THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
+ QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName) + ' REORGANIZE;'
END
FROM #FragmentedIndexes
WHERE [Fragmentation%] > 10
DECLARE #StartOffset INT
DECLARE #Length INT
SET #StartOffset = 0
SET #Length = 4000
WHILE (#StartOffset < LEN(#RebuildIndexesSQL))
BEGIN
PRINT SUBSTRING(#RebuildIndexesSQL, #StartOffset, #Length)
SET #StartOffset = #StartOffset + #Length
END
PRINT SUBSTRING(#RebuildIndexesSQL, #StartOffset, #Length)
EXECUTE sp_executesql #RebuildIndexesSQL
DROP TABLE #FragmentedIndexes
But instead of 'SAMPLED' I'm using 'DETAILED' but still some indexes are not rebuilt. I found a few indexes with the same value of fragmentation over 30% which still wasn't rebuilded or reorganized yet. That script is running every night last 4 days. My problem is I can't use Maintentance plans for this task.
Any ideas please?

According to this answer:
https://dba.stackexchange.com/questions/18372/why-index-rebuild-does-not-reduce-index-fragmentatation
You need to consider the number of page of your index to know if you do a rebuild
I will recommend to change your INSERT INTO SELECT to this
SELECT
DB_NAME(DB_ID()) AS DatabaseName,
ss.name AS SchemaName,
OBJECT_NAME (s.object_id) AS TableName,
i.name AS IndexName,
s.avg_fragmentation_in_percent AS [Fragmentation%],
page_count
FROM
sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'DETAILED') s
INNER JOIN
sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
INNER JOIN
sys.objects o ON s.object_id = o.object_id
INNER JOIN
sys.schemas ss ON ss.[schema_id] = o.[schema_id]
WHERE
s.database_id = DB_ID()
AND i.index_id != 0
AND s.record_count > 0
AND o.is_ms_shipped = 0
AND s.avg_fragmentation_in_percent > 0
AND page_count > 1000

Related

Rebuild or Reorganize indexes

I want to reorganize or rebuild indexes. I know the sql to perform this action on all indexes in a table is
alter index all on table_name reorganize;
But I only want to rebuild or reorganize if fragmentation percentage on each index is between a certain range. Is this possible to do?
Here is a procedure what I wrote
CREATE PROCEDURE dbo.ixRebuild #fillfactor int = 100, #Force bit = 0, #Schema varchar(255) = NULL, #Table varchar(255) = NULL, #PkOnly bit = 0
AS
/*
* ixRebuild
* Rebuild all indices in a database.
* Indices with >30% fragmentation are rebuilt.
* Indices with >6% fragmentation are just reorganised.
*
* The default fill factor is 100%.
*
* Required permissions are:
* GRANT VIEW DATABASE STATE TO <user>
* GRANT ALTER TO <user>
* GRANT EXEC ON ixRebuild TO <user>
*
* Created 17/9/08 by rwb.
*/
BEGIN
DECLARE #db int
DECLARE #tab varchar(256)
DECLARE #ix int
DECLARE #ixName varchar(256)
DECLARE #frag float
DECLARE #cmd varchar(1024)
DECLARE #type int
DECLARE c CURSOR FAST_FORWARD FOR
SELECT DISTINCT s.database_id, s.index_id, i.name,
Convert(float, s.avg_fragmentation_in_percent),
ss.name + '.' + t.name AS tableName,
i.type
FROM sys.dm_db_index_physical_stats(Db_Id(), NULL, NULL, NULL, NULL) s
INNER JOIN sys.indexes i ON s.object_id = i.object_id AND s.index_id = i.index_id
INNER JOIN sys.tables t ON i.object_id = t.object_id
INNER JOIN sys.schemas ss ON t.schema_id = ss.schema_id
WHERE (#Schema IS NULL OR ss.name = #Schema)
AND (#Table IS NULL OR t.name = #Table)
AND (#PkOnly = 0 OR i.is_primary_key = 1)
AND (
#Force = 1
OR (
avg_fragmentation_in_percent > 6
AND page_count > 100 -- rebuilding small indices does nothing
AND i.name IS NOT NULL -- for tables with no PK
)
)
-- DISTINCT because ys.dm_db_index_physical_stats
-- contains a row for each part of a partitioned index on a partitioned table.
OPEN c
FETCH NEXT FROM c INTO #db, #ix, #ixName, #frag, #tab, #type
WHILE ##Fetch_Status = 0
BEGIN
PRINT Db_Name( #db ) + ' / ' + #tab + ' / ' + #ixName + ' ' + Cast(#frag as varchar(16))
SET #cmd = ''
IF #frag < 10.0 AND #Force = 0
BEGIN
SET #cmd = 'ALTER INDEX ' + #ixName + ' ON ' + #tab + ' REORGANIZE'
END
ELSE
BEGIN
SET #cmd = 'ALTER INDEX ' + #ixName + ' ON ' + #tab +
CASE
WHEN #type IN (1, 2) THEN ' REBUILD WITH (FILLFACTOR = ' + Cast(#fillfactor AS varchar(4)) + ')'
ELSE ''
END
END
RAISERROR(#cmd, 0, 1) WITH NOWAIT;
EXEC (#cmd)
FETCH NEXT FROM c INTO #db, #ix, #ixName, #frag, #tab, #type
END
CLOSE c
DEALLOCATE c
END
Generally rebuilding all indexes of a table is a bad idea, because some can have no fragmentation, while some other can be horribly bloated !
Rebuiliding index is a heavy process and is blocking the access of the table the time to do so, except in ONLINE mode available only with the Enterprise version.
So you need to rebuild only under certains circumstances... Authors (which I think due to my old age in RDBMS, I am a part of them...) agree to say that small tables don't care and a percentage of fragmentation under 30 does not matter.
I alway add some complexity over these ideas, with another point : "big" rows of table or indexes (1600 bytes is a max for an index) will appear always to be fragmented, but are not... This because evaluating a frag percent take in account a percent of free space on a page and with a 8 Kb page, a natural no-recoverable space will stay inside the page (20% max for an index and 49 % max for a table).
So a good practice is to mix all those considerations to build a proper code to rebuild or defrag all objects includes in your database.
As an example, a short code to do so, can be :
DECLARE #SQL NVARCHAR(max) = N'';
SELECT #SQL = #SQL + CASE WHEN i.name IS NULL
THEN N'ALTER TABLE [' + s.name + '].[' + o.name + '] REBUILD;'
WHEN avg_fragmentation_in_percent > 30
THEN N'ALTER INDEX [' + i.name + '] ON [' + s.name + '].[' + o.name + '] REBUILD;'
ELSE N'ALTER INDEX [' + i.name + '] ON [' + s.name + '].[' + o.name + '] REORGANIZE;'
END
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) AS ips
JOIN sys.objects AS o ON ips.object_id = o.object_id
JOIN sys.schemas AS s ON o.schema_id = s.schema_id
JOIN sys.indexes AS i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.page_count > 64 AND avg_fragmentation_in_percent > 10;
EXEC (#SQL);

How to list all indexes and index related objects in all databases (SQL Server) using cursor

I wanted to list all index and index related objects in all of my databases (in my case 48) and decided to use cursor. I have found a code on stack overflow that does exactly the same thing for a given one database but modified to use cursor so I can have the same info fol all all databases.The problem is the code seems okay but when i run it gives me error.How do i fix this code and make it run? Thanks
-- SQL query to collect all indexes and related objects
-- instance level from multiple databases
DECLARE #db_nm VARCHAR(250), #sql NVARCHAR(1000)
DECLARE #results TABLE
(
[database_name] sysname,
[table_view] sysname,
[object_type] sysname,
[constraint_type] sysname,
[constraint_name] sysname,
[columns] sysname,
[index_name] sysname,
[index_type] sysname
);
DECLARE db CURSOR LOCAL FAST_FORWARD FOR
SELECT db.name
FROM master.sys.databases AS db
WHERE db.name NOT IN ('master', 'tempdb', 'model', 'msdb')
AND db.state_desc = 'ONLINE' --system db you're probably not looking for info in
OPEN db ;
FETCH NEXT FROM db INTO #db_nm;
WHILE ##fetch_status = 0
BEGIN
-- select * from sys.objects t
-- select schema_name(t.schema_id) + '.' + t.[name] as table_view from ---sys.objects t
SET #sql= 'select ''' + #db_nm + ''' AS [database_name], schema_name(t.schema_id) + t.[name] as [table_view],
case when t.[type] = 'U' Then 'Table'
case when t.[type] = 'V' then 'View'
end as [object_type],
case when c.[type] = 'PK' then 'Primary key'
when c.[type] = 'UQ' then 'Unique constraint'
when i.[type] = 1 then 'Unique clustered index'
when i.type = 2 then 'Unique index'
end as [constraint_type],
c.[name] as [constraint_name],
substring(column_names, 1, len(column_names)-1) as [columns],
i.[name] as [index_name],
case when i.[type] = 1 then 'Clustered index'
when i.type = 2 then 'Index'
end as [index_type]
from [' + #db_nm + '].sys.objects t
left outer join [' + #db_nm + '].sys.indexes i
on t.object_id = i.object_id
left outer join [' + #db_nm + '].sys.key_constraints c
on i.object_id = c.parent_object_id
and i.index_id = c.unique_index_id
cross apply (select col.[name] + ', '
from [' + #db_nm + '].sys.index_columns ic
inner join [' + #db_nm + '].sys.columns col
on ic.object_id = col.object_id
and ic.column_id = col.column_id
where ic.object_id = t.object_id
and ic.index_id = i.index_id
order by col.column_id
for xml path ('') ) D (column_names)
where is_unique = 1
and t.is_ms_shipped <> 1
order by schema_name(t.schema_id) + '.' + t.[name]';
INSERT INTO #results
EXEC (#sql)
FETCH NEXT FROM db INTO #db_nm;
END;
CLOSE db;
DEALLOCATE db;
-- select * into #temp from #results
SELECT * FROM #results;
--Here is the code that fits my need for one given database but want to loop it for all databases
SELECT
schema_name(t.schema_id) + '.' + t.[name] as table_view,
CASE WHEN t.[type] = 'U' THEN 'Table'
WHEN t.[type] = 'V' THEN 'View'
END AS [object_type],
CASE WHEN c.[type] = 'PK' THEN 'Primary key'
WHEN c.[type] = 'UQ' THEN 'Unique constraint'
WHEN i.[type] = 1 THEN 'Unique clustered index'
WHEN i.type = 2 THEN 'Unique index'
END AS constraint_type,
c.[name] AS constraint_name,
substring(column_names, 1, len(column_names)-1) as [columns],
i.[name] as index_name,
case when i.[type] = 1 then 'Clustered index'
when i.type = 2 then 'Index'
end as index_type
from sys.objects t
left outer join sys.indexes i
on t.object_id = i.object_id
left outer join sys.key_constraints c
on i.object_id = c.parent_object_id
and i.index_id = c.unique_index_id
cross apply (select col.[name] + ', '
from sys.index_columns ic
inner join sys.columns col
on ic.object_id = col.object_id
and ic.column_id = col.column_id
where ic.object_id = t.object_id
and ic.index_id = i.index_id
order by col.column_id
for xml path ('') ) D (column_names)
where is_unique = 1
and t.is_ms_shipped <> 1
order by schema_name(t.schema_id) + '.' + t.[name]

Query to find Size for each table By Filtering Rows

The Following Code will display the Size of each table in database
USE DatabaseName
GO
CREATE TABLE #temp (
table_name SYSNAME
, row_count INT
, reserved_size VARCHAR(50)
, data_size VARCHAR(50)
, index_size VARCHAR(50)
, unused_size VARCHAR(50)
)
SET NOCOUNT ON
INSERT #temp
EXEC sp_MSforeachtable 'sp_spaceused ''?'''
SELECT a.table_name
, a.row_count
, COUNT(*) AS col_count
, a.data_size
FROM #temp a
INNER JOIN INFORMATION_SCHEMA.columns b ON a.table_name COLLATE database_default
= b.table_name COLLATE database_default
GROUP BY a.table_name
, a.row_count
, a.data_size
ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS INTEGER) DESC
DROP TABLE #temp
Is there any way to Find the Space of All table by filtering the Row.
Like I have Foreign Key Company ID In All Table would it be possible if i want to know the space Occupied by Company
---Example ---
Purchase Table :
P_ID P_Description P_Price P_CompanyID
------------------------------------------
1 Mobile 100 1
2 Laptop 2100 1
3 Table 50 2
Sale table:
S_ID s_Description S_Price S_CompanyID
------------------------------------------
1 Mobile 110 1
2 Laptop 2200 1
3 Table 100 2
OutPut table:
Table Size Company
---------------------------------
Purchase 1.5MB 1
Sale 1.5MB 1
Purchase 1MB 2
Sale 1MB 2
I have Found the solution as per my Requirement. Thanks to Devart Help.
DECLARE #tblNAME NVARCHAR(50) = ''
DECLARE #colNAME NVARCHAR(50) = ''
DECLARE #SQL NVARCHAR(MAX) = ''
DECLARE CUR CURSOR FOR
SELECT NAME
FROM SYS.TABLES
WHERE TYPE = 'U'
AND SCHEMA_ID = 1
AND name NOT LIKE 'tt_%'
OPEN CUR
FETCH NEXT FROM CUR INTO #tblNAME
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #colNAME= c.name
FROM sys.columns c,sys.objects o
WHERE c.[object_id] = o.[object_id]
AND c.name like '%_CompanyID' And o.name=#tblNAME
if #colNAME is null or #colNAME =''
begin
FETCH NEXT FROM CUR INTO #tblNAME
end
Else
Begin
-- PRINT #tblNAME
--Print '---'+ #colNAME
SELECT #SQL += '
IF OBJECT_ID(''tt_' + o.name + ''') IS NOT NULL
DROP TABLE [tt_' + o.name + ']
SELECT *
INTO [tt_' + o.name + ']
FROM ' + QUOTENAME(SCHEMA_NAME(o.[schema_id])) + '.' + QUOTENAME(o.name) + '
WHERE '+#colNAME+' =10' -- your condition
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.name NOT LIKE 'tt_%'
AND o.name LIKE #tblNAME
AND o.is_ms_shipped = 0
AND EXISTS(
SELECT *
FROM sys.columns c
WHERE c.[object_id] = o.[object_id]
AND c.name like '%_CompanyID' -- your column
)
Set #colNAME=null
FETCH NEXT FROM CUR INTO #tblNAME
end
END
CLOSE CUR
DEALLOCATE CUR
Print #SQL
EXEC sys.sp_executesql #SQL
SELECT REPLACE(o.name, 'tt_', '') as TableName, t.Size, t.Total_Rows, '1' as IsClient
FROM sys.objects o
JOIN (
SELECT
i.[object_id]
, size = SUM(a.total_pages) * 8. / 1024
, total_rows = SUM(CASE WHEN i.index_id IN (0, 1) AND a.[type] = 1 THEN p.[rows] END)
FROM sys.indexes i
JOIN sys.partitions p ON i.[object_id] = p.[object_id] AND i.index_id = p.index_id
JOIN sys.allocation_units a ON p.[partition_id] = a.container_id
GROUP BY i.[object_id]
) t ON o.[object_id] = t.[object_id]
WHERE o.name LIKE 'tt_%'
AND o.is_ms_shipped = 0
AND o.[type] = 'U'
ORDER BY t.size DESC
SET #SQL = ''
SELECT #SQL += '
DROP TABLE [' + o.name + ']'
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.name LIKE 'tt_%'
AND o.is_ms_shipped = 0
EXEC sys.sp_executesql #SQL

SQL Server 2014 Dynamic SQL

Please take a look at the code and help me on the last part, --put all together = fail !!!
I wanted to generate a string for executing sp_executesql but I'm getting an error at the end. I also tried open cursor but it error out too.
Basically I'm trying to get actual row count per column per table for all tables
because general rowcount want give you if new column added and populated.
USE AdventureWorks2014
GO
-- Create view to hold the dataset
Alter view vColumnSchema
AS
with myColumnName
As
(
Select TOP (100) PERCENT
GetDate() As create_date,
##SERVERNAME As Server_Name,
DB_Name() AS database_name,
c.[object_id],
s.name AS [schema_name],
t.name as table_name,
c.name as column_name,
p.rows AS NUM_ROWS,
c.[precision]
from sys.tables as t
INNER JOIN sys.columns as c with(nolock) on t.[object_id] = c.[object_id]
INNER JOIN sys.indexes AS i ON t.object_id = i.object_id
INNER JOIN sys.partitions AS p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.schemas AS s ON s.schema_id = t.schema_id
WHERE t.name NOT LIKE 'dt%'
AND i.object_id > 255
AND i.index_id <= 1
And s.name is not null
Order by s.name,
t.name
)
Select Top 100 percent
create_date,
Server_Name,
database_name,
[schema_name],
table_name,
column_name,
NUM_ROWS,
case when precision = 0 then
'Select Count('+column_name+')'+' from ' +[schema_name]+'.'+table_name+ ' where '+column_name+'<> '''' '
else
'Select Count(' +column_name+')'+' from ' +[schema_name]+ '.'+table_name+' where '+column_name+'> 0'
END as ColumnCount,
case when precision = 0
then ' <> '''' '
Else '> 0'
END As WhereClause
from myColumnName
Order by [schema_name],
table_name
GO
select * from vColumnSchema
where table_name = 'ProductCostHistory'
go
select * from Production.ProductCostHistory -- 395 records
--pick one record and test it = pass
Select Count(EndDate) from Production.ProductCostHistory where EndDate<> '' --200 records
GO
--test = pass on both whereClause
Declare #Column_name nvarchar(50) = 'EndDate'
Declare #Schema_Name nvarchar(20) = 'Production'
declare #table_name nvarchar(50) = 'ProductCostHistory'
declare #whereClause nvarchar(5) = '<> '''' '
declare #sqltext nvarchar(max) ='
select count('+#Column_name+') as ColumnCount from ' +#Schema_Name+'.'+#table_name+' where '+#Column_name+' '+#WhereClause+'
'
EXECUTE sp_executesql #sqltext
GO
--examine each column = pass
Declare #Column_name nvarchar(50) = 'select Column_name from vColumnSchema'
EXECUTE sp_executesql #Column_name
GO
Declare #schema_name nvarchar(50) = 'select schema_name from vColumnSchema'
EXECUTE sp_executesql #schema_name
GO
declare #table_name nvarchar(50) = 'select table_name from vColumnSchema'
EXECUTE sp_executesql #table_name
GO
declare #WhereClause nvarchar(50) = 'select WhereClause from vColumnSchema'
EXECUTE sp_executesql #WhereClause
GO
--put all together = fail !!!
declare #Column_name nvarchar(50) = 'select Column_name from vColumnSchema'
declare #schema_name nvarchar(50) = 'select schema_name from vColumnSchema'
declare #table_name nvarchar(50) = 'select table_name from vColumnSchema'
declare #WhereClause nvarchar(5) = 'select WhereClause from vColumnSchema';
declare #sqltext nvarchar(max) ='
select count('+#Column_name+') as ColumnCount from ' +#Schema_Name+'.'+#table_name+' where '+#Column_name+' '+#WhereClause+'
'
EXECUTE sp_executesql #sqltext
go
If you want the number of rows per column per table:
DECLARE #sql NVARCHAR(MAX) = '';
SELECT #sql = #sql +
N'SELECT '''
+ t.name + ''' AS TableName, '''
+ c.name + ''' AS ColName, COUNT(' + QUOTENAME(c.name) + ') AS [RowCount] FROM '
+ QUOTENAME(t.name) + ' UNION ALL' + CHAR(10)
FROM sys.tables t
INNER JOIN sys.columns c
ON c.object_id = t.object_id
WHERE
t.type = 'U'
AND c.system_type_id <> 35
SELECT #sql = LEFT(#sql, LEN(#sql) - 11)
PRINT #sql
EXECUTE sp_executesql #sql
Not Sure what your end game is But this might help and does not use dynamic sql ...
You can put the number of columns in your original query without a CTE
This puts the col count in the original select
Select TOP (100) PERCENT
GetDate() As create_date,
##SERVERNAME As Server_Name,
DB_Name() AS database_name,
c.[object_id],
s.name AS [schema_name],
t.name as table_name,
c.name as column_name,
p.rows AS NUM_ROWS,
c.[precision] ,
(Select COUNT(c2.object_id)
FROM sys.columns c2
INNER JOIN sys.tables t2 ON t2.object_id = c2.object_id
WHERE t2.object_id = t.object_id
GROUP BY c2.object_id) as ColCountThisTbl
from sys.tables as t
INNER JOIN sys.columns as c with(nolock) on t.[object_id] = c.[object_id]
INNER JOIN sys.indexes AS i ON t.object_id = i.object_id
INNER JOIN sys.partitions AS p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.schemas AS s ON s.schema_id = t.schema_id
WHERE t.name NOT LIKE 'dt%'
AND i.object_id > 255
AND i.index_id <= 1
And s.name is not null
Order by s.name,
t.name `enter code here`

How to count empty tables in database?

Is there any way to count tables with no rows in my database with using T-SQL statement?
There you go... using a derived table.
SELECT * FROM
(
SELECT
[TableName] = so.name,
[RowCount] = MAX(si.rows)
FROM
sysobjects so,
sysindexes si
WHERE
so.xtype = 'U'
AND
si.id = OBJECT_ID(so.name)
GROUP BY
so.name
) sub
WHERE sub.[RowCount] = 0
I use the following:
SELECT t.NAME AS TableName, sum(p.rows) as RowCounts
FROM sys.tables t
INNER JOIN sys.indexes i
ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p
ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE
i.name IS NULL AND i.index_id <= 1
GROUP BY
t.NAME, i.object_id, i.index_id, i.name
HAVING SUM(p.rows) = 0
from khtan # SQL Server Forums, this is used to drop all empty tables, maybe you could adapt it to output a count?
declare #name varchar(128), #sql nvarchar(2000), #i int
select #name = ''
while #name < (select max(name) from sysobjects where xtype = 'U')
begin
select #name = min(name) from sysobjects where xtype = 'U' and name > #name
select #sql = 'select #i = count(*) from [' + #name + ']'
exec sp_executesql #sql, N'#i int out', #i out
if #i = 0
begin
select #sql = 'drop table [' + #name + ']'
print #sql
-- unmask next to drop the table
-- exec (#sql)
end
end
I don't have SQLServer here but I could take a stab at it if you like.