查找不是数字​​或预定义字符串的值

Posted

技术标签:

【中文标题】查找不是数字​​或预定义字符串的值【英文标题】:Find value that is not a number or a predefined string 【发布时间】:2022-01-08 00:54:57 【问题描述】:

我必须测试 sql 表的列是否存在无效值和 NULL。

有效值为:任意数字和字符串 'n.v.' (有和没有点,以及在我的 sql 命令中列出的所有可能的组合)

到目前为止,我已经尝试过:

select count(*)
from table1
where column1 is null
or not REGEXP_LIKE(column1, '^[0-9,nv,Nv,nV,NV,n.v,N.v,n.V,N.V]+$');

正则表达式还匹配单个字符值 'n'、'N'、'v'、'V'(带有和不带有后面的点)。这不应该是这种情况,因为我只希望匹配 sql 命令中写入的确切字符组合。我猜这个问题与使用 REGEXP_LIKE 有关。有什么想法吗?

【问题讨论】:

【参考方案1】:

我猜这个正则表达式会起作用:

NOT REGEXP_LIKE(column1, '^([0-9]+|n\.?v\.?)$', 'i')

请注意,, 不是分隔符,. 表示任何字符,\. 表示点字符本身,'i' 标志可用于忽略大小写而不是硬编码所有大小写组合字符。

【讨论】:

【参考方案2】:

无需使用regexp(大数据会提高性能)- 普通的旧TRANSLATE 足以进行验证。

请注意,第一个translate(column1,'x0123456789','x') 会从字符串中删除所有数字字符,因此如果以null 结尾,则字符串是可以的。

第二个translate(lower(column1),'x.','x')lowered 字符串中删除所有,因此您期望得到nv 的结果。 为了避免n.....v.... 的情况,您还限制了字符串长度。

select 
  column1,
  case when 
     translate(column1,'x0123456789','x') is null or /* numeric string */
     translate(lower(column1),'x.','x') = 'nv' and length(column1) <= 4 then 'OK' 
  end as status   
from table1

COLUMN1   STATUS
--------- ------
1010101   OK
1012828n    
1012828nv   
n.....v....          
n.V       OK

测试数据

create table table1 as
select '1010101' column1 from dual union all -- OK numbers
select '1012828n' from dual union all        -- invalid
select '1012828nv' from dual union all       -- invalid
select 'n.....v....' from dual union all     -- invalid
select 'n.V' from dual;                      -- OK nv

【讨论】:

【参考方案3】:

你可以使用:

select count(*)
from   table1
WHERE  TRANSLATE(column1, ' 0123456789', ' ') IS NULL 
OR     LOWER(column1) IN ('nv', 'n.v', 'nv.', 'n.v.');

其中,对于样本数据:

CREATE TABLE table1 (column1) AS
SELECT '12345' FROM DUAL UNION ALL
SELECT 'nv' FROM DUAL UNION ALL
SELECT 'NV' FROM DUAL UNION ALL
SELECT 'nV' FROM DUAL UNION ALL
SELECT 'n.V.' FROM DUAL UNION ALL
SELECT '...................n.V.....................' FROM DUAL UNION ALL
SELECT '..nV' FROM DUAL UNION ALL
SELECT 'n..V' FROM DUAL UNION ALL
SELECT 'nV..' FROM DUAL UNION ALL
SELECT 'xyz' FROM DUAL UNION ALL
SELECT '123nv' FROM DUAL;

输出:

COUNT(*)
5

或者,如果您想要任意数量的.,那么:

select count(*)
from   table1
WHERE  TRANSLATE(column1, ' 0123456789', ' ') IS NULL 
OR     REPLACE(LOWER(column1), '.') = 'nv';

哪些输出:

COUNT(*)
9

db小提琴here

【讨论】:

以上是关于查找不是数字​​或预定义字符串的值的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式

变量定义为字符串

python函数定义来查找列表中的所有值是不是都是奇数或都不是[关闭]

为啥C语言编程时输入数字转化为了ASC码

t-sql 用户定义函数,用表中的查找替换文本

AS3 数组中的多个值