3

我为使用存储过程的客户端编写了一个查询。结果他们不能授予我的用户对数据库的写访问权限,所以我不能存储我的过程。我可以在查询中将存储过程转换为匿名函数,以便在不使用存储过程的情况下保留该功能吗?

$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);
4

3 回答 3

3

如果你不能做存储过程,你可能也不能做函数,因为它们也没有安全权限。

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

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

于 2012-09-24T18:48:28.307 回答
2

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

还有为什么是函数而不是存储过程?您可以将您在多个数据库查询中执行的所有逻辑放在一个调用中,例如:

call give_me_my_data(lat, long)

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

于 2012-09-24T18:55:16.570 回答
0

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

于 2012-09-24T18:53:17.687 回答