【问题标题】:Fetch multiple values in a single variable and use that to compare with a single value in another variable获取单个变量中的多个值并使用它与另一个变量中的单个值进行比较
【发布时间】:2016-12-09 05:35:28
【问题描述】:

我需要通过选择查询获取多个值并放入单个变量中,然后将该变量的值与另一个只有单个值的变量进行比较。

我是 PL/SQL 编程的新手。我已经搜索了这个论坛并得到了使用 TYPE/ 集合的结果,但不知道如何在我的代码中使用它。

下面是我的代码的 sn-p:

CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
  arg1 varchar2(10) ;
  TYPE snap IS TABLE OF GDWARC_JPN.DIM_ORG_UNIT_HIST.snapshot_period%TYPE;
BEGIN 
  SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual; 
  SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap FROM GDWARC_JPN.DIM_ORG_UNIT_HIST; -- multiple values like DEC-2016, JAN-2016 etc . snapshot_period is date column 

  if arg1 in (snap ) then
    execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition arg1';

【问题讨论】:

    标签: oracle stored-procedures plsql select-into


    【解决方案1】:

    您可以使用 Member of 子句来测试元素是否是集合的一部分

        if some_value member of arg1 then 
    `      dbms_output.put_line('Member') ;
        end if ;
    

    您发布的代码在集合变量的声明和使用方面存在一些问题,以下是更正确的版本。

    CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
      arg1 varchar2(10) ;
      TYPE snap IS TABLE OF GDWARC_JPN.DIM_ORG_UNIT_HIST.snapshot_period%TYPE;
      snap_tab snap := snap() ; --declare a new collection variable and use this 
    BEGIN 
      SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual; 
      SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap_tab/*changed*/ FROM GDWARC_JPN.DIM_ORG_UNIT_HIST; -- multiple values like DEC-2016, JAN-2016 etc . snapshot_period is date column 
    
      if arg1 member of snap_tab /*changed*/ then
        execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition arg1';
    

    【讨论】:

    • 我也尝试使用子句的成员。它抛出错误为:错误(12,4):PLS-00306:调用“成员”时参数的数量或类型错误
    • 感谢 Prabhat,您的代码编译得很好,但是当我尝试运行 proc 时,它抛出错误为:错误报告 - ORA-01858:在预期为数字的地方发现了一个非数字字符 ORA-06512 :在“GDWARC_JPN.MNTH_SNAPSHOT”,第 9 行 ORA-06512:在第 1 行 01858. 00000 - “在需要数字的地方发现了一个非数字字符”你能帮忙吗?
    【解决方案2】:

    您可以简单地使用循环来检查查询返回的所有值:

    CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
      arg1 varchar2(10) ;
    BEGIN 
      arg1 := to_char(sysdate,'MON-yyyy'); /* you do not need to trunc and/or a query here */
      --
      /* you can use a loop to scan all your values */
      for i in (
                  SELECT (to_char(snapshot_period,'MON-yyyy')) val
                  FROM GDWARC_JPN.DIM_ORG_UNIT_HIST
               )
      loop
          if i.val = arg1 then
            /* arg1 must be out of the fixed string */
            execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition ' || arg1;
          end if;
      end loop;
    end;  
    

    但是您的代码似乎循环遍历了一个表,但您只截断了与 sysdate 对应的分区;因此,您的代码可以简化:

    CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
      arg1 varchar2(10) ;
      vCheck number;
    BEGIN 
      arg1 := to_char(sysdate,'MON-yyyy'); /* you do not need to trunc and/or a query here */
      /* you only need to check whether a value for sysdate exists or not */
      select count(1)
      into vCheck
      from GDWARC_JPN.DIM_ORG_UNIT_HIST
        where to_char(snapshot_period,'MON-yyyy') = arg1;
      --
      if vCheck > 0 then
              /* arg1 must be out of the fixed string */
              execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition ' || arg1;
      end if;
    end;  
    

    另外,请注意您不需要 varchar2 来检查您的日期,但您可以简单地将它们都 trunc 到月份并检查 trunc 的结果,并且动态字符串中有错误,给定arg1 应该是一个变量值,而不是硬编码到字符串中。

    【讨论】:

    • 代码已编译,但当没有发生截断时,分区名称应在引号中作为 "DEC-2016" 给出。如果我将 arg1 放在引号中,代码将无法编译。请帮忙。
    • 终于成功了!!.. 感谢您的帮助 :) 创建或替换过程 MNTH_SNAPSHOT AS arg1 varchar2(10) ; v支票号码;开始 arg1 := to_char(sysdate,'MON-yyyy'); /* 这里不需要截断和/或查询 / / 你只需要检查 sysdate 的值是否存在 */ select count(1) into vCheck from GDWARC_JPN.DIM_ORG_UNIT_HIST where to_char(snapshot_period,'MON-yyyy') = arg1; -- 如果 vCheck > 0 则立即执行 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition' || q'["]'|| arg1 ||q'["]' ;
    【解决方案3】:

    我无法发表评论,所以我会写新的回复

    感谢 Prabhat,您的代码编译得很好,但是当我尝试运行 proc ,它抛出错误为:错误报告 - ORA-01858: a non-numeric 在需要数字的地方找到字符 ORA-06512: 在 “GDWARC_JPN.MNTH_SNAPSHOT”,第 9 行 ORA-06512:第 1 行 01858.00000 - “在需要数字的地方发现了一个非数字字符”可以 请帮忙。

    您的问题是您使用了不同的数据类型。

    SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap_tab/*changed*/ FROM GDWARC_JPN.DIM_ORG_UNIT_HIST;
    

    首先,您使用日期,将其转换为字符,然后再次将其保存为日期。不知道怎么编译这个

    SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual; 
    

    当您将 sysdate 转换为所需格式并将其保存到 varchar 变量时,它不再是日期。然后你将它与日期进行比较,因为你在日期上有你的格式,所以它不能被识别。 因此,要么在所有变量中使用日期,要么使用 TRUNC 选项从中提取月份和年份(尽管我不确定你是否可以将表的成员转换为成员,也许你需要在这种情况下使用 for)或打开 snap表转为 varchar 类型

    示例

    CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
      arg1 varchar2(10) ;
      TYPE snap IS TABLE OF varchar2(10);
      snap_tab snap := snap() ; --declare a new collection variable and use this 
    BEGIN 
      SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual; 
      SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap_tab/*changed*/ FROM GDWARC_JPN.DIM_ORG_UNIT_HIST; -- multiple values like DEC-2016, JAN-2016 etc . snapshot_period is date column 
    
      if arg1 member of snap_tab /*changed*/ then
        execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition arg1';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多