0

我正在收集两列(col & val)。进入第二个 select col 是其他列的参数,val 是该列的值。

在此处输入图像描述

declare
  TYPE t_my_list is record(id varchar2(1000), col VARCHAR2(4000),val VARCHAR2(4000));
  TYPE list_3STR is table of t_my_list;    
  v_stmt    VARCHAR2(32000) := 'SELECT id, col, val FROM userA.tableA';
  v_lstmt   VARCHAR2(32000);
  v_ret     list_3STR := list_3STR();
  cDel   number;

begin
 EXECUTE IMMEDIATE v_stmt BULK COLLECT INTO v_ret;

  for i in v_ret.first..v_ret.last loop
   v_lstmt := 'SELECT count(*) FROM userB.tableB 
      WHERE NVL('||v_ret (i).col||', ''<null>'') in ('''||v_ret (i).val||''', ''<null>'') and idB = '''||v_ret (i).id||'''';

   EXECUTE IMMEDIATE v_lstmt INTO cDel;
    If cDel > 0 Then
    --some code
    cDel = 0;   
    end if;
  end loop;
end;

但是在我的选择语句中我可以有 null 所以我使用 NVL。另外,因为我可以有数字,所以我需要使用 convert to_char('||v_ret (i).col||')。此外,列的类型是数字、RAW、日期等。

我的问题:

  • NVL还有其他可能性吗?

  • 如果没有,有 oracle 默认转换器吗?(所有类型都需要是 Varchar2)

4

2 回答 2

1

您可以更改代码以执行以下操作:

   v_lstmt := 'SELECT count(*) FROM userB.tableB WHERE id = '''||v_ret (i).id||''''
     || ' and ('||v_ret (i).col||' is null or '||v_ret (i).col||' = :val)';

   EXECUTE IMMEDIATE v_lstmt INTO cDel using v_ret (i).val;

这将检查该列是否为 null与提供的 匹配val,并使用绑定变量来提供要检查的值以减少解析位。

但是,这仍然依赖于隐式转换,因此如果您在表中有日期值,例如,您将依赖 NLS 设置将其转换为与目标表列类型匹配。

您可以使用all_tab_columns视图查找目标列的数据类型,并val在绑定之前将其显式转换为该类型。一个更复杂但可能更健壮的方法是使用dbms_sql内部动态 SQL 而不是execute immediate.

不过,外部查询似乎不需要是动态的,您可以这样做:

declare
  v_lstmt   VARCHAR2(32000);
  cDel   number;
begin
  for rec in (SELECT id, col, val FROM tableA) loop
    v_lstmt := 'SELECT count(*) FROM tableB WHERE id = '''||rec.id||''''
      || ' and ('||rec.col||' is null or '||rec.col||' = :val)';


    dbms_output.put_line(v_lstmt);
    EXECUTE IMMEDIATE v_lstmt INTO cDel using rec.val;
    If cDel > 0 Then
      --some code
      cDel := 0;   
    end if;
  end loop;
end;
/
于 2018-08-03T08:04:04.960 回答
0

如果我正确理解了您的问题,您希望包括 v_ret (i).col 为 NULL 的情况。

如果是这样,您可以尝试在 select 语句中使用以下代码:

WHERE ('||v_ret (i).col||' is null OR '||v_ret (i).col||' = '||v_ret (i).val||')

代替:

WHERE NVL('||v_ret (i).col||', ''<null>'') in ('''||v_ret (i).val||''', ''<null>'')

作为默认转换器,您可以尝试使用CAST函数:https ://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/CAST.html

于 2018-08-03T07:53:07.800 回答