使用游标从动态视图中获取动态列的数据

Fetching data of a dynamic column from a dynamic view using cursor

需求是检查视图的数据一致性。有点复杂,一步步来吧。

  1. A table check_data_column 基本上有 5 个小鬼。列:ViewName、ColumnName、Mandatory、MaxLength、DataType。

它将包含有关特定视图的每个字段的信息。例如:

ViewName: Employee_V
ColumnName: EmployeeNo
Mandatory: 1 (True)
MaxLength: 10
DataType: Number

ViewName: Employee_V
ColumnName: EmployeeName
Mandatory: 1 (True)
MaxLength: 20
DataType: String
  1. 现在我必须编写一个函数,它从这个 check_data_column 中获取所有条目,并在适当的视图中检查每个提到的列的数据。

从上面的例子来看,它会检查Employee_V中的数据。 EmployeNo 列中的每个条目不应为空,最大长度应为 10,并且应为数值。 同样,EmployeeName 列中的每个条目不应为空,最大长度应为 20,并且应为字符串。

  1. 观看次数未知,没有。每个视图中的列数未知。

为了解决上面的问题,我写了如下代码:

FUNCTION CheckData(viewname VARCHAR2)
RETURN VARCHAR2
Is

  return_v      VARCHAR2(1000);
  query_v       VARCHAR2(200);
  column_c      SYS_REFCURSOR;
  column_v      column_c%ROWTYPE;

  CURSOR ddc_c IS
  SELECT *
  FROM check_data_column;

BEGIN
  return_v := null;

  FOR ddc_v IN ddc_c LOOP

    query_v := 'SELECT' || ddc_v.column_name || 'FROM anc_sap.' || ddc_v.viewname;

    OPEN column_c FOR query_v;
    LOOP
       FETCH column_c INTO column_v;
       EXIT WHEN column_c%NOTFOUND;

       IF LENGTH(column_v) > ddc_v.max_length THEN
           return_v := 'Max. length exceeded';
       END IF;

       ----Other validations (on mandatory and data type)

    END LOOP; 
    CLOSE column_c;

  END LOOP;

  RETURN return_v;

END CheckData;

问题:

我在这里面临的问题是为 sys_refcursor column_c 声明 column_v 变量。由于目前我无法考虑 sys_refcursor 的替代品,我还能做些什么吗?

此功能在简单测试中有效。它检查空值和长度,您必须添加其余的验证。

create or replace function CheckData(i_viewname VARCHAR2)
RETURN VARCHAR2
Is
  query_v       VARCHAR2(2000);
  v_cnt number := 0;

  CURSOR ddc_c IS 
    SELECT * FROM check_data_column where viewname = i_viewname;

BEGIN
  FOR ddc_v IN ddc_c LOOP

    -- check nulls
    if ddc_v.mandatory = 1 then
      query_v := 'select count(1) from '|| ddc_v.viewname 
        ||' where '||ddc_v.columnname||' is null';
      execute immediate query_v into v_cnt;
      if v_cnt > 0 then
        return 'null values for mandatory column '
          ||ddc_v.viewname ||'.'||ddc_v.columnname||' exists';
      end if;
    end if;

    -- check column length
    query_v := 'select count(1) from '|| ddc_v.viewname 
      ||' where length('||ddc_v.columnname||') > '||ddc_v.maxlength;
    execute immediate query_v into v_cnt;
    if v_cnt > 0 then
      return 'max length in column '||ddc_v.viewname
        ||'.'||ddc_v.columnname||' exceeded';
    end if;

    -- other validations

  END LOOP;

  RETURN 'OK';

END CheckData;