![](/img/trans.png)
[英]VARCHAR column with numeric and non-numeric data to be filtered by numeric comparasion in WHERE clause
[英]Finding non-numeric values in varchar column
要求:
通用查詢/函數,用於檢查表的varchar列中提供的值是否實際上是數字,並且精度不超過允許的精度。
可用值:
表名稱,列名稱,允許的精度,允許的比例
一般建議是創建一個函數並使用to_number()來驗證值,但不會驗證允許的長度(精度標度)。
我的解決方案:
使用Regexp驗證號碼NOT REGEXP_LIKE(COLUMN_NAME, '^-?[0-9.]+$')
驗證左部分的長度(小數點前)(我不知道它的實際名稱是什么),因為對於小數位數,oracle會根據需要自動舍入。 由於實際列為varchar,因此我將使用substr,instr在小數點左側找到該組件。
如上所述,Regexp允許使用123 ... 123124..55之類的數字,我還將驗證小數點的數量。 [如果> 1,則報錯]
查詢以查找無效號碼:
Select * From Table_Name
Where
(NOT REGEXP_LIKE(COLUMN_NAME, '^-?[0-9.]+$')
OR
Function_To_Fetch_Left_Component(COLUMN_NAME) > (Precision-Scale)
/* Can use regexp_substr now but i already had a function for that */
OR
LENGTH(Column_Name) - LENGTH(REPLACE(Column_Name,'.','')) > 1
/* Can use regexp_count aswell*/)
我對自己的解決方案感到滿意並感到滿意,直到一列只有“。”為止。 價值逃脫了我的支票,我看到了支票的局限性。 盡管添加另一個檢查來驗證這一點也可以解決我的問題,但是整個solution
對我而言似乎效率很低。
我將非常感謝更好的解決方案(以任何方式)。
提前致謝。
尋找:
像這樣:
Select *
From Table_Name
Where NOT REGEXP_LIKE(COLUMN_NAME, '^[+-]?(\d+(\.\d*)?|\.\d+)$')
如果您不想在數字字符串中使用零填充值,則:
Select *
From Table_Name
Where NOT REGEXP_LIKE(COLUMN_NAME, '^[+-]?(([1-9]\d*|0)(\.\d*)?|\.\d+)$')
具有精度和小數位數(假設它按照NUMBER( precision, scale )
數據類型和scale < precision
起作用):
Select *
From Table_Name
Where NOT REGEXP_LIKE(COLUMN_NAME, '^[+-]?(\d{1,'||(precision-scale)||'}(\.\d{0,'||scale||'})?|\.\d{1,'||scale||'})$')
或者,對於具有精度和小數位數的非零填充數字:
Select *
From Table_Name
Where NOT REGEXP_LIKE(COLUMN_NAME, '^[+-]?(([1-9]\d{0,'||(precision-scale-1)||'}|0)(\.\d{0,'||scale||'})?|\.\d{1,'||scale||'})$')
或者,對於任何精度和規模:
Select *
From Table_Name
Where NOT REGEXP_LIKE(
COLUMN_NAME,
CASE
WHEN scale <= 0
THEN '^[+-]?(\d{1,'||precision||'}0{'||(-scale)||'})$'
WHEN scale < precision
THEN '^[+-]?(\d{1,'||(precision-scale)||'}(\.\d{0,'||scale||'})?|\.\d{1,'||scale||'})$'
WHEN scale >= precision
THEN '^[+-]?(0(\.0{0,'||scale||'})?|0?\.0{'||(scale-precision)||'}\d{1,'||precision||'})$'
END
)
精度意味着您最多需要數字中的allowed_precision
數字(嚴格來說,不計算前導零,但我會忽略它)。 該小數位數表示最多allowed_scale
可以在小數點后。
這建議一個正則表達式,例如:
[-]?[0-9]{1,<before>}[.]?[0-9]{0,<after>}
您可以構造正則表達式:
NOT REGEXP_LIKE(COLUMN_NAME,
REPLACE(REPLACE('[-]?[0-9]{1,<before>}[.]?[0-9]{0,<after>}', '<before>', allowed_precision - allowed_scale
), '<after>', allowed_scale)
現在,可變正則表達式的效率非常低。 您也可以使用like
和其他功能來執行邏輯。 我認為條件是:
(column_name not like '%.%.%' and
column_name not like '_%-%' and
translate(column_name, '0123456789-.x', 'x') is null and
length(translate(column_name, '-.x', 'x') <= allowed_precision and
length(translate(column_name, '-.x', 'x') >= 1 and
instr(translate(column_name, '-.x', 'x'), '.') <= allowed_precision - allowed_scale
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.