我有一张桌子如下图所示。该表将动态生成,我不知道它将保持什么值。
------------------------------------------
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
。
我没有任何草稿代码来展示我的尝试,因为我不知道我该怎么做。
答案 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及其各自的列替换为表的列名。
缺陷:表名是硬编码的。试图使代码通用立即执行或任何其他技巧。很快就会实现。 编辑:修复了缺陷。