我有一个字段有时包含如下字符串:2/23/2013 12:25:55~45
我需要在 ~ 处拆分字符串,并确定 ~ 的左侧是否是有效的日期时间值,而 ~ 的右侧是有效的整数。基本上我想要返回的是一个真/假,这些条件是否正确。
请记住,该字段可以包含空值,可以包含任何其他类型的数据,并且可以包含多个波浪号。在所有情况下,我都需要返回 false。我需要返回 true 的唯一时间是当字段包含日期/时间值、单个波浪号和整数时。
在 SQL Server 中,您可以执行以下操作:
select (case when col like '%~%'
then (case when isdate(left(col, charindex('~', col) - 1)) = 1 and
isnumeric(substring(col, charindex('~', col)+1, 1000)) = 1 and col not like '%~%.%' and col not like '%~%e%'
then 1
else 0
end)
else 0
end) as IsFunkyFormat, substring(col, charindex('~', col)+1, 1000), left(col, charindex('~', col) - 1)
嵌套大小写是为了防止在找不到分隔符时出错。这些not like
表达式旨在排除非整数的数字格式。
这个问题比看起来更棘手,因为它很容易出错,或者以这样一种方式编写它,它现在适用于您给定的数据集,但无法适用于其他数据集。
如果这是您存储在数据库中的数据,我强烈建议您了解数据库规范化。规范化的一个原则是您只在列中存储一个值。在这种情况下,您将日期时间和整数值存储在同一列中。将数据存储在多列中会好得多。
话虽如此,我知道有时您会获得一些需要导入数据库的原始数据。很多时候,我们无法控制我们得到的原始数据,所以我们必须凑合使用 SQL 体操。在这种特殊情况下,有几种不同类型的后空翻很有用。
4 个项目中只有 1 个内置于 SQL Server。有一个名为 IsDate 的函数,它接受一个字符串参数并返回一个位,该位指示字符串表示的日期是否可以转换为日期。
要确定字符串中 ~ 的数量,诀窍是确定带波浪号的字符串的长度,以及不带波浪号的字符串的长度。我们可以通过这样做来确定哪些行包含单个波浪号:
When Len(Data) = Len(Replace(Data, '~', '')) + 1
另一个需要解决的棘手问题是确定一个字符串是否代表一个整数。有多种方法可以做到这一点,但我最喜欢的方法是将硬编码值连接到您的数据,然后测试数字。例如,IsNumeric 函数将为字符串 1e4 返回 true,因为 e 表示科学计数法,而 1e4 可以解释为 1000。因此,如果您这样做:
IsNumeric(Data + 'e0')
对于科学记数法,这将返回 false,因为数据将类似于 1e4,它连接到“e0”以获得不是数字的“1e4e0”。同样,我们可以将 .0 连接到字符串以检查小数。如果您的数据是 45.2(这是数字)并且您将 .0 连接到它,您会得到 '45.2.0' 这不是数字。您还可以在测试中添加“-”以检查正数。“-20”是数字,但“-”+“-20”(即“--20”)不是数字。
Select YourColumnHere,
Len(Replace(YourColumnHere, '~', '')) + 1,
Case When Len(YourColumnHere) = Len(Replace(YourColumnHere, '~', '')) + 1
Then
Case When IsDate(Left(YourColumnHere, CharIndex('~', YourColumnHere)-1)) = 1
Then
Case When Right(YourColumnHere, Len(YourColumnHere)-CharIndex('~', YourColumnHere)) > ''
Then IsNumeric('-' + Right(YourColumnHere, Len(YourColumnHere)-CharIndex('~', YourColumnHere)) + '.0e0')
Else 0
End
Else 0
End
Else 0
End
From YourTableNameHere