проверить, есть ли в Oracle функция «это число» - PullRequest
35 голосов
/ 22 февраля 2011

Я пытаюсь проверить, является ли значение из столбца в запросе оракула (10g) числом, чтобы сравнить его.Что-то вроде:

select case when ( is_number(myTable.id) and (myTable.id >0) ) 
            then 'Is a number greater than 0' 
            else 'it is not a number' 
       end as valuetype  
  from table myTable

Есть идеи, как это проверить?

Ответы [ 16 ]

61 голосов
/ 19 марта 2012

Еще одна идея, упомянутая здесь , заключается в использовании регулярного выражения для проверки:

SELECT  foo 
FROM    bar
WHERE   REGEXP_LIKE (foo,'^[[:digit:]]+$');

Приятная часть в том, что вам не нужна отдельная функция PL / SQL.Потенциально проблемная часть заключается в том, что регулярное выражение может быть не самым эффективным методом для большого числа строк.

32 голосов
/ 22 февраля 2011

Предполагая, что столбец идентификатора в myTable не объявлен как NUMBER (что выглядит странным выбором и может быть проблематичным), вы можете написать функцию, которая пытается преобразовать (предположительно VARCHAR2) идентификатор в число, перехватывает исключение и возвращает «Y» или «N».Что-то вроде

CREATE OR REPLACE FUNCTION is_number( p_str IN VARCHAR2 )
  RETURN VARCHAR2 DETERMINISTIC PARALLEL_ENABLE
IS
  l_num NUMBER;
BEGIN
  l_num := to_number( p_str );
  RETURN 'Y';
EXCEPTION
  WHEN value_error THEN
    RETURN 'N';
END is_number;

Затем вы можете встроить этот вызов в запрос, т.е.

SELECT (CASE WHEN is_number( myTable.id ) = 'Y' AND myTable.id > 0 
               THEN 'Number > 0'
             ELSE 'Something else'
         END) some_alias
  FROM myTable

Обратите внимание, что, хотя PL / SQL имеет логический тип данных, SQL этого не делает.Таким образом, хотя вы можете объявить функцию, которая возвращает логическое значение, вы не можете использовать такую ​​функцию в запросе SQL.

15 голосов
/ 28 августа 2013

Ответ Саиша с использованием REGEXP_LIKE является правильной идеей, но не поддерживает плавающие числа. Этот будет ...

Возвращаемые значения, которые являются числовыми

SELECT  foo 
FROM    bar
WHERE   REGEXP_LIKE (foo,'^-?\d+(\.\d+)?$');

Возвращаемые значения не числовые

SELECT  foo 
FROM    bar
WHERE   NOT REGEXP_LIKE (foo,'^-?\d+(\.\d+)?$');

Вы можете сами проверять свои регулярные выражения до тех пор, пока ваше сердце не наполнится http://regexpal.com/ (но убедитесь, что вы установили флажок совпадать с разрывом строки для этого).

5 голосов
/ 14 января 2013

Это потенциальный дубликат Поиск строк, которые не содержат числовых данных в Oracle . См. Также: Как определить, является ли строка числовой в SQL? .

Вот решение на основе Майкла Дарранта , которое работает для целых чисел.

SELECT foo
FROM bar
WHERE DECODE(TRIM(TRANSLATE(your_number,'0123456789',' ')), NULL, 'number','contains char') = 'number'

Адриан Карнейро опубликовал решение, которое работает для десятичных и других. Однако, как указал Джастин Кейв, это неправильно классифицирует строки, такие как «123.45.23.234» или «131 + 234».

SELECT foo
FROM bar
WHERE DECODE(TRIM(TRANSLATE(your_number,'+-.0123456789',' ')), NULL, 'number','contains char') = 'number'

Если вам нужно решение без PL / SQL или REGEXP_LIKE, это может помочь.

5 голосов
/ 20 апреля 2012

Вы можете использовать функцию регулярного выражения 'regexp_like' в ORACLE (10g), как показано ниже:

select case
       when regexp_like(myTable.id, '[[:digit:]]') then
        case
       when myTable.id > 0 then
        'Is a number greater than 0'
       else
        'Is a number less than or equal to 0'
     end else 'it is not a number' end as valuetype
from table myTable
2 голосов
/ 23 февраля 2011

Я против использования when others, поэтому я бы использовал (возвращая "логическое целое число" из-за того, что SQL не поддерживает логические значения)

create or replace function is_number(param in varchar2) return integer
 is
   ret number;
 begin
    ret := to_number(param);
    return 1; --true
 exception
    when invalid_number then return 0;
 end;

В вызове SQL вы должны использовать что-то вроде

select case when ( is_number(myTable.id)=1 and (myTable.id >'0') ) 
            then 'Is a number greater than 0' 
            else 'it is not a number or is not greater than 0' 
       end as valuetype  
  from table myTable
1 голос
/ 22 января 2016

Это мой запрос, чтобы найти все те, которые НЕ являются числами:

Select myVarcharField
From myTable
where not REGEXP_LIKE(myVarcharField, '^(-)?\d+(\.\d+)?$', '')
and not REGEXP_LIKE(myVarcharField, '^(-)?\d+(\,\d+)?$', '');

В моем поле я.и, к сожалению, десятичные числа должны были принять это во внимание, иначе вам нужно только одно из ограничений.

1 голос
/ 25 апреля 2014

@ JustinCave - замена «когда значение» для «когда другие» является хорошим дополнением к вашему подходу выше. Эта небольшая дополнительная настройка, хотя концептуально та же самая, устраняет необходимость определения и последующего выделения памяти для вашей переменной l_num:

function validNumber(vSomeValue IN varchar2)
     return varchar2 DETERMINISTIC PARALLEL_ENABLE
     is
begin
  return case when abs(vSomeValue) >= 0 then 'T' end;
exception
  when value_error then
    return 'F';
end;

Просто замечание для тех, кто предпочитает эмулировать логику числового формата Oracle с использованием «более рискованного» подхода REGEXP, пожалуйста, не забудьте рассмотреть NLS_NUMERIC_CHARACTERS и NLS_TERRITORY.

1 голос
/ 17 сентября 2012
CREATE OR REPLACE FUNCTION is_number(N IN VARCHAR2) RETURN NUMBER IS
  BEGIN
    RETURN CASE regexp_like(N,'^[\+\-]?[0-9]*\.?[0-9]+$') WHEN TRUE THEN 1 ELSE 0 END;
END is_number;

Обратите внимание, что 45e4 не будет рассматриваться как число, но вы всегда можете изменить регулярное выражение для достижения противоположного.

1 голос
/ 22 февраля 2011

Как определяется столбец?Если это поле varchar, то это не число (или оно хранится как единое целое).Oracle может выполнить преобразование для вас (например, выбрать * из someTable, где charField = 0), но оно будет возвращать только те строки, в которых преобразование выполнено и возможно.Это также далеко от идеальной ситуации с точки зрения производительности.

Итак, если вы хотите провести сравнение чисел и рассматривать этот столбец как число, возможно, его следует определить как число?

То естьвот что вы можете сделать:

create or replace function myToNumber(i_val in varchar2) return number is
 v_num number;
begin
 begin
   select to_number(i_val) into v_num from dual;
 exception
   when invalid_number then
   return null;
 end;
 return v_num;
end;

Вы также можете включить другие параметры, которые имеет обычный to_number.Используйте так:

select * from someTable where myToNumber(someCharField) > 0;

Он не вернет ни одной строки, которую Oracle считает недействительным числом.

Приветствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...