使用游标从动态视图中获取动态列的数据
Fetching data of a dynamic column from a dynamic view using cursor
需求是检查视图的数据一致性。有点复杂,一步步来吧。
- 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
- 现在我必须编写一个函数,它从这个 check_data_column 中获取所有条目,并在适当的视图中检查每个提到的列的数据。
从上面的例子来看,它会检查Employee_V中的数据。
EmployeNo 列中的每个条目不应为空,最大长度应为 10,并且应为数值。
同样,EmployeeName 列中的每个条目不应为空,最大长度应为 20,并且应为字符串。
- 观看次数未知,没有。每个视图中的列数未知。
为了解决上面的问题,我写了如下代码:
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;
需求是检查视图的数据一致性。有点复杂,一步步来吧。
- 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
- 现在我必须编写一个函数,它从这个 check_data_column 中获取所有条目,并在适当的视图中检查每个提到的列的数据。
从上面的例子来看,它会检查Employee_V中的数据。 EmployeNo 列中的每个条目不应为空,最大长度应为 10,并且应为数值。 同样,EmployeeName 列中的每个条目不应为空,最大长度应为 20,并且应为字符串。
- 观看次数未知,没有。每个视图中的列数未知。
为了解决上面的问题,我写了如下代码:
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;