Более быстрый способ проверить, состоит ли строка из цифр или содержит хотя бы один нецифровой символ, — это использовать функцию translate
. Увы, из-за того, что Oracle обрабатывает пустые строки не по стандарту SQL, форма функции, которую мы должны использовать, немного сложна:
translate(input_string, 'z0123456789', 'z')
(z
может быть любым нецифровым символом, он нам нужен, чтобы третий аргумент не был нулевым). Это работает путем перевода z
в себя, а 0
и т. д. в ничто. Таким образом, если входная строка была null
или состояла только из цифр, и ТОЛЬКО в этом случае, значение, возвращаемое функцией, равно null
.
Кроме того: чтобы ускорить процесс, вы можете протестировать каждый столбец с условием EXISTS
. Если столбец не должен быть числовым, то в большинстве случаев условие EXISTS
станет истинным очень быстро, поэтому вам придется проверять очень небольшое количество значений из таких столбцов.
Когда я пытался выполнить эту работу, я столкнулся с многочисленными побочными проблемами. Предположительно, вы хотите просмотреть все схемы (кроме SYS
и, возможно, SYSTEM
). Поэтому вам нужно запустить процедуру (анонимную блокировку) от учетной записи с привилегиями SYSDBA. Затем я столкнулся с проблемами с нестандартными именами таблиц и столбцов (имена, начинающиеся с подчеркивания и т. д.); что напомнило идентификаторы, определенные в двойных кавычках - ужасная практика.
Для иллюстрации я буду использовать схему HR — на которой сработал подход. Возможно, вам придется настроить это дальше; Я не смог заставить его работать, изменив строку
and owner = 'HR'
to
and owner != 'SYS'
Итак, с этим длинным вступлением, вот что я сделал.
Во-первых, в «обычной» учетной записи пользователя (моя собственная, с именем INTRO
— я запускаю очень маленькую базу данных только с одним «нормальным» пользователем, плюс «стандартные» пользователи Oracle, такие как SCOTT, HR и т. д.) — так, в схеме INTRO
, я создал таблицу для получения имени владельца, имени таблицы и имени столбца для всех столбцов типа данных VARCHAR2, которые содержат только «числовые» значения или null
(числовое определение, как вы это сделали). ПРИМЕЧАНИЕ ЗДЕСЬ: Если вы хотите чтобы действительно проверить все числовые значения, вам действительно понадобится регулярное выражение или что-то вроде того, что показал Вернфрид; В противном случае я бы все же использовал условие EXISTS, а не COUNT в анонимной процедуре.
Затем я создал анонимный блок для поиска нужных столбцов. ПРИМЕЧАНИЕ. У вас не будет схемы INTRO
— поэтому меняйте ее везде в моем коде (и при создании таблицы, и в анонимном блоке). Если процедура завершится успешно, вы сможете запросить таблицу. Я показываю это и в конце.
При входе в систему как SYS (или другого пользователя с полномочиями SYSDBA):
create table intro.cols_with_numbers (
owner_name varchar2(128),
table_name varchar2(128),
column_name varchar2(128)
);
declare x number;
begin
execute immediate 'truncate table intro.cols_with_numbers';
for t in ( select owner, table_name, column_name
from dba_tab_columns
where data_type like 'VARCHAR2%'
and owner = 'HR'
)
loop
execute immediate 'select case when exists (
select *
from ' || t.owner || '.' || t.table_name ||
' where translate(' || t.column_name || ',
''z0123456789'', ''z'') is not null
) then 1 end
from dual'
into x;
if x is null then
insert into intro.cols_with_numbers (owner_name, table_name, column_name)
values(t.owner, t.table_name, t.column_name);
end if;
end loop;
end;
/
Запустите эту процедуру, а затем запросите таблицу:
select * from intro.cols_with_numbers;
no rows selected
(что означает, что в таблицах схемы HR не было числовых столбцов с неправильным типом данных VARCHAR2 — или, по крайней мере, таких столбцов, которые имели бы только неотрицательные целые значения.) Вы можете продолжить тестирование, намеренно создав таблицу с такая колонка и тестирование, чтобы убедиться, что она «поймана» процедурой.
ДОБАВЛЕНО. Вот что происходит, когда я меняю владельца с 'HR'
на 'SCOTT'
:
PL/SQL procedure successfully completed.
OWNER_NAME TABLE_NAME COLUMN_NAME
-------------------- -------------------- --------------------
SCOTT BONUS JOB
SCOTT BONUS ENAME
так что, кажется, работает нормально (хотя на других схемах я иногда сталкиваюсь с ошибкой... Я посмотрю, смогу ли я понять, что это такое).
В этом случае таблица пуста (нет строк!) — это один из примеров «ложного срабатывания», который вы можете обнаружить. (В более общем случае вы получите ложное срабатывание, если все в столбце VARCHAR2 равно null
— во всех строках таблицы.)
ЗАМЕТЬТЕ также, что столбец может иметь только числовые значения, и все же лучшим типом данных будет VARCHAR2. Это тот случай, когда значения являются просто идентификаторами и не подразумеваются как «числа» (которые мы можем сравнивать друг с другом или с фиксированными значениями и/или с которыми мы можем производить арифметические действия). Пример — SSN (номер социального страхования) или эквивалент в других странах; SSN является «официальным» идентификатором каждого человека для ведения бизнеса с правительством. SSN является числовым (на самом деле, возможно, чтобы подчеркнуть тот факт, что он НЕ должен быть «номером», несмотря на имя, он часто пишется с парой дефисов...)
person
mathguy
schedule
18.12.2017
'123 '
) считать числом? - person mathguy   schedule 18.12.20171.5
тоже не является числом? Как насчет-33
? Ваше текущее решение не будет рассматривать их как числа. Как насчет положительных целых чисел, представленных в экспоненциальной записи?'1.0E+03'
равно 1000 в экспоненциальном представлении. - person mathguy   schedule 18.12.2017