获取单个变量中的多个值并使用它与另一个变量中的单个值进行比较

Posted

技术标签:

【中文标题】获取单个变量中的多个值并使用它与另一个变量中的单个值进行比较【英文标题】: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';

【问题讨论】:

【参考方案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';

【讨论】:

以上是关于获取单个变量中的多个值并使用它与另一个变量中的单个值进行比较的主要内容,如果未能解决你的问题,请参考以下文章

如何使用单个查询获取存储在不同变量中的多个表行的计数?

如何从 HTML/PHP 中的单个 <select> 变量中获取多个值?

使用单个字符串变量传递@Requestparam中的多个键

在pl sql中的单个变量中传递两个或多个参数[重复]

可以从列表页面上的 api 中的辅助表获取变量,但不能在单个项目页面上

如何在单个 bash 变量中使用多个主机名?