Создание пользовательской функции MySQL?

Я только начал использовать MySQL с PHP, и я хотел бы узнать, можно ли создать пользовательскую функцию. Этот фрагмент кода должен иллюстрировать то, что я пытаюсь сделать.

// a somewhat complicated formula not suitable to embed into the query function Distance($latA, $lonA, $latB, $lonB) { // earth's radius $radius = 3956; $latA = deg2rad($latA); $lonA = deg2rad($lonA); $latB = deg2rad($latB); $lonB = deg2rad($lonB); // calculate deltas $deltaLat = $latB - $latA; $deltaLon = $lonB - $lonA; // calculate Great Circle distance $result = pow(sin($deltaLatitude / 2.0), 2) + (cos($latA) * cos($latB) * pow(sin($deltaLon / 2.0), 2)); $distance = $radius * 2 * atan2(sqrt($result), sqrt(1 - $result)); return $distance; } // how can I call Distance() in my query? $query = "SELECT lat, lon FROM zipcodes WHERE Distance(lat, lon, 0, 0) < 20"; mysql_query($query); 

Заранее благодарю за любую помощь!

Вы объявляете эту функцию MySQL в своем приложении, и она останется в базе данных до тех пор, пока сервер базы данных не будет перезапущен.

 mysql_query("CREATE FUNCTION Distance(LAT_A INT, LON_A INT, LAT_B INT, LON_B INT, ) RETURNS INT READS SQL DATA DETERMINISTIC BEGIN DECLARE radius, deltaLat, deltaLon, result, distance BIGINT; SET radius=3956; SET deltaLat=LAT_B-LAT_A; SET deltaLon=LON_B-LON_A; SET result=POW(SIN(deltaLat/2), 2) + (COS(LAT_A) * COS(LAT_B) * POW(SIN(deltaLon/2.0), 2)); SET distance=radius * 2 * ATAN2(SQRT(result), SQRT(1 - result)); RETURN distance; END"); 

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

Как только вы это объявили, вы можете использовать его так:

 $query = "SELECT lat, lon FROM zipcodes WHERE Distance(lat, lon, 0, 0) < 20"; mysql_query($query); 

Однако, если ваша база данных перезагружается, любые функции или процедуры, объявленные ранее, будут потеряны. Возможно обработать ошибку MySQL 1305 ( Function functionName does not exist ) изящно на уровне приложения.

В обработчике ошибок базы данных:

 switch (mysql_errno()): case 1305: if (false === $database->_declareStoredProcedureFlag) { if ($c = preg_match_all("/FUNCTION [a-zA-Z0-9]+\." . "([a-zA-Z0-9_]*) does not exist/is", mysql_error(), $matches) ) { $storedFunctionName = $matches[1][0]; $database->_declareStoredProcedureFlag = true; if (true === $database->declareStoredFunction($storedFunctionName)) { $result = mysql_query($query); } } } break; ... 

Вы, конечно, можете написать функцию MySQL для этого. У меня нет времени писать, но вот где вы начинаете:

http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html

Mysql хранит подпрограммы http://dev.mysql.com/doc/refman/5.0/en/stored-routines.html

Некоторые из функций могут быть разными, например, эквивалент mysql, равный deg2rad php, является функцией radians () mysql. Я думаю, вы должны иметь возможность создать эквивалентную функцию. При таком подходе вы должны знать, что эти запросы будут иметь значение для таблиц всю таблицу zipcodes каждый раз.

Поскольку функции не работают в кавычках "или" вы должны разделить его с полной остановкой. (.)

 $query = mysql_query("SELECT lat, lon FROM zipcodes WHERE ".Distance($lat, $lon, 0, 0)." < 20"); 

Надеюсь это поможет 🙂