简体   繁体   English

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

[英]SQL: Cannot convert nvarchar to numeric in complex query

I need to get the nearest airport in my database table from the current users position. 我需要从当前用户位置获取数据库表中最近的机场。 I found this formula: https://de.scribd.com/presentation/2569355/Geo-Distance-Search-with-MySQL#page=7 我找到了这个公式: https : //de.scribd.com/presentation/2569355/Geo-Distance-Search-with-MySQL#page=7

So there are a few differences between the formula described in the link above and my current situation: The example was in MySQL, I'm using MS SQL (not a problem, I guess). 因此,上面的链接中描述的公式与我的当前状态之间存在一些差异:该示例在MySQL中,我使用的是MS SQL(我想这不是问题)。 lat and lon are considered to be database columns with numeric data type, but for some reason the database table was created with two corresponding columns of type varchar . latlon被认为是具有numeric数据类型的数据库列,但是由于某种原因,数据库表是使用两个对应的varchar类型的列创建的。

My problem is: When I want to use an ORDER BY clause, it throws Error converting data type nvarchar to numeric , without it, it works. 我的问题是:当我想使用ORDER BY子句时, Error converting data type nvarchar to numeric ,没有它,它将起作用。 I did some research on what rubbish was inserted as string and migrated it so that I just have some empty values. 我对将什么垃圾作为字符串插入并进行了迁移进行了一些研究,以便获得一些空值。

I can't take all because I only need one. 我不能全部拿走,因为我只需要一个。 But if I do TOP 1 without ORDER BY I don't get any airport rather than the nearest airport. 但是,如果我在没有ORDER BY情况下进行TOP 1 ,则我不会到达任何机场,而不是最近的机场。 Does anyone know how to fix the query? 有人知道如何解决查询吗?

Thanks in advance! 提前致谢!

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

First, this logic doesn't make sense: 首先,这种逻辑没有意义:

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

The like is looking for non-numeric characters. like正在寻找非数字字符。 I think you intend: 我认为您打算:

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

This ensures that the values are numeric. 这样可以确保值是数字。

The solution to your problem -- at least in SQL Server 2012+ -- is to use try_convert() or try_cast() : 解决问题的方法(至少在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

This will prevent any conversion errors. 这样可以防止任何转换错误。

You shouldn't use just numeric . 您不应该只使用numeric Use either a floating point representation or something with decimal places, say numeric(20, 10) . 使用浮点表示形式或带小数位的内容,例如numeric(20, 10)

The reason this occurs with the order by is because of the SQL optimizer. order by发生的原因是由于SQL优化器。 You clearly have some lat/long values that do not convert correctly to a numeric . 显然,您有一些经/纬度值无法正确转换为numeric SQL Server allows itself to re-arrange operations, so the conversion might take place before the filtering by the where clause. SQL Server允许自己重新安排操作,因此转换可能发生 where子句筛选之前 This is part of the overall query optimization. 这是整体查询优化的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM