需要构建一个包含存储在另一个表

时间:2016-07-07 12:18:46

标签: sql oracle plsql oracle11g

我有一张桌子如下图所示。该表将动态生成,我不知道它将保持什么值。

------------------------------------------
TABLE_NAME      COLUMN_NAME    CHAR_LENGTH
------------------------------------------
 EMPLOYEE          COL1             100
 EMPLOYEE          COL2             200
 EMPLOYEE          COL3             300
 EMPLOYEE          COL4             400

基于此表,我想以这样的方式构建一个查询,它将为我提供那些包含char长度大于CHAR_LENGTH列值的数据的列。

例如,如果COL2包含char长度为500(> 200)的数据,则查询会给我COL2

我没有任何草稿代码来展示我的尝试,因为我不知道我该怎么做。

3 个答案:

答案 0 :(得分:1)

由于您的需求的动态性,我不认为这在纯SQL中是可行的。你需要某种形式的PL / SQL。

假设您只需输出所需的结果即可,这里有一个可以完成工作的PL / SQL块:

declare
  wExists number(1);
begin
  for rec in (select * from your_dynamic_table)
  loop
    execute immediate 'select count(*)
                         from dual
                        where exists (select null
                                        from ' || rec.table_name || ' t
                                       where length(t.' || rec.column_name || ') > ' || rec.char_length || ')'
    into wExists;

    if wExists = 1 then
      dbms_output.put_line(rec.column_name);
    end if;
  end loop;
end;

您还会注意到使用exists子句来优化查询,以便尽可能不必要地迭代整个表。

或者,如果您希望结果可查询,可以考虑将代码转换为流水线函数。

答案 1 :(得分:0)

select column_name
from (
 select statement that builds the table output
) A
where char_length<length(column_name)

会有帮助吗?

答案 2 :(得分:0)

您需要一个程序来实现相同的目标:

这里我正在处理Oracle中的all_tab_columns表,这是一个默认表,其结构与参考示例非常相似。(试试select * from all_tab_columns)。 all_tab_columns的结构与您的结构非常相似,只是您永远不会找到其值超过其数据长度的varchar记录(明显的数据库级别约束)。日期字段可能超出数据长度,并且反映在此过程的输出中。我正在搜索EMPLOYEES中所有大小超过指定范围的列。

DECLARE
cursor c is select column_name,data_length,table_name from all_tab_columns where table_name=:Table_name;
V_INDEX_NAME all_tab_columns.column_name%type;
v_data_length all_tab_columns.data_length%type;
V_NUMBER PLS_INTEGER;
v_table_name all_tab_columns.table_name%type;
 BEGIN
open c;
    LOOP
     FETCH c into v_index_name,v_data_length,v_table_name;
          EXIT when c%NOTFOUND;
          v_number :=0;
execute immediate 'select count(*)  from '|| :Table_name ||' where length('||v_index_name||')>'||v_data_length into v_number;
 if v_number>1 then
 dbms_output.put_line(v_index_name||' has values greater than specified'||' '||V_INDEX_NAME||' '||v_data_length);
 end if;
 END LOOP;
 close c;
 END;
 /

将all_tab_columns及其各自的列替换为表的列名。

缺陷:表名是硬编码的。试图使代码通用立即执行或任何其他技巧。很快就会实现。 编辑:修复了缺陷。