Определенная пользователем функция MySQL для синтаксиса долготы широты

Я создал функцию MySQL, чтобы определить, находится ли набор координат широты и долготы в определенном диапазоне другого набора координат широты и долготы. Тем не менее, функция дает мне синтаксическую ошибку, поэтому я не могу проверить, правильно ли она работает. Любая помощь в выяснении того, что вызывает ошибку, будет с большой благодарностью. Функция вместе с ее описанием написана ниже:

Он работает, если начальная координата lat/long передается функции. База данных содержит строки targa, targb и targc, которые содержат широту, долготу и диапазон (соответственно) для сравнения. Столбец "Тарт" в базе данных указывает, следует ли проверять эту строку для диапазона широты/долготы.

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   RETURNS INT (1) НАЧАТЬ   DECLARE расстояние десятичное (18, 10) 'в строке 4

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

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

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

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

EDIT: следующий код функционирует и работает. Не забудьте установить разделитель в $$. Еще раз спасибо за помощь.

Рабочий код:

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 ответа

У вас есть RETURNS и READS SQL DATA не в порядке. RETURNS на первом месте:

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

EDIT: Также вы ссылаетесь на столбцы в своей базе данных, как вы сказали в своем комментарии. Не только ваша функция не знает, к какой таблице относятся эти столбцы, но, как правило, вы не должны ссылаться на столбцы из функций. Вместо этого добавьте параметры в свою функцию:

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$$

Затем в ваших запросах вы можете передать имена столбцов функции.

(Отказ от ответственности: убедитесь, что я положил латы и длинные позиции в нужные места. Думаю, что и сделал.)


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

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

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$$

licensed under cc by-sa 3.0 with attribution.