比較するために、Oracle(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
それを確認する方法についてのアイデアはありますか?
myTable
のID列がNUMBERとして宣言されていないと仮定すると(これは奇妙な選択であり、問題があると思われます)、(おそらくVARCHAR2)IDを数値に変換しようとする関数を記述できます、例外をキャッチし、「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クエリでそのような関数を使用することはできません。
here に言及したもう1つのアイデアは、正規表現を使用して確認することです。
SELECT foo
FROM bar
WHERE REGEXP_LIKE (foo,'^[[:digit:]]+$');
良い点は、別のPL/SQL関数が必要ないことです。問題となる可能性のある部分は、正規表現が多数の行に対して最も効率的な方法ではない可能性があることです。
REGEXP_LIKE
を使用したSaishの答えは正しい考えですが、浮動小数点数はサポートしていません。これは...
数値の戻り値
SELECT foo
FROM bar
WHERE REGEXP_LIKE (foo,'^-?\d+(\.\d+)?$');
数値ではない戻り値
SELECT foo
FROM bar
WHERE NOT REGEXP_LIKE (foo,'^-?\d+(\.\d+)?$');
http://regexpal.com/ (ただし、改行で一致するチェックボックスを選択してくださいこのため。
これは、 Oracleに数値データを含まない行を見つける の潜在的な重複です。次も参照してください: SQLで文字列が数値であるかどうかを確認する方法は? .
Michael Durrant's に基づく解決策は、整数に対して機能します。
SELECT foo
FROM bar
WHERE DECODE(TRIM(TRANSLATE(your_number,'0123456789',' ')), NULL, 'number','contains char') = 'number'
Adrian Carneiro 小数などで機能するソリューションを投稿しました。ただし、Justin Caveが指摘したように、これにより「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を使用しないソリューションが必要な場合、これが役立つ場合があります。
次のように、Oracle(10g)で正規表現関数「regexp_like」を使用できます。
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
私は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
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は数字とは見なされないことに注意してください。しかし、正規表現をいつでも変更して反対のことを達成できます。
これは、番号ではないすべてのものを見つけるための私のクエリです:
Select myVarcharField
From myTable
where not REGEXP_LIKE(myVarcharField, '^(-)?\d+(\.\d+)?$', '')
and not REGEXP_LIKE(myVarcharField, '^(-)?\d+(\,\d+)?$', '');
私の分野で私はしました。そして、悲しいことに、10進数はそれを考慮に入れなければなりませんでした。
列はどのように定義されていますか? varcharフィールドの場合、数値ではありません(または1として格納されます)。 Oracleは変換を実行できる場合があります(たとえば、charField = 0のsomeTableから*を選択します)が、変換が成立し、可能な場合にのみ行を返します。これは、理想的なパフォーマンスとはほど遠いです。
したがって、数値比較を行い、この列を数値として扱いたい場合、おそらく数値として定義する必要がありますか?
とはいえ、ここであなたができることは次のとおりです。
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が無効な数値と見なす行は返されません。
乾杯。
@JustinCave-「when other」の「when value_error」の置き換えは、上記のアプローチに対する素晴らしい改良です。このわずかな追加のTweakは、概念的には同じですが、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;
「riskier」REGEXPアプローチを使用してOracleの数値形式ロジックをエミュレートすることを好む人にも注意してください。NLS_NUMERIC_CHARACTERSとNLS_TERRITORYを考慮することを忘れないでください。
まあ、is_number関数を作成して呼び出すと、コードが機能します。
create or replace function is_number(param varchar2) return boolean
as
ret number;
begin
ret := to_number(param);
return true;
exception
when others then return false;
end;
編集:ジャスティンの答えに従ってください。純粋なSQL呼び出しの詳細を忘れていました。
この例を使用できます
SELECT NVL((SELECT 1 FROM DUAL WHERE REGEXP_LIKE (:VALOR,'^[[:digit:]]+$')),0) FROM DUAL;