在 varchar 列中进行数字比较

Compare numerically in varchar column

我需要在 PostgreSQL 数据库上编写 HQL 查询(如果可能,不是本机 SQL),选择 attr 值大于 39 的行。问题是attr 列是一个 varchar 列,不仅包含数字。我只需要数字并且只需要大于 39。适用于我的本机查询如下:

SELECT * FROM my_table WHERE attr ~ '^[0-9\.]+$' AND CAST(attr AS BIGINT) > 39;

我尝试了以下 HQL 等价物(none 有效):

1. SELECT myTable FROM MyTable myTable WHERE attr ~ '^[0-9\.]+$' AND CAST(attr AS long) > 39; //~ cannot be used in HQL query
2. SELECT myTable FROM MyTable myTable WHERE ISNUMERIC(attr) = 1 AND CAST(attr AS long) > 39; //cannot extract result set
3. SELECT myTable FROM MyTable myTable WHERE attr LIKE '^[0-9\.]+$' AND CAST(attr AS long) > 39; //cannot extract result set
4. SELECT myTable FROM MyTable myTable WHERE CAST(attr AS long) > 39; //cannot extract result set
5. SELECT myTable FROM MyTable myTable WHERE attr > '39'; //wrong data types - rows with 4 in the attr column are found

你可以应用这个技巧:

SUBSTRING(
  CONCAT('00000000000000000000', attr), 
  LENGTH(attr) + 1, 
  20
) > '00000000000000000039'

我使用了 20 0 位的随机数。如果 attr 中的数字更大,则需要进行调整。这不会处理 attr 可能匹配的字符串数据,但我相信您还有一些其他列可以帮助您更可靠地解释 attr 列内容。

但当然,我肯定会首先停止使用 EAV 反模式,and/or 使用适当的数据类型...

尝试创建一个像这样的 PostgreSQL 函数:

CREATE FUNCTION parse_attr_to_boolean(attr character varying) RETURNS BOOLEAN AS $$
        BEGIN
                RETURN attr ~ '^[0-9\.]+$' AND CAST(attr AS BIGINT) > 39;
        END;
$$ LANGUAGE plpgsql;

现在,您只需在 HQL 查询中调用函数即可:

SELECT t 
FROM MyTable t 
WHERE parse_attr_to_boolean(t.attr)

只需要注册SQL函数,如parse_attr_to_boolean,如果函数在SELECT子句中使用。但是,由于您在 WHERE 子句中使用它,它可以按原样传递给 SQL 查询。