用于纬度经度语法的MySQL用户定义函数

时间:2010-09-04 00:48:29

标签: mysql phpmyadmin distance latitude-longitude user-defined-functions

我创建了一个MySQL函数来确定一组纬度和经度坐标是否在另一组纬度和经度坐标的某个范围内。但是,该函数给我一个语法错误,所以我无法测试它是否正常工作。任何帮助找出造成错误的原因将不胜感激。该函数及其描述如下:

通过将起始纬度/经度坐标传递给函数来工作。该数据库包含行targa,targb和targc,它们包含要比较的纬度,经度和范围(分别)。数据库中的targ列指定是否应针对纬度/经度范围检查此行。

CREATE FUNCTION inrange(
 lat1 decimal(11, 7), 
 lon1 decimal(11, 7))
 READS SQL DATA
 RETURNS INT(1)
BEGIN
 DECLARE distance decimal(18, 10);

 SET distance = ACOS(SIN(lat1)*SIN(targ2)+COS(lat1)*COS(targ2)*COS(targ3-lon1))*6371;

 IF distance <= targ4 THEN 
  RETURN 1;
 END IF;

 RETURN 0;
END$$

mysql给我的错误是:

1064 - 您的SQL语法出错;检查与MySQL服务器版本对应的手册,以便在“READS SQL DATA”附近使用正确的语法     返回INT(1) 开始     DECLARE第4行的距离十进制(18,10)

我似乎无法弄清楚如何克服这个错误。

另外,如果有人来这篇帖子寻找这样的mysql函数,我还有另一个相关的帖子:

MySQL Function to Determine Zip Code Proximity / Range

我非常感谢另一张海报的功能(作为这个功能的灵感来源),但我需要更紧凑的东西。因此,有问题的功能。

编辑:以下代码正常运行。只需记住将分隔符设置为$$。再次感谢大家的帮助。

工作代码:

CREATE FUNCTION inrange(
    lat1 decimal(11, 7), 
    long1 decimal(11, 7),
    lat2 decimal(11, 7),
    long2 decimal(11, 7),
    rng decimal(18, 10))
    RETURNS INT(1)
BEGIN
    DECLARE distance decimal(18, 10);

    SET lat1 = lat1 * PI() / 180.0,
       long1 = long1 * PI() / 180.0,
       lat2 = lat2 * PI() / 180.0,
       long2 = long2 * PI() / 180.0;

    SET distance = ACOS(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(long2-long1))*6371;

    IF distance <= rng THEN 
        RETURN 1;
    END IF;

    RETURN 0;
END$$

2 个答案:

答案 0 :(得分:3)

您的RETURNS和READS SQL DATA乱序。退货首先是:

CREATE FUNCTION inrange(
    lat1 decimal(11, 7), 
    lon1 decimal(11, 7))
    RETURNS INT(1)
    READS SQL DATA
BEGIN

编辑:此外,您还可以引用数据库中的列,就像您在评论中所说的那样。您的函数不仅不知道这些列属于哪个表,而且通常不应该引用函数中的列。而是向您的函数添加参数:

CREATE FUNCTION inrange(
    lat1 decimal(11, 7), 
    long1 decimal(11, 7),
    lat2 decimal(11, 7),
    long2 decimal(11, 7),
    rng decimal(18, 10))
    RETURNS INT(1)
BEGIN
    DECLARE distance decimal(18, 10);

    SET distance = ACOS(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(long2-long1))*6371;

    IF distance <= rng THEN 
        RETURN 1;
    END IF;

    RETURN 0;
END$$

然后,在查询中,您可以将列名称传递给函数。

(免责声明:确保我把拉特和长片放在正确的位置。我想我做到了。)

答案 1 :(得分:1)

根据您所包含的程序,您的分隔符似乎设置为$$

如果是,请尝试以下方法:

CREATE FUNCTION inrange(
 lat1 decimal(11, 7), 
 lon1 decimal(11, 7))
 RETURNS INT(1)
 READS SQL DATA
BEGIN
 DECLARE distance decimal(18, 10);

 SET distance = ACOS(SIN(lat1)*SIN(targ2)+COS(lat1)*COS(targ2)*COS(targ3-lon1))*6371;

 IF distance <= targ4 THEN 
  RETURN 1;
 END IF;

 RETURN 0;
END$$