#在 Access 中解析字符串时从 `Switch` 抛出的错误

#Error thrown from `Switch` when string parsing in Access

我正在尝试在 Access 中执行 SWITCH 语句以将多种格式的 GPS 纬度和经度解析为十进制格式

SELECT
  IIF(ISNull(a.Lat), NULL, Len(A.lat) - Len(Replace(A.lat," ", ""))) as _spaces,
  Switch(
    ISNull([_spaces]), A.Lat,
    [_spaces] = 0, CDbl(A.Lat), 
    [_spaces] = 1, CDbl(Left(A.Lat,2)) + CDbl(MID(A.Lat,4,6))/60,
    [_spaces] = 2, CDbl(Left(A.Lat,2)) + CDbl(MID(A.Lat,4,2))/60 + CDbl(RIGHT(A.Lat,LEN(A.Lat)-6))/3600,
    1=1, CDbl(A.Lat)
  ) as [Lat]
FROM AggregateTags as A

但是 returns #Error for all except where _spaces=0.

所以,我想我会通过简化条件来调试,只尝试解析 _spaces 是 1 或 2 的地方。此外,如果我的解析是错误的 _spaces=2 我想我只是为该条件设置了一个任意值。我还重新命名了输出结果列,以防引用中出现任何循环。

SELECT 
 IIF(ISNull(a.Lat), NULL, Len(A.lat) - Len(Replace(A.lat," ", ""))) as _spaces,
 Switch(
    [_spaces]=2, 50.0,
    [_spaces]=1, CDbl(Left(A.Lat,2)) + CDbl(MID(A.Lat,4,6))/60
  ) as Latt
FROM AggregateTags as A

这适用于 _spaces=1,但仍然会在 _spaces=2.

处抛出 #Error

我试过 CDbl 转换 50.050。我还尝试通过消除对查询前面的列声明的引用来查看评估顺序是否存在问题:SWITCH(IIF(ISNull(a.Lat), NULL, Len(A.lat) - Len(Replace(A.lat," ", "")))=2, 50.0, ...) 但这仍然会引发 #Error where _spaces=2。交换各种内部条件 + 结果配对的位置时也会发生同样的情况。

奇怪的是,当我离开 [_spaces]=1 而只有 [_spaces]=2 和默认条件

时,我没有收到错误消息
SELECT 
 IIF(ISNull(a.Lat), NULL, Len(A.lat) - Len(Replace(A.lat," ", ""))) as _spaces,
 Switch(
    [_spaces]=2, CDbl(50),
    1=1, A.Lat
) as Latt
FROM AggregateTags as A

[_spaces]=1 也包含在内时,为什么会抛出 [_spaces]=2 的#Error?

lat 列的示例数据

39 14.838
39 27 15.88
39.20628
"" (empty string)
NULL

MS Access 中的 Switch 语句原型为 Switch( expr-1, value-1 [, expr-2, value-2 ] … [, expr-n, value-n ] )

Access 评估 Switch 语句中的所有 values,如果任何错误发生 - 即使 expr 不匹配 - 它会给出 #Error,如下面进行演示。

SELECT
  testing.ID as nbr,
  CDbl(LEFT(nbr,3)) as L,
  CDbl(RIGHT(nbr,3)) as R,
  SWITCH(1=1,999,0=1,CDbl(0)) as intval,
  CDbl(RIGHT(nbr,5)) as errVal,
  SWITCH(1=1,999,0=1,CDbl(RIGHT(nbr,5))) as first
FROM testing

短文本 ID 列中的唯一值是“123 456”,这会产生

  --------------------------------------------------
  |   nbr   |  L  |  R  | intval | errVal |  first |
  | ---------------------------------------------- |
  | 123 456 | 123 | 456 |    999 | #Error | #Error |
  --------------------------------------------------

显然 1=1 始终为真,0=1 始终为假。尽管如此,Access 仍然评估 "values."

在 "Access is dumb"

下提交另一个条目

至于我的解析器,我所有的坐标都在落基山脉以西的北美,所以所有的纬度都是小数点前 2 位,所有的长都是负的 3 位。更健壮的解析器会找到每个空格的位置并相应地分解数字,还可能会查找并消除符号(°'")。

由于 SWITCH 的评估方法在错误生成方面的疯狂,我切换到 IIF

SELECT 
  IIF(ISNull(a.Lat), NULL, Len(A.lat) - Len(Replace(A.lat," ", ""))) AS _Tspaces,
  IIF(ISNull(a.Lat), NULL, Len(A.lat) - Len(Replace(A.lat," ", ""))) AS _Gspaces,
  IIF(
    ISNull([_Tspaces]), NULL, IIF(
      [_Tspaces]=1, CDbl(Left(A.Lat,2)) + CDbl(RIGHT(A.Lat,6))/60, IIF(
        [_Tspaces]=2, CDbl(Left(A.Lat,2)) + CDbl(MID(A.Lat,4,2))/60 + CDbl(RIGHT(A.Lat,LEN(A.Lat)-6))/3600, IIF(
          [_Tspaces]=0, CDbl(A.Lat), A.Lat
        )
      )
    )
  ) AS Latitude,
  -1*IIF(
    ISNull([_Gspaces]), NULL, IIF(
      [_Gspaces]=1, ABS(CDbl(Left(A.Long,4))) + CDbl(RIGHT(A.Long,7))/60, IIF(
        [_Gspaces]=2, ABS(CDbl(Left(A.Long,2))) + CDbl(MID(A.Long,5,2))/60 + CDbl(RIGHT(A.Long,LEN(A.Long)-7))/3600, IIF(
          [_Gspaces]=0, ABS(CDbl(A.Long)), A.Long
        )
      )
    )
  ) AS Longitude
FROM AggregateTags AS A;