【问题标题】:How To Check Numerical Format in SQL Server 2008如何在 SQL Server 2008 中检查数字格式
【发布时间】:2020-06-12 20:31:44
【问题描述】:

我正在将一些现有的 Oracle 查询转换为 MSSQL Server (2008),但不知道如何复制以下正则表达式检查:

SELECT SomeField
FROM SomeTable
WHERE NOT REGEXP_LIKE(TO_CHAR(SomeField), '^[0-9]{2}[.][0-9]{7}$');

这将查找数字格式以 2 个正数开头、后跟一个小数点和 7 个小数位的数据的所有结果:12.3456789

我尝试过使用STRCASTCONVERT,但由于某种原因,它们似乎都将小数点截断为小数点后 4 位。截断使我无法使用LENCHARINDEX 获得可靠的结果。手动将大小参数添加到STR 会稍微接近一些,但我仍然不知道如何将原始数值表示与转换后的值进行比较。

SELECT SomeField
     , STR(SomeField, 10, 7)
     , CAST(SomeField AS VARCHAR)
     , LEN(SomeField )
     , CHARINDEX(STR(SomeField ), '.') 
FROM SomeTable
+------------------+------------+---------+-----+-----------+
|       Orig       |    STR     |  Cast   | LEN | CHARINDEX |
+------------------+------------+---------+-----+-----------+
| 31.44650944      | 31.4465094 | 31.4465 |   7 |         0 |
| 35.85609         | 35.8560900 | 35.8561 |   7 |         0 |
| 54.589623        | 54.5896230 | 54.5896 |   7 |         0 |
| 31.92653899      | 31.9265390 | 31.9265 |   7 |         0 |
| 31.4523333333333 | 31.4523333 | 31.4523 |   7 |         0 |
| 31.40208955      | 31.4020895 | 31.4021 |   7 |         0 |
| 51.3047869443893 | 51.3047869 | 51.3048 |   7 |         0 |
| 51               | 51.0000000 | 51      |   2 |         0 |
| 32.220633        | 32.2206330 | 32.2206 |   7 |         0 |
| 35.769247        | 35.7692470 | 35.7692 |   7 |         0 |
| 35.071022        | 35.0710220 | 35.071  |   6 |         0 |
+------------------+------------+---------+-----+-----------+

【问题讨论】:

  • SomeField的数据类型是什么?
  • @MartinSmith 这是float
  • 对数字进行字符串比较毫无意义。只需使用where somefield >= 0 and somefield < 100
  • @ParrishHusband 。 . .我添加了 Oracle 标记,因为您正在使用 numbers 的神秘功能,该功能适用​​于 Oracle,但不适用于 SQL Server。
  • Float 使它更不合理,因为SELECT CAST(CAST(31.1111111 AS float) AS decimal(38,36)) 返回31.111111099999998685916580143384635448。无论如何,您将无法区分 31.11111109999999868591658014338463544831.1111111

标签: sql sql-server oracle sql-server-2008


【解决方案1】:

您想要做的事情在 SQL Server 中没有意义。

Oracle supports a number data type 具有可变精度:

如果未指定精度,则列存储给定值。

SQL Server 中没有对应的数据类型。您有一个可变数字(浮点数/实数)或一个固定数字(十进制/数字)。但是,两者都适用于列中的所有值,而不适用于行中的单个值。

你能做的最接近的是:

where somefield >= 0 and somefield < 100

或者如果你想坚持有一个小数部分:

where somefield >= 0 and somefield < 100 and floor(somefield) <> somefield

但是,您可能有有效的整数值,这会过滤掉。

【讨论】:

  • 您的第一个建议是我最初尝试与客户一起尝试的,但这不满足格式要求。我同意数据类型使这不太理想。
  • 不是“不太理想”——考虑到浮动的不精确性,甚至不可能。如果要验证人们输入的格式,则需要将其存储为字符串,因为浮点数不精确,甚至十进制也无法区分输入的 50.000000050。虽然它也应该存储为数字数据类型用于所有其他目的
  • @MartinSmith 我很欣赏这里的智慧。我将转发所有这些信息以及极其糟糕和 hacky 的解决方法,让他们知道这首先是一个坏主意,并且是对这些数据的不可靠检查。
【解决方案2】:

This answer 给了我一个选项,它与首先检查小数点位置结合使用。

SELECT SomeField 
FROM SomeTable
WHERE SomeField IS NOT NULL
  AND CHARINDEX('.', SomeField ) = 3
  AND LEN(CAST(CAST(REVERSE(CONVERT(VARCHAR(50), SomeField , 128)) AS FLOAT) AS BIGINT)) = 7

虽然我知道从几乎所有指标来看这都很糟糕,但它满足了要求。

正如几位海报所指出的那样,检查此数据类型格式的基础存在固有缺陷,但是对于这个非常孤立的用例,我想记录解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多