【问题标题】:Storing Select result and using loop to test in PL/SQL block存储选择结果并使用循环在 PL/SQL 块中进行测试
【发布时间】:2019-01-05 04:57:54
【问题描述】:

我想将查询的结果集存储到某个临时位置(听说过游标),然后使用循环根据值测试每一列。我试过了

Declare r_rec mytable%ROWTYPE;
BEGIN
select * into r_rec from mytable where column='20190103';
/*IF need to test certain condition for each column.
Then
V_C:=V_C+1;
end if; */

end;
/

如果让您感到困惑,我很抱歉。我的要求是检查一组记录的任何列是否包含 0,如果我需要递增以获取任何列中包含 0 的行数。我可以查询它,但我必须输入所有 200 列,我正在寻找一种替代方法,我可以测试选择查询的每条记录,以检查获取的任何记录中的任何列是否为 0。

很抱歉没有正确发布我的问题。

【问题讨论】:

  • 为什么不使用带有WHERE 子句的UPDATE 语句来定义应该更新哪些行?我不明白在这种情况下需要光标
  • 如果您正在测试某个条件,为什么不将其作为查询的一部分而不是在循环中呢?您将如何处理满足和不满足条件的行?您可能正在寻找collections,但不清楚...如果您只是计算有多少行符合条件,那么您可能只需要一个简单的聚合count(*),它不需要PL/SQL完全没有。

标签: sql oracle


【解决方案1】:

游标不存储结果,它实际上是一个让您迭代结果的指针(正如@Ted 实际展示的那样)。如果您想将结果存储在您的 PL/SQL 块中,那么您可以使用a collection,您可以将其声明为与您的表匹配的类型,以接近您的单行查询到记录类型;然后bulk-collect 进入:

declare
  type t_tab is table of mytable%ROWTYPE;
  v_tab t_tab;
  v_c pls_integer := 0;
begin
  select *
  bulk collect into v_tab
  from mytable
  where col1='20190103';

  for i in 1..v_tab.count loop
    if v_tab(i).col2 = 'Y' then -- whatever you need to test
      v_c := v_c + 1;
    end if;
  end loop;

  dbms_output.put_line(v_c);
end;
/

但是除非你对匹配的行和不匹配你的条件的行做其他事情,你可以在主查询中添加它作为测试:

declare
  type t_tab is table of mytable%ROWTYPE;
  v_tab t_tab;
  v_c pls_integer := 0;
begin
  select *
  bulk collect into v_tab
  from mytable
  where col1='20190103'
  and col2='Y'; -- whatever you need to test

  for i in 1..v_tab.count loop
    v_c := v_c + 1;
  end loop;

  dbms_output.put_line(v_c);
end;
/

如果您只计算匹配的行,则不需要游标或集合,只需使用聚合函数:

declare
  v_c pls_integer;
begin
  select count(*)
  into v_c
  from mytable
  where col1='20190103'
  and col2='Y'; -- whatever you need to test

  dbms_output.put_line(v_c);
end;
/

或者根本不使用 PL/SQL:

select count(*)
from mytable
where col1='20190103'
and col2='Y'; -- whatever you need to test

顺便说一句,您的 '20190103' 值看起来像是将日期存储为字符串。您应该use the correct data type - 将日期存储为实际日期。 (如果该列是日期,那么您依赖于隐式转换,这也不是一个好主意......)

【讨论】:

  • 很抱歉让您感到困惑。我的要求是检查一组记录的任何列是否包含 0,如果我需要递增以获取任何列中包含 0 的行数。我可以查询它,但我必须输入所有 200 列,我正在寻找一个替代方法,我可以测试选择查询的每条记录,以检查获取的任何记录中的任何列是否为 0。抱歉没有正确发布我的问题.
  • 您仍然需要键入所有列名,以便在循环中一一检查它们。或者您可以使用dbms_sql 来自动执行该操作,但这可能会使事情变得过于复杂。使用静态 SQL 查询或 PL/SQL 块,您可以通过对数据字典的查询来生成列列表,以节省您在物理上将它们全部输入,如果这是您唯一的反对意见。但是您仍然需要以某种方式确定要包含哪些列 - 或者可能要排除哪些列,如果这是一个较短的列表。
  • 嗨,你能看看我的问题吗?它类似于修剪最后一个字符。谢谢stackoverflow.com/questions/69834411/…
【解决方案2】:

下面是一个非常简单的循环查询结果的方法:

BEGIN
  FOR rec IN (select col1, col2 from mytable where column = '20190103') LOOP
    IF rec.col1 > rec.col2 THEN
      ...
    END IF;
  END LOOP;
END;

【讨论】:

    【解决方案3】:

    这是一个我认为对你有帮助的模板:

    DECLARE
       cursor c1 is
         select column1, column2 ... etc from mytable where column='20190103';
    
    BEGIN
    
       FOR r_rec in c1
       LOOP
          if r_rec.column_XYZ = something then
           do_something;
          end if;
       END LOOP;
    END;
    

    【讨论】:

      【解决方案4】:

      我从Search All Fields In All Tables For A Specific Value (Oracle)修改了这个答案

      做计数。 它将计算包含 0 的表中每个字段的记录。 用你的替换我的表名。

          SELECT count(*),
         SUBSTR (table_name, 1, 30) "Table",
            SUBSTR (column_name, 1, 30) "Column"
          FROM cols,
            TABLE (xmlsequence (dbms_xmlgen.getxmltype ('select '
          || column_name
            || ' from '
            || table_name
            || ' where upper('
           || column_name
           || ') like upper(''%'
           || 0
           || '%'')' ).extract ('ROWSET/ROW/*') ) ) t
           where table_name = 'INVENTORY_LINE'
           group by SUBSTR (table_name, 1, 30) ,
            SUBSTR (column_name, 1, 30) 
         ORDER BY "Table";
      

      【讨论】:

        猜你喜欢
        • 2019-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-05
        • 2019-04-06
        相关资源
        最近更新 更多