如何找到空表? PL / SQL与T-SQL

时间:2017-04-30 13:44:57

标签: sql-server

我想使用T-SQL列出空表。

我可以在PL / SQL中执行,如下所示,但我在T-SQL中遇到错误。

 -- Oracle PLSQL :: TABLES HAVING EMPTY DATA
 SET SERVEROUTPUT ON
DECLARE
  CNT PLS_INTEGER;
BEGIN
  FOR C IN ( SELECT TABLE_NAME FROM ALL_TABLES 
  WHERE OWNER='xxxx'   ) 
LOOP
    EXECUTE IMMEDIATE 'Select Count(*) From "' || C.TABLE_NAME || '" where rownum=1'
            INTO CNT;
    IF( CNT = 0 ) THEN
      DBMS_OUTPUT.PUT_LINE( C.TABLE_NAME );
    END IF;
  END LOOP;
END;

在T-SQL中获取错误

DECLARE @tblnme VARCHAR(128) 
DECLARE @CNT NUMERIC(5)
DECLARE @sqlstr NVARCHAR(200)

DECLARE c1 CURSOR FOR
SELECT name FROM sys.objects WHERE name IN ('t1','t2')

OPEN c1
FETCH c1 into @tblnme

WHILE @@FETCH_STATUS = 0
BEGIN
@sqlstr = N'SELECT TOP 1 @CNT =1  FROM' +@tblnme
exec sp_executesql @sqlstr 

IF @CNT IS NULL
print @tblnme+' is empty'

FETCH c1 into @tblnme
END

CLOSE c1
DEALLOCATE c1

错误:

Msg 102, Level 15, State 1, Line 13
Incorrect syntax near '@sqlstr'.
Msg 156, Level 15, State 1, Line 22
Incorrect syntax near the keyword 'CLOSE'.

请指教。 如果在T-SQL中可以实现任何其他最佳方式,请告诉我。 我希望通过检查最小1行是否存在列表空表。

提前致谢。

1 个答案:

答案 0 :(得分:4)

我建议使用SQL Server目录视图来避免扫描表以获取行数。尽管计数在事务上不一致,但它应该足以找到空表。这也可以让你避开光标。

SELECT
      QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' + QUOTENAME(t.name) AS TableName
FROM sys.tables AS t
WHERE NOT EXISTS(
    SELECT 1
    FROM sys.partitions AS p
    WHERE 
        p.object_id = t.object_id
        AND p.index_id IN(0,1)
        AND p.rows > 0
    )
ORDER BY TableName;

<强>更新

您的T-SQL游标脚本出错的原因是SQL字符串变量缺少SET命令。下面是一个修复示例,它还解决了不同模式中的对象和一些其他调整。

DECLARE
      @tblnme NVARCHAR(261) 
    , @CNT NUMERIC(5)
    , @sqlstr NVARCHAR(200);

DECLARE c1 CURSOR LOCAL FAST_FORWARD FOR
    SELECT QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' + QUOTENAME(name)
    FROM sys.tables
    WHERE name IN ('t1','t2');

OPEN c1;
FETCH c1 INTO @tblnme;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sqlstr = N'SELECT TOP 1 @CNT = 1  FROM ' + @tblnme;
    SET @CNT = NULL;
    EXEC sp_executesql @sqlstr, N'@CNT int OUTPUT', @CNT = @CNT OUTPUT;

    IF @CNT IS NULL
        PRINT @tblnme+' is empty';
    FETCH c1 INTO @tblnme;
END;

CLOSE c1;
DEALLOCATE c1;