SQL:在复杂查询中无法将nvarchar转换为数字

时间:2018-01-16 11:26:16

标签: sql sql-server geolocation

我需要从当前用户位置获取数据库表中最近的机场。我找到了这个公式:https://de.scribd.com/presentation/2569355/Geo-Distance-Search-with-MySQL#page=7

因此,上面链接中描述的公式与我目前的情况之间存在一些差异:示例是在MySQL中,我使用的是MS SQL(我猜不是问题)。 latlon被视为具有numeric数据类型的数据库列,但由于某种原因,数据库表是使用两个类型为varchar的相应列创建的。

我的问题是:当我想使用ORDER BY子句时,它会抛出Error converting data type nvarchar to numeric,如果没有它,它就会起作用。我做了一些关于什么垃圾作为字符串插入并进行迁移的研究,以便我只有一些空值。

我不能全部因为我只需要一个。但如果我TOP 1没有ORDER BY,我就不会在任何机场而不是最近的机场。有谁知道如何修复查询?

提前致谢!

SELECT TOP 1
  temp.Distance
FROM (
  SELECT
    (
      3956 * 2 * ASIN(
          SQRT(
              POWER(
                  SIN((53.6349994 - abs(CAST(latitude_deg AS numeric))) * pi() / 180 / 2), 2) + COS(53.6349994 * pi()/180) * COS(abs(CAST(latitude_deg AS numeric)) * pi()/180) * POWER(SIN((10.0117336 - CAST(longitude_deg AS numeric)) * pi()/180 / 2), 2) ))) AS Distance
  FROM Airport_Airports
  WHERE
    isnumeric(longitude_deg) = 1 AND isnumeric(latitude_deg) = 1 AND
    longitude_deg LIKE '%[^0-9.]%' AND latitude_deg LIKE '%[^0-9.]%'
) AS temp
WHERE
  temp.Distance < 50000
Order BY
  temp.Distance

1 个答案:

答案 0 :(得分:2)

首先,这个逻辑没有意义:

WHERE isnumeric(longitude_deg) = 1 AND
      isnumeric(latitude_deg) = 1 AND
      longitude_deg LIKE '%[^0-9.]%' AND
      latitude_deg LIKE '%[^0-9.]%'

like正在寻找非数字字符。我想你打算:

WHERE isnumeric(longitude_deg) = 1 AND
      isnumeric(latitude_deg) = 1 AND
      longitude_deg NOT LIKE '%[^0-9.]%' AND
      latitude_deg NOT LIKE '%[^0-9.]%'

这可确保值为数字。

问题的解决方案 - 至少在SQL Server 2012+中 - 是使用try_convert()try_cast()

  (3956 * 2 * ASIN(
      SQRT(
          POWER(
              SIN((53.6349994 - abs(try_convert(numeric, latitude_deg))) * pi() / 180 / 2), 2) + COS(53.6349994 * pi()/180) * COS(abs(try_convert(numeric, latitude_deg)) * pi()/180) * POWER(SIN((10.0117336 - try_convert(numeric, longitude_deg)) * pi()/180 / 2), 2) ))) AS Distance

这可以防止任何转换错误。

你不应该只使用numeric。使用浮点表示或带小数位的东西,比如numeric(20, 10)

order by发生这种情况的原因是因为SQL优化器。您显然有一些lat / long值无法正确转换为numeric。 SQL Server允许自己重新安排操作,因此转换可能在过滤之前由<{1}}子句进行过滤。这是整体查询优化的一部分。