在 MySQL 的 LIMIT 子句中使用变量

发布于 2024-07-07 07:17:04 字数 324 浏览 6 评论 0原文

我正在编写一个存储过程,其中有一个名为 my_size 的输入参数,它是一个 INTEGER。 我希望能够在 SELECT 语句的 LIMIT 子句中使用它。 显然这不受支持,有没有办法解决这个问题?

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

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

I am writing a stored procedure where I have an input parameter called my_size that is an INTEGER. I want to be able to use it in a LIMIT clause in a SELECT statement. Apparently this is not supported, is there a way to work around this?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

夕嗳→ 2024-07-14 07:17:04

对于那些无法使用 MySQL 5.5.6+ 并且不想编写存储过程的人,还有另一种变体。 我们可以使用 ROWNUM 在子查询上添加 where 子句。

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

For those, who cannot use MySQL 5.5.6+ and don't want to write a stored procedure, there is another variant. We can add where clause on a subselect with ROWNUM.

SET @limit = 10;
SELECT * FROM (
  SELECT instances.*, 
         @rownum := @rownum + 1 AS rank
    FROM instances, 
         (SELECT @rownum := 0) r
) d WHERE rank < @limit;
誰ツ都不明白 2024-07-14 07:17:04

存储过程

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 ;

用法

在下面的示例中,它每次通过提供起始为 1 和 11 来检索 10 条记录。1 和 11 可能是作为 GET/POST 参数接收的页码分页。

call get_users(1, 10);
call get_users(11, 10);

STORED PROCEDURE

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 ;

USAGE

In the following example it retrieves 10 records each time by providing start as 1 and 11. 1 and 11 could be your page number received as GET/POST parameter from pagination.

call get_users(1, 10);
call get_users(11, 10);
那伤。 2024-07-14 07:17:04

我知道这个答案来晚了,但请尝试 SQL_SELECT_LIMIT。

例子:

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

I know this answer has come late, but try SQL_SELECT_LIMIT.

Example:

Declare rowCount int;
Set rowCount = 100;
Set SQL_SELECT_LIMIT = rowCount;
Select blah blah
Set SQL_SELECT_LIMIT = Default;
如若梦似彩虹 2024-07-14 07:17:04

搜索发现了这篇文章。 我已将相关文字粘贴在下面。

这是一个论坛帖子,显示了准备好的声明的示例
您将变量值分配给限制子句:

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

但是,我认为这个错误应该引起一些注意,因为我不能
想象一下程序中准备好的语句将允许任何
过程编译时优化。 我有一种感觉,准备好了
语句在过程运行时编译和执行,
这可能会对效率产生负面影响。 如果极限
子句可以接受正常的过程变量(例如,一个过程
参数),那么数据库仍然可以执行编译时
在过程中对查询的其余部分进行优化。 这
可能会加快程序的执行速度。 我不是专家
不过。

A search turned up this article. I've pasted the relevant text below.

Here's a forum post showing an example of prepared statements letting
you assign a variable value to the limit clause:

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

However, I think this bug should get some attention because I can't
imagine that prepared statements within a procedure will allow for any
procedure-compile-time optimizations. I have a feeling that prepared
statements are compiled and executed at the runtime of the procedure,
which probaby has a negative impact on efficiency. If the limit
clause could accept normal procedure variables (say, a procedure
argument), then the database could still perform compile-time
optimizations on the rest of the query, within the procedure. This
would likely yield faster execution of the procedure. I'm no expert
though.

一腔孤↑勇 2024-07-14 07:17:04

MySQL 5.5.6 中已添加此功能。
检查此链接

我已经升级到 MySQL 5.5,只是为了这个功能并且效果很好。
5.5 也有很多性能升级,我完全推荐它。

This feature has been added to MySQL 5.5.6.
Check this link out.

I've upgraded to MySQL 5.5 just for this feature and works great.
5.5 also has a lot of performance upgrades in place and I totally recommend it.

看春风乍起 2024-07-14 07:17:04

另一种方式,与“Pradeep Sanjaya”所写的相同,但使用 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;

Another way, the same as wrote "Pradeep Sanjaya", but using 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;
記柔刀 2024-07-14 07:17:04

从 MySQL 版本 5.5.6 开始,您可以使用变量/参数指定 LIMITOFFSET

有关参考,请参阅 5.5 手册,< a href="http://dev.mysql.com/doc/refman/5.6/en/select.html#idm140462371147952" rel="nofollow noreferrer">5.6 手册 和 @Quassnoi 的 答案

As of MySQL version 5.5.6, you can specify LIMIT and OFFSET with variables / parameters.

For reference, see the 5.5 Manual, the 5.6 Manual and @Quassnoi's answer

请叫√我孤独 2024-07-14 07:17:04

我在使用 MySql 5.0 时遇到了同样的问题,并在 @ENargit 的答案的帮助下编写了一个过程:

CREATE PROCEDURE SOME_PROCEDURE_NAME(IN _length INT, IN _start INT)
BEGIN
    SET _start = (SELECT COALESCE(_start, 0));
    SET _length = (SELECT COALESCE(_length, 999999)); -- USING ~0 GIVES OUT OF RANGE ERROR
    SET @row_num_personalized_variable = 0;

    SELECT
    *,
    @row_num_personalized_variable AS records_total         
    FROM(
        SELECT
        *,
        (@row_num_personalized_variable := @row_num_personalized_variable + 1) AS row_num
        FROM some_table
    ) tb
    WHERE row_num > _start AND row_num <= (_start + _length);
END;

还包括通过记录总数查询获得的总行数。

I've faced the same problem using MySql 5.0 and wrote a procedure with the help of @ENargit's answer:

CREATE PROCEDURE SOME_PROCEDURE_NAME(IN _length INT, IN _start INT)
BEGIN
    SET _start = (SELECT COALESCE(_start, 0));
    SET _length = (SELECT COALESCE(_length, 999999)); -- USING ~0 GIVES OUT OF RANGE ERROR
    SET @row_num_personalized_variable = 0;

    SELECT
    *,
    @row_num_personalized_variable AS records_total         
    FROM(
        SELECT
        *,
        (@row_num_personalized_variable := @row_num_personalized_variable + 1) AS row_num
        FROM some_table
    ) tb
    WHERE row_num > _start AND row_num <= (_start + _length);
END;

Also included the total rows obtained by the query with records_total.

面犯桃花 2024-07-14 07:17:04

您必须声明一个变量,然后设置它。 那么 LIMit 将会工作并将其放入 StoredProcedure 中,不确定它是否在正常查询中工作,

如下所示:

DECLARE rowsNr INT DEFAULT 0;  
SET rowsNr = 15;  
SELECT * FROM Table WHERE ... LIMIT rowsNr;

you must DECLARE a variable and after that set it. then the LIMIt will work and put it in a StoredProcedure not sure if it works in normal query

like this:

DECLARE rowsNr INT DEFAULT 0;  
SET rowsNr = 15;  
SELECT * FROM Table WHERE ... LIMIT rowsNr;
鹿! 2024-07-14 07:17:04

看来这里很多人都想用LIMIT作为参数而不用存储过程。

可以通过 PREPARE 和 EXECUTE 来完成,如下所示:

set @my_size = 100;
set @sql = concat("SELECT * FROM some_table LIMIT ", @my_size);
PREPARE stmt FROM @sql;
EXECUTE stmt;

It seems that many people here want to use LIMIT as a parameter without stored procedures.

it can be done with PREPARE and EXECUTE like this:

set @my_size = 100;
set @sql = concat("SELECT * FROM some_table LIMIT ", @my_size);
PREPARE stmt FROM @sql;
EXECUTE stmt;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文