If you ever encounter a character column that should be numeric, there’s always a possibility that it contains non-numeric data that you don’t know about.
For example, someone might have set up a Price
column as a varchar
column that should have been a numeric
column, and now you need to clean up after them. You might start by identifying all non-numeric data so that you can work out what to do with it before converting the column to a numeric type.
In SQL, you can run a query to return non-numeric data from the column. The query you use will largely depend on your DBMS.
SQL Server
SQL Server has an ISNUMERIC()
function that returns 1
for numeric values and 0
for non-numeric values.
Here’s an example of using this function to return just the non-numeric values from a column:
SELECT c1
FROM t1
WHERE ISNUMERIC(c1) <> 1;
Here, c1
is a varchar
column (that may or may not contain numeric data) and t1
is the table.
In this case we used ISNUMERIC()
in a WHERE
clause to narrow the query results to just those where the result of ISNUMERIC(c1)
is not 1
.
Another way to do it would be to use = 0
instead of <> 1
.
Oracle
In Oracle, we can negate the REGEXP_LIKE()
function with a regular expression pattern:
SELECT c1
FROM t1
WHERE NOT REGEXP_LIKE(c1, '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$');
The regex pattern matches floating point numbers, and so we negated it with NOT
.
Matching non-integers can be done with a less complex pattern:
SELECT c1
FROM t1
WHERE NOT REGEXP_LIKE(c1, '^[0-9]+$');
MySQL
In MySQL, we can negate the REGEXP
operator:
SELECT c1
FROM t1
WHERE c1 NOT REGEXP '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$';
For non-integers, we can use the same pattern that we used in the Oracle example for matching non-integers:
SELECT c1
FROM t1
WHERE c1 NOT REGEXP '^[0-9]+$';
MariaDB
In MariaDB, we can negate its implementation of the REGEXP
operator:
SELECT c1
FROM t1
WHERE c1 NOT REGEXP '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$';
And for non-integers:
SELECT c1
FROM t1
WHERE c1 NOT REGEXP '^[0-9]+$';
PostgreSQL
Here’s the Postgres version:
SELECT c1
FROM t1
WHERE c1 !~ '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$';
And for non-integers:
SELECT c1
FROM t1
WHERE c1 !~ '^[0-9]+$';
SQLite
In SQLite, we have a couple of options. We can use the typeof()
function to filter the results to just numeric types (real
and integer
), then negate that:
SELECT c1
FROM t1
WHERE typeof(c1) <> 'integer'
AND typeof(c1) <> 'real';
In this case we can remove the AND
operator to limit it to just non-integers.
Alternatively, we could use typeof()
to check for only types of null
, text
, or blob
.
If we prefer to use a regex pattern, we can apply that with the REGEXP
function:
SELECT c1
FROM t1
WHERE c1 NOT REGEXP '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$';
For non-integers, we can apply the same pattern as with the previous examples for non-integers.