2008-10-28 24 views
32

Estoy escribiendo un procedimiento almacenado donde tengo un parámetro de entrada llamado my_size que es un int, quiero poder usar en una cláusula de límite en una instrucción select. Aparentemente esto no es compatible, ¿hay alguna forma de evitar esto?Cláusula LIMIT variable en MySQL

# I want something like: 
SELECT * FROM some_table LIMIT my_size; 

# Instead of hardcoding a permanent limit: 
SELECT * FROM some_table LIMIT 100; 
+0

Si usted tiene control sobre qué versión de MySQL que utilice, parece que este se fija a partir de v5.5.6. http://bugs.mysql.com/bug.php?id=11918 – Hammerite

+0

encontró otra solución simple http://stackoverflow.com/a/4315661 – user3011839

+0

Tenga en cuenta que en * MySQL 5.7.16 * (y tal vez otros) el ' LIMIT @nrows OFFSET @ noffset' en una rutina almacenada parece ser rechazado también, mientras que se acepta un 'LIMIT nrows OFFSET noffset', siempre y cuando' DECLARE nrows INT; DECLARAR noffset INT' en el inicio de la rutina. – Xenos

Respuesta

9

Ha aparecido this article. He pegado el texto relevante a continuación.

Aquí hay un mensaje del foro que muestra un ejemplo de declaraciones preparadas dejar se asigna un valor de la variable a la cláusula de límite:

http://forums.mysql.com/read.php?98,126379,133966#msg-133966

Sin embargo, creo que este fallo debe conseguir una cierta atención porque puedo ' imagine que las declaraciones preparadas dentro de un procedimiento permitirán cualquier optimizaciones de tiempo de compilación de procedimientos. Tengo la sensación de que las declaraciones preparadas se compilan y se ejecutan en el tiempo de ejecución del procedimiento, , lo que probablemente tiene un impacto negativo en la eficiencia. Si la cláusula de límite puede aceptar variables de procedimiento normales (por ejemplo, un procedimiento argumento), la base de datos aún podría realizar optimizaciones en tiempo de compilación en el resto de la consulta, dentro del procedimiento. Este probablemente produzca una ejecución más rápida del procedimiento. Aunque no soy un experto .

12

Sé que esta respuesta ha llegado tarde, pero pruebe SQL_SELECT_LIMIT.

Ejemplo:

Declare rowCount int; 
Set rowCount = 100; 
Set SQL_SELECT_LIMIT = rowCount; 
Select blah blah 
Set SQL_SELECT_LIMIT = Default; 
+2

Lamentablemente, no parece ser compatible con un argumento para la posición de inicio, como 5,2 para tomar 2 filas de la posición 5. Pero a menos que lo necesite, puede hacer el truco. – Gruber

+0

Desafortunadamente, este truco no funciona para una parte 'SELECT ...' de consultas tales como 'REPLACE ... SELECT ...'. – Apostle

7

Esta característica ha sido añadido a MySQL 5.5.6. Compruebe esto link hacia fuera.

Me actualicé a MySQL 5.5 solo para esta característica y funciona muy bien. 5.5 también tiene muchas actualizaciones de rendimiento implementadas y lo recomiendo totalmente.

13

procedimiento almacenado

DELIMITER $ 
create PROCEDURE get_users(page_from INT, page_size INT) 
begin 
SET @_page_from = page_from; 
SET @_page_size = page_size; 
PREPARE stmt FROM "select u.user_id, u.firstname, u.lastname from users u limit ?, ?;"; 
EXECUTE stmt USING @_page_from, @_page_size; 
DEALLOCATE PREPARE stmt; 
end$ 
DELIMITER ; 

USO

call get_users(1, 10); 
+0

funcionó mejor para mí - gracias – auval

2

Otra forma, el mismo que escribió "Pradeep Sanjaya", pero utilizando CONCAT:

CREATE PROCEDURE `some_func`(startIndex INT, countNum INT) 
READS SQL DATA 
    COMMENT 'example' 
BEGIN 
    SET @asd = CONCAT('SELECT `id` FROM `table` LIMIT ',startIndex,',',countNum); 
    PREPARE zxc FROM @asd; 
    EXECUTE zxc; 
END; 
+0

Es una gran solución al usar declaraciones ** 'PREPARE' ** y **' EXECUTE' **. Una nota importante: no necesitamos usar el procedimiento Create. Podemos usar la instrucción ** 'PREPARE' ** y **' EXECUTE' ** en el código principal sql también. –

20

Para aquellos , que no puede usar MySQL 5.5.6+ y no desea escribir un procedimiento almacenado, hay otra variante. Podemos agregar where cláusula en una subselección con ROWNUM.

SET @limit = 10; 
SELECT * FROM (
    SELECT instances.*, 
     @rownum := @rownum + 1 AS rank 
    FROM instances, 
     (SELECT @rownum := 0) r 
) d WHERE rank < @limit; 
+1

Me gusta la inicialización de @rownum dentro de SELECT, ¡lindo! – andig

Cuestiones relacionadas