MySQLで値が数値かどうかを検出


159

MySQLクエリの値が数値であるかどうかを検出する方法はありますか?といった

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true

1 * col = col戦略をテストしましたが、PHPを介してクエリが呼び出されると、どういうわけか失敗します(そうでない場合はtrueを返します)。ただし、phpMyAdminではハックが機能します。つまり、私のテストは期待どおりに動作しますが、アプリケーションを購入すると動作しません。
Jahaziel

回答:


249

これはほとんどの場合に機能します。

SELECT * FROM myTable WHERE concat('',col1 * 1) = col1

次のような非標準の番号では機能しません

  • 1e4
  • 1.2e5
  • 123. (末尾10進数)

ありがとうございました。残念ながら、123は数値ですが、123Xはそうでないことを認識する必要があります。
Urbycoz、2011

1
@リチャード-私はあなたが与えた例外を読んだだけです。あなたは文字「e」を意味すると思った。私はあなたが今何を意味するかを理解しています。
Urbycoz、2011

先行ゼロは、巧妙なSQL開発者にとって問題ではありません--- trim(col1から先行0)
pimbrouwers 2014年

私はそれが古い投稿であることを知っていますが、クエリでこのメソッドを使用します。しかし、問題があります。 "2-Power"が "2"として検出され、問題を引き起こしていないため、問題が発生します。何か案が ?
GRosay、2015年

1
後続ゼロと先行ゼロ(例:023.12000)の場合:concat( ''、col1 * 1)= '0' OR concat( ''、col1 * 1)= IF(LOCATE( '。'、col1)、TRIM(BOTH ' 0 'FROM col1)、TRIM(LEADING' 0 'FROM col1));
フランソワ・ブルトン

298

正規表現も使用できます...次のようになります。

SELECT * FROM myTable WHERE col1 REGEXP '^[0-9]+$';

リファレンス: http : //dev.mysql.com/doc/refman/5.1/en/regexp.html


70
SELECT * FROM myTable WHERE col1 REGEXP '^ [0-9] + $';
Dmitriy Kozmenko 2013年

6
受け入れられた答えは本当に賢いですが、この答えはより直接的であり、私はそれが受け入れられた解決策であるべきだと思います。
pedromanoel 2013年

21
「一致しない」の場合には:WHERE col1 NOT REGEXP...、あなたは小数点を持っているかもしれない場合のために、使用の正規表現:^[0-9\.]+$
ロビーエーヴリル

2
また、科学表記法では機能せず、intでのみ機能します
David Wilkins、

1
Regex migthは、これを使用したことがない人には読みにくいですが、これを使うと本当に素晴らしい短い作業を行うことができます
Olli

56

データが「test」、「test0」、「test1111」、「111test」、「111」の場合

データが単純なintであるすべてのレコードを選択するには:

SELECT * 
FROM myTable 
WHERE col1 REGEXP '^[0-9]+$';

結果: '111'

(正規表現では、^は開始を意味し、$は終了を意味します)

整数または10進数が存在するすべてのレコードを選択するには:

SELECT * 
FROM myTable 
WHERE col1 REGEXP '^[0-9]+\\.?[0-9]*$'; - for 123.12

結果: '111'(最後の例と同じ)

最後に、 numberが存在するすべてのレコードを選択するには、これを使用します。

SELECT * 
FROM myTable 
WHERE col1 REGEXP '[0-9]+';

結果:「test0」と「test1111」と「111test」と「111」


連結トリックよりも明確で「ハッキリ」が少ないため、このアプローチの方が好きです。ありがとう!
2013年

8
負の値では機能しません。次のように私が提案した正規表現を修正したい:REGEXP '^[+\-]?[0-9]+\\.?[0-9]*$'
ニコラ・

「+」記号は不要で、「-?」だけを使用できますが、使用する場合はエスケープする必要があります(「-」記号はエスケープする必要はありません)。 。
T.コーナー

13
SELECT * FROM myTable
WHERE col1 REGEXP '^[+-]?[0-9]*([0-9]\\.|[0-9]|\\.[0-9])[0-9]*(e[+-]?[0-9]+)?$'

符号付き10進数にも一致します(-1.2、+ 0.2、6、2e9、1.2e-10など)。

テスト:

drop table if exists myTable;
create table myTable (col1 varchar(50));
insert into myTable (col1) 
  values ('00.00'),('+1'),('.123'),('-.23e4'),('12.e-5'),('3.5e+6'),('a'),('e6'),('+e0');

select 
  col1,
  col1 + 0 as casted,
  col1 REGEXP '^[+-]?[0-9]*([0-9]\\.|[0-9]|\\.[0-9])[0-9]*(e[+-]?[0-9]+)?$' as isNumeric
from myTable;

結果:

col1   |  casted | isNumeric
-------|---------|----------
00.00  |       0 |         1
+1     |       1 |         1
.123   |   0.123 |         1
-.23e4 |   -2300 |         1
12.e-5 | 0.00012 |         1
3.5e+6 | 3500000 |         1
a      |       0 |         0
e6     |       0 |         0
+e0    |       0 |         0

デモ


3
パーフェクト!実際にすべての拠点をカバーする回答のみ。受け入れられる答えでなければなりません。
Dom

10

数値行を返します

私は次のクエリで解決策を見つけ、私のために働きました:

SELECT * FROM myTable WHERE col1 > 0;

このクエリは、0より大きい列のみを持つ行を返します。 col1

非数値行を返します

数値ではない列をチェックしたい場合は、トリック(!col1 > 0)でこれを試してください:

SELECT * FROM myTable WHERE !col1 > 0;

これは機能しません。「123abc」という数字で始まる文字列がある場合、それは数値行ステートメントで返され、非数値ステートメントでは返されません。
JStephen

@JStephenそうですね!SELECT * FROM myTable WHERE col1 = 123;クエリはcolの値が次の場合でも行を返すため123abc
Bora

9

この回答はDmitryに似ていますが、正数と負数だけでなく小数も許可されます。

select * from table where col1 REGEXP '^[[:digit:]]+$'

8

UDF(ユーザー定義関数)を使用します。

CREATE FUNCTION isnumber(inputValue VARCHAR(50))
  RETURNS INT
  BEGIN
    IF (inputValue REGEXP ('^[0-9]+$'))
    THEN
      RETURN 1;
    ELSE
      RETURN 0;
    END IF;
  END;

次に、クエリを実行すると

select isnumber('383XXXX') 

-0を返します

select isnumber('38333434') 

-戻り値1

tablexからisnumber(mycol)mycol1、col2、colxを選択します。-列mycol1に1と0を返します

-小数、科学表記などを使用するように関数を拡張できます。

UDFを使用する利点は、「where句」比較の左側または右側で使用できることです。これにより、SQLがデータベースに送信される前に大幅に簡素化されます。

 SELECT * from tablex where isnumber(columnX) = isnumber('UnkownUserInput');

お役に立てれば。


5

私のコンピュータではREGEXPよりも高速に見える別の方法は

SELECT * FROM myTable WHERE col1*0 != col1;

これにより、col1が数値で始まるすべての行が選択されます。


2
値がゼロの場合はどうでしょうか?
Urbycoz 2014年

1
あなたはAND col1<>0その例外を処理するために単に追加できると思います。
Urbycoz 2014年

ゼロ値では機能しないことは事実ですが、埋め込み番号(例:004)では完全に機能します。受け入れられた回答は埋め込み番号では機能しません
Abbas

これが数字をチェックする最良の方法だと思います。SELECT * FROM myTable WHERE col1 * 0!= col1 OR col1 = '0';のように、ゼロをチェックするためのORステートメントを追加する必要があるだけです。
Binu Raman

の誤検知が発生し'1a'ます。ところで:それはと同等だWHERE col1 <> 0- rextester.com/DJIS1493
ポール・シュピーゲル

4

この単純なバージョンがまだありません:

SELECT * FROM myTable WHERE `col1` + 0 = `col1`

(足し算は掛け算として速くなるはずです)

またはさらに再生するための最も遅いバージョン:

SELECT *, 
CASE WHEN `col1` + 0 = `col1` THEN 1 ELSE 0 END AS `IS_NUMERIC` 
FROM `myTable`
HAVING `IS_NUMERIC` = 1

3
私が誤解していない限り、MySQLは文字列を0に変換するため、これは文字列と数値を区別せず、どちらも同じ値を返します。
Ivan McA 2017年

3
'a' + 0 = 'a'is TRUE
Paul Spiegel

3

私はお勧めします:検索が単純な場合は、 `

column*1 = column

`興味深いオペレータ:)は機能し、フィールドvarchar / charよりも高速です。

SELECT * FROM myTable WHERE column * 1 = column;

ABC*1 => 0 (NOT EQU **ABC**)
AB15*A => 15 (NOT EQU **AB15**)
15AB => 15 (NOT EQU **15AB**)
15 => 15 (EQUALS TRUE **15**)

1
MySQLではselect 'aaa123' >= 0との両方がselect '123aaa' >= 0true を 返すことを知っていますか?
Grzegorz Smulko 16

1
SELECT * FROM myTable WHERE sign (col1)!=0

もちろん、sign(0)はゼロですが、クエリを次のように制限できます...

SELECT * FROM myTable WHERE sign (col1)!=0 or col1=0

更新:「1abc」は1の符号を返すため、これは100%信頼できるわけではありませんが、「ab1c」はゼロを返します...したがって、これは、数字で始まらないテキストに対してのみ機能します。


0

あなたは使うことができます CAST

  SELECT * from tbl where col1 = concat(cast(col1 as decimal), "")


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.