Ermitteln Sie, ob der Wert in MySQL eine Zahl ist

159

Gibt es eine Möglichkeit zu erkennen, ob ein Wert eine Zahl in einer MySQL-Abfrage ist? Sowie

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true
Urbycoz
quelle
Ich habe die 1 * col = col-Strategie getestet, aber irgendwie schlägt sie fehl, wenn die Abfrage über PHP aufgerufen wird (und gibt true zurück, wenn dies nicht der Fall sein sollte). In phpMyAdmin funktioniert der Hack jedoch. Dies bedeutet, dass sich mein Test wie erwartet verhält, meine Anwendung nicht zu kaufen.
Jahaziel

Antworten:

249

Dies sollte in den meisten Fällen funktionieren.

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

Es funktioniert nicht für nicht standardmäßige Zahlen wie

  • 1e4
  • 1.2e5
  • 123. (nachgestellte Dezimalstelle)
RichardTheKiwi
quelle
Danke dir. Leider muss ich erkennen, dass 123 eine Zahl ist, 123X jedoch nicht.
Urbycoz
1
@ Richard- Ich habe gerade die Ausnahmen gelesen, die du gegeben hast. Ich dachte du meinst das Zeichen "e". Ich verstehe, was du jetzt meinst.
Urbycoz
Führende Nullen sind kein Problem für einen geschickten SQL-Entwickler - Trim (führende 0 von Spalte 1)
Pimbrouwers
Ich weiß, dass es ein alter Beitrag ist, aber ich verwende diese Methode in meiner Abfrage. Aber ich habe ein Problem, es erkennt "2-Power" als "2" und verursacht Probleme, da es das nicht tun soll. Irgendeine Idee ?
GRosay
1
Für nachfolgende und führende Nullen (z. B. 023.12000): concat ('', col1 * 1) = '0' ODER concat ('', col1 * 1) = IF (LOCATE ('.', Col1), TRIM (BOTH ') 0 'FROM col1), TRIM (LEADING' 0 'FROM col1));
François Breton
298

Sie können auch den regulären Ausdruck verwenden ... es wäre wie folgt:

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

Referenz: http://dev.mysql.com/doc/refman/5.1/en/regexp.html

T. Ecke
quelle
70
SELECT * FROM myTable WHERE col1 REGEXP '^ [0-9] + $';
Dmitriy Kozmenko
6
Die akzeptierte Antwort ist wirklich klug, aber diese Antwort ist direkter, und ich denke, es sollte die akzeptierte Lösung sein.
Pedromanoel
21
Für den Fall "stimmt nicht überein": WHERE col1 NOT REGEXP...und für den Fall, dass Sie möglicherweise einen Dezimalpunkt haben, verwenden Sie Regex:^[0-9\.]+$
Robbie Averill
2
Funktioniert auch nicht für wissenschaftliche Notation, sondern nur für Ints
David Wilkins
1
Regex könnte für Leute, die es nie benutzt haben, schwer zu lesen sein, aber Sie können wirklich großartige und kurze Dinge damit machen
Olli
56

Wenn Ihre Daten 'test', 'test0', 'test1111', '111test', '111' sind.

So wählen Sie alle Datensätze aus, bei denen die Daten ein einfaches int sind:

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

Ergebnis: '111'

(In Regex bedeutet ^ Anfang und $ bedeutet Ende)

So wählen Sie alle Datensätze aus, in denen eine Ganzzahl oder eine Dezimalzahl vorhanden ist:

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

Ergebnis: '111' (wie letztes Beispiel)

Verwenden Sie Folgendes, um alle Datensätze auszuwählen , in denen eine Nummer vorhanden ist:

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

Ergebnis: 'test0' und 'test1111' und '111test' und '111'

Dmitriy Kozmenko
quelle
Ich mag diesen Ansatz besser, weil er klarer und weniger "hackisch" ist als der Verkettungstrick. Vielen Dank!
Brokethebuildagain
8
Funktioniert nicht für negative Werte. Ich würde den vorgeschlagenen regulären Ausdruck wie folgt ändern:REGEXP '^[+\-]?[0-9]+\\.?[0-9]*$'
Nicolas
Ich würde sagen, das "+" Symbol ist nicht notwendig, Sie könnten nur ein "-?" Verwenden, aber wenn Sie es verwenden möchten, sollten Sie es maskieren (und das "-" Symbol muss nicht maskiert werden). .
T. Corner
13
SELECT * FROM myTable
WHERE col1 REGEXP '^[+-]?[0-9]*([0-9]\\.|[0-9]|\\.[0-9])[0-9]*(e[+-]?[0-9]+)?$'

Passt auch zu signierten Dezimalstellen (wie -1,2, +0,2, 6, 2e9, 1,2e-10) ).

Prüfung:

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;

Ergebnis:

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

Demo

Paul Spiegel
quelle
3
Perfekt! Nur Antwort, die tatsächlich alle Grundlagen abdeckt. Sollte die akzeptierte Antwort sein.
Dom
10

Gibt numerische Zeilen zurück

Ich habe die Lösung mit folgender Abfrage gefunden und arbeite für mich:

SELECT * FROM myTable WHERE col1 > 0;

Diese Abfrage gibt Zeilen zurück, deren Spalte nur größer als Null ist col1

Gibt nicht numerische Zeilen zurück

Wenn Sie die nicht numerische Spalte überprüfen möchten, versuchen Sie dies mit dem Trick ( !col1 > 0):

SELECT * FROM myTable WHERE !col1 > 0;
Bora
quelle
Dies funktioniert nicht. Wenn Sie eine Zeichenfolge haben, die mit der Zahl "123abc" beginnt, wird diese in Ihrer Anweisung für numerische Zeilen und nicht in der nicht numerischen Anweisung zurückgegeben.
JStephen
@JStephen Du hast recht! Da die SELECT * FROM myTable WHERE col1 = 123;Abfrage Zeilen zurückgibt, ist sogar der Spaltenwert123abc
Bora
9

Diese Antwort ähnelt Dmitry, lässt jedoch Dezimalstellen sowie positive und negative Zahlen zu.

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

Verwenden Sie eine UDF (benutzerdefinierte Funktion).

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

Dann, wenn Sie abfragen

select isnumber('383XXXX') 

- gibt 0 zurück

select isnumber('38333434') 

- kehrt zurück 1

Wählen Sie isnumber (mycol) mycol1, col2, colx aus tablex aus. - gibt 1s und 0s für die Spalte mycol1 zurück

- Sie können die Funktion zum Aufnehmen von Dezimalstellen, wissenschaftlichen Notationen usw. verbessern.

Der Vorteil der Verwendung einer UDF besteht darin, dass Sie sie auf der linken oder rechten Seite Ihres "where-Klausel" -Vergleichs verwenden können. Dies vereinfacht Ihr SQL erheblich, bevor es an die Datenbank gesendet wird:

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

hoffe das hilft.

Hugo R.
quelle
5

Eine andere Alternative, die auf meinem Computer schneller als REGEXP zu sein scheint, ist

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

Dadurch werden alle Zeilen ausgewählt, in denen col1 mit einem numerischen Wert beginnt.

Stian Hvatum
quelle
2
Was ist, wenn der Wert Null ist?
Urbycoz
1
Ich denke, Sie könnten einfach hinzufügen AND col1<>0, um diese Ausnahme zu behandeln.
Urbycoz
Es ist wahr, dass es nicht für Nullwerte funktioniert, aber es funktioniert perfekt für gepolsterte Zahlen, z. B. 004. Die akzeptierte Antwort funktioniert nicht für gepolsterte Zahlen
Abbas
Ich denke, dies ist der beste Weg, um nach Zahlen zu suchen. Es ist nur so, dass wir eine OR-Anweisung hinzufügen müssen, um Null zu prüfen, als SELECT * FROM myTable WHERE col1 * 0! = Col1 OR col1 = '0';
Binu Raman
Ich bekomme ein falsches Positiv für '1a'. Übrigens: es ist äquivalent zu WHERE col1 <> 0- rextester.com/DJIS1493
Paul Spiegel
4

Diese einfache Version fehlt noch:

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

(Addition sollte als Multiplikation schneller sein)

Oder langsamste Version zum weiteren Spielen:

SELECT *, 
CASE WHEN `col1` + 0 = `col1` THEN 1 ELSE 0 END AS `IS_NUMERIC` 
FROM `myTable`
HAVING `IS_NUMERIC` = 1
Jirka Kopřiva
quelle
3
Sofern ich nicht falsch verstehe, konvertiert MySQL eine beliebige Zeichenfolge in eine 0, sodass nicht zwischen Zeichenfolgen und Zahlen unterschieden wird. Beide geben dasselbe zurück.
Ivan McA
3
'a' + 0 = 'a'ist WAHR
Paul Spiegel
3

Ich empfehle: Wenn Ihre Suche einfach ist, können Sie `verwenden

column*1 = column

`Operator interessant :) ist Arbeit und schneller als auf Feldern varchar / char

SELECT * FROM myTable WHERE Spalte * 1 = Spalte;

ABC*1 => 0 (NOT EQU **ABC**)
AB15*A => 15 (NOT EQU **AB15**)
15AB => 15 (NOT EQU **15AB**)
15 => 15 (EQUALS TRUE **15**)
Ferhat KOÇER
quelle
1
Ist Ihnen bewusst, dass in MySQL sowohl das select 'aaa123' >= 0als auch select '123aaa' >= 0true zurückgegeben werden?
Grzegorz Smulko
1
SELECT * FROM myTable WHERE sign (col1)!=0

Natürlich ist das Vorzeichen (0) Null, aber dann können Sie Ihre Abfrage auf ... beschränken.

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

UPDATE: Dies ist nicht 100% zuverlässig, da "1abc" das Vorzeichen 1 zurückgeben würde, "ab1c" jedoch Null zurückgeben würde. Dies könnte also nur für Text funktionieren, der nicht mit Zahlen beginnt.

Miguel
quelle
0

Sie können mit tun CAST

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

Ich habe festgestellt, dass dies ganz gut funktioniert

if(col1/col1= 1,'number',col1) AS myInfo
Mike der Elf
quelle
Es ist das gleiche wie zu überprüfen col1 <> 0und gibt ein falsches Positiv für 1a- rextester.com/HLORBZ1242
Paul Spiegel
-1

Versuchen Sie zu teilen / 1

select if(value/1>0 or value=0,'its a number', 'its not a number') from table
Diego Guidobono
quelle