我有一张桌子#temp。 #temp中的数据是数据库中的表名。我希望只显示表有数据的表名。如何在不使用动态SQL的情况下执行此操作?
我的样本数据如下:
create TABLE #temp (Table_Name VARCHAR(50))
insert into #temp values ('#temp1')
,('#temp2')
,('#temp3')
,('#temp4')
create TABLE #temp1 (Col1 int)
insert into #temp1 values (1)
,(3)
,(4)
create TABLE #temp2 (Col1 int)
insert into #temp2 values (7)
,(9)
,(6)
create TABLE #temp3 (Col1 int)
create TABLE #temp4 (Col1 int)
我手动删除空白表,如何使用大量空白表的查询来执行此操作?
DELETE FROM #temp
WHERE Table_Name = '#temp3'
or Table_Name = '#temp4'
这是我想要的结果
DROP TABLE #temp
DROP TABLE #temp1
DROP TABLE #temp2
DROP TABLE #temp3
DROP TABLE #temp4
DECLARE @TABLE_NAME VARCHAR(50), @COMMAND VARCHAR(500), @COUNT INT, @COUNTT INT
DECLARE @CountResults TABLE (CountReturned INT)
create TABLE #TABLE_NAME (TABLE_NAME VARCHAR(50))
SELECT @COUNTT= COUNT(*) FROM #temp
WHILE @COUNTT > 0
BEGIN
SELECT TOP 1 @TABLE_NAME = Table_Name FROM #temp
SET @COMMAND = 'SELECT COUNT(*) FROM ' + @TABLE_NAME
INSERT @CountResults EXEC (@COMMAND)
SET @Count = (SELECT * FROM @CountResults)
BEGIN TRANSACTION
DELETE @CountResults
ROLLBACK TRANSACTION
IF(@Count > 0)
BEGIN
INSERT INTO #TABLE_NAME VALUES (@TABLE_NAME)
END
DELETE FROM #temp WHERE Table_Name = @TABLE_NAME
SELECT @COUNTT= COUNT(*) FROM #temp
END
SELECT * FROM #TABLE_NAME
答案 0 :(得分:0)
我不知道在没有查询该表的情况下确定表是否为空的任何方法,在您的情况下表示动态SQL。你的评论听起来好像你没关系,但正在寻找一种比使用循环更简洁的方法。这是(有限的)可能性:
declare @sql nvarchar(max);
select @sql =
-- coalesce() ensures that UNION ALL is inserted before every SELECT but the first.
coalesce(@sql + N' union all ', N'') +
-- Select each table name. Note that SQL Server allows table names that contain
-- single quotes. In this case (or in the case of plain old bad/malicious data in
-- #temp), we need to make sure those characters are enclosed within the string
-- literal we're building.
N'select ''' + replace(table_name, N'''', N'''''') +
-- Use EXISTS to make sure there are one or more records in the table.
N''' where exists (select 1 from ' + quotename(table_name) + N')'
from #temp;
exec sp_executesql @sql;
这将构建并执行如下所示的查询:
select '#temp1' where exists (select 1 from [#temp1])
union all
select '#temp2' where exists (select 1 from [#temp2])
union all
select '#temp3' where exists (select 1 from [#temp3])
union all
select '#temp4' where exists (select 1 from [#temp4])
这种方法有一些您应该注意的限制:
如果#temp
包含任何不是表或视图名称的字符串,查询将失败。通常情况下,我建议使用object_id()
或查询INFORMATION_SCHEMA.TABLES
来缓解此问题,但是您使用其他临时表的名称加载#temp
这一事实会使事情变得复杂。
如果#temp
包含明确命名表架构的表名,则查询也将失败,例如: dbo.Stuff
,因为quotename()
会将其呈现为[dbo.Stuff]
而不是[dbo].[Stuff]
。但是,如果省略quotename()
,如果table_name
包含空格或其他有问题的字符,则可能会出现错误和/或破坏行为的风险。
简而言之,如果您只是想要一些供个人使用的东西,并且可以对#temp
中的数据做出某些假设,那么上述内容应该有效。但是如果你想要在任何情况下都能正常安全地运行的东西,那么就需要做一些事情,这样即使你可以避免使用某种循环,这样做也不太可能使事情变得复杂。 / p>
答案 1 :(得分:0)
我有一个不使用动态sql的方法。它使用sysindexes表,根据微软的说法,他们可能会随心所欲地改变它。所以这可能不适合生产系统。但它可能是一个很好的起点。如果源表不是临时表,这也更容易一些,因为临时表的实际名称与用于创建它们的名称不匹配。
此脚本在SQL Server 2008 r2上为我工作。
-- drop table #MyTempTable;
Create table #MyTempTable(Table_Name varchar(50));
insert #MyTempTable values ('#MyTempTable2');
insert #MyTempTable values ('#MyTempTable3');
insert #MyTempTable values ('#MyTempTable4');
Create table #MyTempTable2 (Col1 int);
insert #MyTempTable2 values (1);
Create table #MyTempTable4 (Col1 int);
Create table #MyTempTable3 (Col1 int);
SELECT *
FROM #MyTempTable M1
JOIN tempdb.sys.tables T ON T.name LIKE (M1.Table_Name + '%')
JOIN [tempdb].[dbo].[sysindexes] S ON S.id = T.object_id
WHERE S.rowcnt > 0
这不是一个理想的解决方案,但它满足您的要求。如果您在自己的环境中使用它,它可能会让您深入了解实现更大目标的更好方法。祝你好运。
编辑:sysindexes表中的每个索引都有一个条目。或者在我的示例中,对于堆(没有索引)。因此,如果基表有多个索引,则需要稍微修改查询。也许将JOIN
和WHERE
条款更改为WHERE EXISTS SELECT * FROM [tempdb].[dbo].[sysindexes] S WHERE S.id = T.object_id AND S.rowcnt > 0
使用它进行游戏,您应该能够得到您所要求的位置。
编辑2:用sysobjects替换sys.tables。
SELECT *
FROM #MyTempTable M1
JOIN [tempdb].[dbo].[sysobjects] O ON O.name LIKE (M1.Table_Name + '%')
JOIN [tempdb].[dbo].[sysindexes] S ON S.id = O.id
WHERE S.rowcnt > 0
答案 2 :(得分:-1)
基于DeadZone的查询,以下适用于非临时表:
SELECT DISTINCT Table_Name
INTO #TABLE_NAME
FROM #Temp M1
JOIN [dbo].[sysobjects] O ON O.name LIKE (M1.Table_Name + '%')
JOIN [dbo].[sysindexes] S ON S.id = O.id
WHERE S.rowcnt > 0