我刚刚开始在PHP中使用MySQL,我想知道是否可以创建自定义函数。这段代码片段应该说明我正在尝试做的事情。
// 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);
提前感谢您的帮助!
答案 0 :(得分:12)
您在应用程序中声明了此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的mathematical functions。将此处理卸载到数据库是快速有效的(数据不必通过网络传输,并且您只返回所需的结果)。
一旦你宣布了这个,就可以这样使用它:
$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;
...
答案 1 :(得分:1)
你当然可以写一个MySQL函数来做到这一点。我现在没时间写一个,但是这里是你开始的地方:
http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
答案 2 :(得分:1)
Mysql存储了例程http://dev.mysql.com/doc/refman/5.0/en/stored-routines.html
有些功能可能不同,例如,相当于php的deg2rad的mysql是mysql的radians()函数。我认为你应该能够创建一个等效的函数。使用这种方法,您应该知道这些查询每次都必须表格扫描整个zipcodes表。
答案 3 :(得分:0)
因为函数在引号“或”中不起作用,所以你必须用句号将其拆分。(。)
$query = mysql_query("SELECT lat, lon FROM zipcodes WHERE ".Distance($lat, $lon, 0, 0)." < 20");
希望这会有所帮助:)