2012-05-18 10 views
7

Estoy intentando crear un procedimiento almacenado. Esto es lo que tengo hasta ahora (no funciona):MySQL Variables de procedimiento almacenadas de las instrucciones SELECT

DELIMITER | 
CREATE PROCEDURE getNearestCities(IN cityID INT) 
    BEGIN 
     DECLARE cityLat FLOAT; 
     DECLARE cityLng FLOAT; 
     SET cityLat = SELECT cities.lat FROM cities WHERE cities.id = cityID; 
     SET cityLng = SELECT cities.lng FROM cities WHERE cities.id = cityID; 
     SELECT *, HAVERSINE(cityLat,cityLng, cities.lat, cities.lng) AS dist FROM cities ORDER BY dist LIMIT 10; 
    END | 

Haversine es una función que creé que funciona muy bien. Como puede ver, intento tomar la identificación de una ciudad de la tabla de ciudades y luego establecer cityLat y cityLng en algunos otros valores de ese registro. Obviamente estoy haciendo esto mal aquí usando SELECT.

Esto es posible. Parece que debería ser. Cualquier ayuda será muy apreciada.

Respuesta

12

Se corrigió un par de cosas y se agregó una alternativa seleccionar - eliminar según corresponda.

DELIMITER | 

CREATE PROCEDURE getNearestCities 
(
IN p_cityID INT -- should this be int unsigned ? 
) 
BEGIN 

DECLARE cityLat FLOAT; -- should these be decimals ? 
DECLARE cityLng FLOAT; 

    -- method 1 
    SELECT lat,lng into cityLat, cityLng FROM cities WHERE cities.cityID = p_cityID; 

    SELECT 
    b.*, 
    HAVERSINE(cityLat,cityLng, b.lat, b.lng) AS dist 
    FROM 
    cities b 
    ORDER BY 
    dist 
    LIMIT 10; 

    -- method 2 
    SELECT 
     b.*, 
     HAVERSINE(a.lat, a.lng, b.lat, b.lng) AS dist 
    FROM  
     cities AS a 
    JOIN cities AS b on a.cityID = p_cityID 
    ORDER BY 
     dist 
    LIMIT 10; 

END | 

delimiter ; 
13

sólo hay que encerrar sus SELECT declaraciones que aparecen entre paréntesis para indicar que son subconsultas:

SET cityLat = (SELECT cities.lat FROM cities WHERE cities.id = cityID); 

Como alternativa, puede utilizar la sintaxis de MySQL SELECT ... INTO. Una ventaja de este enfoque es que tanto cityLat y cityLng se pueden asignar de una sola tabla de acceso:

SELECT lat, lng INTO cityLat, cityLng FROM cities WHERE id = cityID; 

Sin embargo, todo el procedimiento se puede reemplazar con un solo SELECT declaración auto-unió:

SELECT b.*, HAVERSINE(a.lat, a.lng, b.lat, b.lng) AS dist 
FROM  cities AS a, cities AS b 
WHERE a.id = cityID 
ORDER BY dist 
LIMIT 10; 
Cuestiones relacionadas