Поиск значения по всем таблицам
Вариант1:
DECLARE
match_count INTEGER;
query_str VARCHAR2(400);
l_owner VARCHAR2(10) := 'SCOTT';
l_search_text VARCHAR2(100) := '10';
BEGIN
FOR t IN (select table_name, column_name FROM all_tab_columns a
where owner = l_owner
and a.data_type in ('NUMBER', 'VARCHAR2')
)
LOOP
begin
match_count := 0;
query_str := 'SELECT COUNT(*) FROM ' ||l_owner||'.'|| t.table_name ||
' WHERE to_char(' || t.column_name || ') = :1';
EXECUTE IMMEDIATE query_str
INTO match_count
USING l_search_text;
IF match_count > 0 THEN
dbms_output.put_line(l_owner||'.'||t.table_name || ' ' || t.column_name || ' ' || match_count);
dbms_output.put_line(' SELECT t.'|| t.column_name || ', t.* from '||l_owner||'.'|| t.table_name||' t where to_char(' || t.column_name || ') = '''||l_search_text||'''');
dbms_output.put_line('');
END IF;
exception
when others then
dbms_output.put_line(t.table_name||'.'||t.column_name||' : '||SQLERRM||' : '||SQLCODE);
dbms_output.put_line(query_str);
dbms_output.put_line('');
/*raise*/
end;
END LOOP;
END;
Вариант2:
--SET SERVEROUTPUT ON SIZE 1000000
DECLARE
TYPE tab_columns_rec_type IS RECORD (
table_name all_tab_columns.table_name%type
,column_name all_tab_columns.column_name%type
,data_type all_tab_columns.data_type%type
);
type tab_columns_tab_type is table of tab_columns_rec_type index by binary_integer;
l_tab_columns_rec tab_columns_tab_type;
match_count INTEGER;
query_str VARCHAR2(400);
l_owner VARCHAR2(10) := 'SCOTT';
l_search_text VARCHAR2(100) := '10'; -- % добавляем здесь, если ищем не по точному вхождению
l_number NUMBER;
is_number NUMBER(1);
l_str_length NUMBER;
/*
l_mode:
1 - NUMBER и VARCHAR2
2 - only NUMBER
3 - only VARCHAR2
*/
l_mode NUMBER := 1;
-- При каком количестве найденные совпадений
-- прекращать поиск
l_found_count NUMBER := 1;
l_exists_count NUMBER;
BEGIN
l_str_length := length(l_search_text);
begin
l_number := to_number(l_search_text);
is_number := 1;
exception
when VALUE_ERROR then
is_number := 0;
end;
if (l_mode = 1 and is_number = 1) then
select table_name, column_name, data_type
bulk collect into l_tab_columns_rec
FROM all_tab_columns a
where owner = l_owner
and a.data_length >= l_str_length
and ( a.data_type = 'VARCHAR2' or a.data_type = 'NUMBER' );
elsif (l_mode = 2 and is_number = 1) then
select table_name, column_name, data_type
bulk collect into l_tab_columns_rec
FROM all_tab_columns a
where owner = l_owner
and a.data_length >= l_str_length
and a.data_type = 'NUMBER';
else
select table_name, column_name, data_type
bulk collect into l_tab_columns_rec
FROM all_tab_columns a
where owner = l_owner
and a.data_length >= l_str_length
and a.data_type = 'VARCHAR2';
end if;
l_exists_count := 0;
if NOT (l_tab_columns_rec is null or l_tab_columns_rec.count = 0) then
for j in l_tab_columns_rec.first..l_tab_columns_rec.last
LOOP
begin
match_count := 0;
if (l_tab_columns_rec(j).data_type = 'VARCHAR2') then
query_str := 'SELECT count(*) FROM ' ||l_owner||'.'|| l_tab_columns_rec(j).table_name ||
' WHERE rownum = 1 and to_char(' || l_tab_columns_rec(j).column_name || ') = :1';
EXECUTE IMMEDIATE query_str
INTO match_count
USING l_search_text;
elsif (l_tab_columns_rec(j).data_type = 'NUMBER') then
query_str := 'SELECT count(*) FROM ' ||l_owner||'.'|| l_tab_columns_rec(j).table_name ||
' WHERE rownum = 1 and ' || l_tab_columns_rec(j).column_name || ' = :1';
EXECUTE IMMEDIATE query_str
INTO match_count
USING l_number;
end if;
IF match_count > 0 THEN
l_exists_count := l_exists_count + 1;
dbms_output.put_line(l_tab_columns_rec(j).data_type||' '||l_owner||'.'||l_tab_columns_rec(j).table_name || ' ' || l_tab_columns_rec(j).column_name );
dbms_output.put_line(' SELECT t.'|| l_tab_columns_rec(j).column_name || ', t.* from '||l_owner||'.'|| l_tab_columns_rec(j).table_name||' t where to_char(' || l_tab_columns_rec(j).column_name || ') like '''||l_search_text||'''');
dbms_output.put_line('');
if (l_exists_count = l_found_count) then
exit;
end if;
END IF;
exception
when others then
dbms_output.put_line(l_tab_columns_rec(j).table_name||'.'||l_tab_columns_rec(j).column_name||' : '||SQLERRM||' : '||SQLCODE);
dbms_output.put_line(query_str);
dbms_output.put_line('');
/*raise*/
end;
END LOOP;
end if;
END;

Можно сделать небольшую оптимизацию скрипту по количеству элементов в цикле:
l_str_length number; l_dummy number; is_number number(1); begin l_str_length := length(i_str); begin l_dummy := to_number(i_str); is_number := 0; exception when others then is_number := 1; end; FOR t IN (select table_name, column_name FROM all_tab_columns a where owner = i_owner and a.DATA_LENGTH >= l_str_length and (a.data_type = ’VARCHAR2′ or (is_number = 1 and a.data_type = ’NUMBER’))) LOOPошибся в коде
вместо «is_number := 0;» нужно конечно использовать «is_number := 1;» и наоборот.
@maart
мне проще закоментировать ненужный тип в строке
and a.data_type in ('NUMBER', 'VARCHAR2')Но конечно, кому как удобно.
Я написал процедуру в своем пакете с утилитами, и в зависимости от входных параметров применяется разная логика поиска. Из неё и кусочек кода приложил.
Например, добавил ещё два параметра. Первый отвечает за операнд «=» или «like ‘%i_str%'». Второй отвечает за регистр букв — учитывать или не учитывать.
Maart, приветствую! Очень нужен такой полезный скриптец — поиск заданного значения во всех таблицах и поиск объектов, которые сожержат, например заданное название столбца. Можешь, плиз, поделиться скриптами, от начала и до конца. Указанные здесь не срабатывают — 1 -й зависает напрочь, а твою оптимизацию не совсем понимаю…
Заранее спасибо!
P.S. Для Oracle …
Добавил второй вариант, работает быстрее.
Привет! Спасибо большое за оперативность — даже не ожидала такого скорого ответа! Единственное но… почему-то у меня оба этих скрипта виснут — я уж минут через 15 прерываю выполнение — надоедает ждать…
Ты можешь, их, плиз, как-то оптимизировать?
Буду тебе крайне признательна и благодарна!!! ;)
@sunsbaby
По большой схеме будет работать долго. У меня, например, отрабатывает около 1 часа.
Для оптимизации можно ограничить названия таблиц, если примерно известно в каких лежат данные.
select table_name ,column_name ,data_type FROM all_tab_columns a where owner = 'SCOTT' and a.data_length >= 5 and (a.data_type = 'VARCHAR2' or a.data_type = 'NUMBER') and table_name like 'EMP%'Чуток подправил вариант2, добавил параметр
@rudev
Спасибо огромнейшее! Ещё маленький глупый вопросик… У меня отработал 2-й вриант, но в рез-те тока написал «anonymous block completed» …а где же сам ответ посмотреть можно? :))
P.S. готова тебя расцеловать (если тебя это интересует…….) ;) :))
@sunsbaby


В PL/SQL Developer можно просмотреть так:
Если в SQL-PLUS, то раскомментировать первую строку:
@rudev
A если Oracle SQL?
P.S. Может это как-то преобразовать в процедуру или функцию? :)
@sunsbaby

Для SQL Developer
Ура! Получилось! ТЫ супер-пупер программер!!!! :)
Здравствуйте, уважаемый
Очень нужен этот полезный скриптец – поиск заданного значения во всех таблицах и поиск объектов, которые содержат, например заданное название столбца.
Может, поделитесь скриптами, от начала и до конца.
Заранее благодарю,
Вадим
Все, что вам надо, уже есть в посте.
поиск заданного значения во всех таблицах — это вариант1 и вариант2
поиск объектов, которые содержат, например заданное название столбца — таблица all_tab_columns
Респект за скрипт, работает, пригодился! Переслал коллегам.