【问题标题】:How get information from multiple tables using cursor?如何使用游标从多个表中获取信息?
【发布时间】:2015-04-17 23:01:17
【问题描述】:

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

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

【问题讨论】:

  • 您需要在存储过程中的游标中进行选择,然后对返回的每个表名使用动态 SQL。
  • @dnoeth 我尝试使用您的提示,但遇到了一些问题
  • This answer 与 TSQL (SQL Server) 而不是 Teradata SQL 相关,但可能会对您有所帮助。

标签: sql cursor teradata


【解决方案1】:

您需要一个存储过程,因为这是您在 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;

【讨论】:

    【解决方案2】:

    如果这是 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;
    

    【讨论】:

      【解决方案3】:

      在 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,语法可能会比较困难,但您可以在网上找到示例

      【讨论】:

        【解决方案4】:

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

        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

        【讨论】:

          【解决方案5】:

          您需要使用动态 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;
          

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-30
            • 2013-02-23
            • 2017-11-09
            • 1970-01-01
            • 2012-03-13
            • 2015-06-02
            • 1970-01-01
            • 2011-11-23
            相关资源
            最近更新 更多