如何使用游标从多个表中获取信息?

时间:2015-02-17 09:11:59

标签: sql cursor teradata

我有一个查询,它返回多个表,类似于:

SELECT TableName, DatabaseName +'.'+ TableName, ColumnName
FROM DBC.Columns
WHERE ColumnName = 'id'

我需要通过查看存储在这些表中的信息来遍历这些表,以便只获取特定的表。

我尝试过类似下面的代码,使用' LOOP'和光标,但它表示Query is invalid(代码来自here):

DECLARE cursor_Tables CURSOR FOR     
    SELECT DatabaseName || '.' || TableName
    FROM   DBC.Columns
    WHERE  ColumnName  ='id'; 

OPEN cursor_Tables; 
    label1: 
    LOOP    
        FETCH  cursor_Tables into tbName;
        IF (SQLSTATE ='02000') THEN
            LEAVE label1;
        END IF;

        CASE WHEN (  
            SELECT COUNT(*)
            FROM prd3_db_tmd.K_PTY_NK01
            WHERE id = 0 ) > 0
             THEN tbName
        END 
    END LOOP label1;
CLOSE cursor_Tables;
END;

我怎样才能真正解决这个问题?我还需要使用程序吗? DBMS是Teradata

5 个答案:

答案 0 :(得分:4)

您需要一个存储过程,因为这是您可以在Teradata中使用游标的唯一位置。

REPLACE PROCEDURE testproc()
DYNAMIC RESULT SETS 1
BEGIN
   DECLARE tbName VARCHAR(257);
   DECLARE SqlStr VARCHAR(500);

   -- temporary table to store the result set
   CREATE VOLATILE TABLE _vt_(tbName VARCHAR(257)) ON COMMIT PRESERVE ROWS;

   -- your existing query to return the table name
   -- Better use ColumnsV instead of Columns
   FOR cursor_Tables AS    
       SELECT DatabaseName || '.' || TABLENAME AS tbName
       FROM   DBC.ColumnsV
       WHERE  ColumnName  ='id'
   DO -- prepare the dynamic SQL ...
      SET SqlStr = 
         'insert into _vt_
          select ''' || cursor_tables.tbName || ''' 
          from ' || cursor_tables.tbName || '
          where id = 0 
          having count(*) > 0;
          ';
      -- ... and run it
      EXECUTE IMMEDIATE SqlStr;
   END FOR;

   BEGIN -- return the result set
      DECLARE resultset CURSOR WITH RETURN ONLY FOR S1;
      SET SqlStr = 'SELECT * FROM _vt_;';
      PREPARE S1 FROM SqlStr;
      OPEN resultset;
   END;

   DROP TABLE vt;
END;

答案 1 :(得分:1)

如果这是SQL Server,您可以检查以下SQL cursor,我编辑了游标声明和其中的代码 虽然它们可能与您的要求不同,但我认为您可以轻松修改

declare @sql nvarchar(max)
declare @tablename nvarchar(100)

DECLARE cursor_Tables CURSOR FOR     
    SELECT s.name + '.' + o.name 
        --s.name [schema], o.name [table]
    FROM   sys.Columns c
    inner join sys.objects o on c.object_id = o.object_id
    inner join sys.schemas s on s.schema_id = o.schema_id
    WHERE  c.Name  ='id' and o.type = 'U'

/*
SELECT TableName, DatabaseName +'.'+ TableName, ColumnName
FROM DBC.Columns
WHERE ColumnName = 'id'
*/
OPEN cursor_Tables; 

FETCH NEXT FROM cursor_Tables INTO @tablename

WHILE @@FETCH_STATUS = 0
BEGIN

--  print @tablename
set @sql = 'select case when count(*) > 0 then ''' + @tablename + ''' else '''' end from ' + @tablename
exec sp_executesql @sql

 FETCH NEXT FROM cursor_Tables INTO @tablename
END

CLOSE cursor_Tables;
DEALLOCATE cursor_Tables;

答案 2 :(得分:1)

在SQL Server上,可以使用sp_MsForEachTable未记录的存储过程而不是像游标一样的循环结构

请检查以下SQL命令

EXEC sp_MSForEachTable 'IF EXISTS(select * from sys.columns where name = ''Id'' and object_id = object_id(''?''))SELECT ''?'', COUNT(*) FROM ?'

如果您使用sp_msforeachtable或sp_msforeachdb,语法可能会很困难,但您可以在网上找到样本

答案 3 :(得分:1)

您可以创建一个变量来保存行数并将其设置为等于计数:

DECLARE @count INT

SELECT @count = COUNT(*)
FROM prd3_db_tmd.K_PTY_NK01
WHERE id = 0

然后使用if语句选择具有符合条件的行的表:

IF @count > 0
BEGIN
    SELECT tbName
END

另外作为旁注,CASE语句前面没有SELECT,语法无效,如果你不喜欢上面提到的方式,你可能只想在CASE前添加SELECT来尝试它

答案 4 :(得分:0)

您需要使用动态SQL。如果您需要查看表格中的信息,可以创建同义词。

    CURSOR  cursor_Tables is
        SELECT DatabaseName || '.' || TableName AS tbName 
        FROM   DBC.Columns
        WHERE  ColumnName  ='id'; 

begin  
    FOR R IN cursor_Tables
    LOOP    

    execute immediate 'CREATE OR REPLACE SYNONYM your_synonym FOR '|| R.tbName ;

    select *
    from your_synonym;


    END LOOP;
END;

或者,如果您愿意,可以创建视图。