Това не е нормална част от функционалността на базата данни. Вие обаче не сте първият човек, който е поискал това или нещо подобно.
Решението изисква две неща. Първият е речникът на данните; базата данни на Oracle не поддържа Reflection, но идва с набор от изгледи, които ни дават метаданни за обектите на нашата база данни. В този случай имаме нужда от user_tab_columns
, което ще ни даде колоните за дадена таблица. Второто нещо е динамичен SQL; това е способността да се сглоби SQL заявка по време на изпълнение и след това да се изпълни. Има няколко начина да направите това, но обикновено референтните курсори са достатъчни.
Следният код е доказателство за концепцията. Отнема четири параметъра:
- името на таблицата, която искате да търсите
- името на основната ключова колона на тази таблица
- стойността на първичния ключ, по която искате да ограничите
- стойността, която искате да търсите.
Той е rough'n'ready, така че може да се наложи да го редактирате, за да подредите изхода или да направите програмата по-гъвкава.
create or replace procedure search_cols
(tname in user_tables.table_name%type
, pk_col in user_tab_columns.column_name%type
, pk in number
, val in number )
is
firstcol boolean := true;
stmt varchar2(32767);
result varchar2(32767);
rc sys_refcursor;
begin
stmt := 'select ';
<< projection >>
for lrec in ( select column_name from user_tab_columns
where table_name = tname
and column_name != pk_col
and data_type = 'NUMBER'
order by column_id )
loop
if not firstcol then
stmt := stmt || chr(10) || '||'',''||';
else
firstcol := false;
end if;
stmt := stmt || ' case when '|| lrec.column_name||' = '|| val ||
' then '''|| lrec.column_name || ''' else null end';
end loop projection;
stmt := stmt || chr(10)|| ' from '||tname||' where '|| pk_col || ' = '|| pk;
-- dbms_output.put_line(stmt);
open rc for stmt;
fetch rc into result;
close rc;
dbms_output.put_line(tname || '::' || val || ' found in '||result);
end search_cols;
/
Както можете да видите, динамичният SQL е труден за четене. По-трудно е да се отстраняват грешки :) Така че е добра идея да имате средство за показване на крайния израз.
Както и да е, ето резултатите:
SQL> set serveroutput on size unlimited
SQL> exec search_cols('T23', 'ID', 111, 10)
T23::10 found in ,COL_B,COL_C,
PL/SQL procedure successfully completed.
SQL> exec search_cols('T23', 'ID', 222, 10)
T23::10 found in COL_A,,,
PL/SQL procedure successfully completed.
SQL>