Пользовательская функция MySQL для синтаксиса широты и долготы - PullRequest
3 голосов
/ 04 сентября 2010

Я создал функцию 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) НАЧАТЬ ОБЪЯВИТЬ десятичное расстояние (18, 10) 'в строке 4

Я не могу понять, как обойти эту ошибку.

Кроме того, если кто-то пришел к этому сообщению в поисках такой функции mysql, у меня также был другой связанный пост:

Функция MySQL для определения близости / диапазона почтового индекса

Я очень благодарен другому постеру за его функции (который послужил источником вдохновения для этого), но мне нужно что-то более компактное. Следовательно, рассматриваемая функция.

РЕДАКТИРОВАТЬ: Следующий код работает и работает. Просто не забудьте установить разделитель на $$. Еще раз спасибо всем за помощь.

Рабочий код:

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 ]

3 голосов
/ 04 сентября 2010

Ваши ВОЗВРАЩАЕТСЯ и ЧИТАЕТ SQL-ДАННЫЕ не в порядке. ВОЗВРАЩАЕТСЯ на первом месте:

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 голос
/ 04 сентября 2010

Из процедуры, которую вы включили, похоже, что ваш разделитель установлен на $$.

Если это так, попробуйте следующее:

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$$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...