我需要确定给定的字符串是否可以在SQL语句中解释为数字(整数或浮点数)。如下所示:

SELECT AVG(CASE WHEN x ~ '^[0-9]*.?[0-9]*$' THEN x::float ELSE NULL END) FROM test

我发现Postgres的pattern matching可以用于此目的。因此,我修改了this place中给出的语句以合并浮点数。这是我的代码:
WITH test(x) AS (
    VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
    ('123.456'), ('abc'), ('1..2'), ('1.2.3.4'))

SELECT x
     , x ~ '^[0-9]*.?[0-9]*$' AS isnumeric
FROM test;

输出:
    x    | isnumeric
---------+-----------
         | t
 .       | t
 .0      | t
 0.      | t
 0       | t
 1       | t
 123     | t
 123.456 | t
 abc     | f
 1..2    | f
 1.2.3.4 | f
(11 rows)

如您所见,前两项(空字符串''和唯一句点'.')被错误分类为数字类型(不是)。目前,我无法对此进一步了解。任何帮助表示赞赏!

更新基于this answer(及其注释),我将该模式调整为:
WITH test(x) AS (
    VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
    ('123.456'), ('abc'), ('1..2'), ('1.2.3.4'), ('1x234'), ('1.234e-5'))

SELECT x
     , x ~ '^([0-9]+[.]?[0-9]*|[.][0-9]+)$' AS isnumeric
FROM test;

这使:
     x    | isnumeric
----------+-----------
          | f
 .        | f
 .0       | t
 0.       | t
 0        | t
 1        | t
 123      | t
 123.456  | t
 abc      | f
 1..2     | f
 1.2.3.4  | f
 1x234    | f
 1.234e-5 | f
(13 rows)

正如我现在看到的那样,科学计数法和负数仍然存在一些问题。

最佳答案

您可能已经注意到,基于正则表达式的方法几乎不可能正确执行。例如,您的测试表明1.234e-5实际上不是有效数字。另外,您错过了负数。如果某些东西看起来像数字,但是当您尝试存储它会导致溢出怎么办?

相反,我建议创建一个函数,该函数尝试实际转换为NUMERIC(如果任务需要,则转换为FLOAT),并根据转换是否成功返回TRUEFALSE

该代码将完全模拟ISNUMERIC()函数:

CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
    x = $1::NUMERIC;
    RETURN TRUE;
EXCEPTION WHEN others THEN
    RETURN FALSE;
END;
$$
STRICT
LANGUAGE plpgsql IMMUTABLE;

在数据上调用此函数将得到以下结果:
WITH test(x) AS ( VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
  ('123.456'), ('abc'), ('1..2'), ('1.2.3.4'), ('1x234'), ('1.234e-5'))
SELECT x, isnumeric(x) FROM test;

    x     | isnumeric
----------+-----------
          | f
 .        | f
 .0       | t
 0.       | t
 0        | t
 1        | t
 123      | t
 123.456  | t
 abc      | f
 1..2     | f
 1.2.3.4  | f
 1x234    | f
 1.234e-5 | t
 (13 rows)

如果数据实际上是数字,它不仅更正确,更容易阅读,而且还可以更快地工作。

关于regex - PostgreSQL的isnumeric(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16195986/

10-11 03:48