MySQL中的匿名函数?

时间:2012-09-24 18:42:04

标签: php mysql sql

我为使用存储过程的客户端编写了一个查询。事实证明,他们无法授予我的用户对数据库的写入权限,因此我无法存储我的程序。我可以将我的存储过程转换为查询中的匿名函数,以便在不使用存储过程的情况下保留功能吗?

$establishFunction = mysql_query("DROP FUNCTION IF EXISTS fn_distance_cosine;
CREATE FUNCTION fn_distance_cosine (
    latitude_1 DOUBLE,
    longitude_1 DOUBLE,
    latitude_2 DOUBLE,
    longitude_2 DOUBLE
)
RETURNS DOUBLE
DETERMINISTIC
SQL SECURITY INVOKER
RETURN ACOS(
      SIN(RADIANS(latitude_1)) * SIN(RADIANS(latitude_2))
      + COS(RADIANS(latitude_1)) * COS(RADIANS(latitude_2))
      * COS(RADIANS(longitude_2 - longitude_1))
    ) * 3956.547;
");

mysql_query("SET @input_lat :=" . $lat . ";");
mysql_query("SET @input_lon :=" . $lon . ";");

mysql_query("SET @max_latitude := @input_lat + DEGREES(50.0/3956.547);");
mysql_query("SET @min_latitude := @input_lat - DEGREES(50.0/3956.547);");
mysql_query("SET @max_longitude := @input_lon + DEGREES(50.0/3956.547/COS(RADIANS(@input_lat)));");
mysql_query("SET @min_longitude := @input_lon - DEGREES(50.0/3956.547/COS(RADIANS(@input_lat)));");

if($result = mysql_query("SELECT
      *,
      fn_distance_cosine(lat, lon, @input_lat, @input_lon) AS distance_in_miles,
      COUNT(*) AS store_number_count
    FROM stores
    JOIN items_stores
    ON stores.store_number=items_stores.store_number
    WHERE `lat` BETWEEN @min_latitude AND @max_latitude
      AND `lon` BETWEEN @min_longitude AND @max_longitude
    GROUP BY stores.store_code
    HAVING store_code_count > 1
    ORDER BY distance_in_miles
    LIMIT 10;
    ")){  
        while ($r = mysql_fetch_assoc($result)){
        $rows[] = $r;
    }
}else{
    //failed.
    echo (mysql_error ());
}

print json_encode($rows);

3 个答案:

答案 0 :(得分:3)

如果您无法执行存储过程,则可能无法执行任何功能,因为它们也没有安全权限。

选项#1 - 让自己的DBA审核SQL语句,然后对数据库进行修改以容纳存储过程。

选项#2 - 您的另一个选择是将该代码移出数据库并移入PHP。所以,是的,您可以将其移动到PHP中,但它不会像数据库引擎那样快速或高效。

答案 1 :(得分:1)

不,你不能拥有匿名功能。如果您的客户无法授予您添加此功能的适当权限,那么他们为什么要求您写一个?如果您的数据库用户帐户无法安装该功能,那么肯定有人拥有正确的用户帐户,以便能够根据您的SQL为您创建此功能。

另外为什么函数而不是存储过程呢?您可以在一次调用中将您正在进行的所有逻辑放在几个数据库查询中,如:

call give_me_my_data(lat, long)

你会使用一些基于数据库的逻辑和一些基于php的逻辑(带有许多不必要的查询)来获取你需要的数据,而不是一直走下去并定义一个存储过程,这似乎很奇怪。会清理你的PHP代码,只进行一次查询。

答案 2 :(得分:0)

你能在同一个mysql服务器上获得一个单独的数据库吗?然后,您可以在那里声明该过程,然后通过显式添加数据库名称前缀在查询中使用它。我不完全确定它是否真的有效,但我猜它确实有效。