`

MySQL5查询结果分页

阅读更多
在mysql中利用select语句的一个特性就可以很方便地实现查询结果的分页,select语句的语法:

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [FROM table_references
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name' export_options
      | INTO DUMPFILE 'file_name'
      | INTO @var_name [, @var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]


LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数,如果给出两个参数,

第一个参数指定返回的第一行在所有数据中的位置(类似于数组或集合中元素的索引—index),从0开始

(注意不是1),第二个参数指定最多返回行数。
例如:

select * from table LIMIT 5,10; #返回第6-15行数据
select * from table LIMIT 5; #返回前5行
select * from table LIMIT 0,5; #返回前5行



MySQL5 分页查询深入研究

按照分页状态划分,MySQL5支持动态分页和静态分页。
按照分页对象划分,MySQL5支持SQL分页和存储过程分页。
MySQL5分页的基本原理是依靠limit字句来对查询分页。
MySQL5的limit语句不支持表达式,只支持确定的整数值或者预定义参数。
这是一个大陷阱!也是MySQL最为变态的一个特征了,让我迷茫了很长时间才知道。
不过DB2、Oracle等数据库分页参数都支持表达式。也是本文中的一个焦点问题。
MySQL5的语句的基本格式是在SELECT语句最后添加一个返回记录的限制数,有两个参数(取值范围均大于等于0),分别用来限制返回记录的起起始位置和返回记录的数量,。但是不包含起始位置的记录,例如:SELECT * FROM TAB LIMIT 1,3; 则指挥显示第2、3、4三条记录,第1条记录不会被返回,如果要返回则应该从0开始。

下面从分页对象的角度研究MySQL5的分页实现,分为SQL分页和存储过程分页。其中SQL分页分为两种类型,一种是静态的,一种是动态的。而存储过程下只讨论动态的,静态的没有意义。

环境:
Windows XP Professional 简体中文版
mysql-5.0.25.-win32

测试脚本:
--select语句的语法参考:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    { LIKE old_tbl_name | (LIKE old_tbl_name) }

create_definition:
    column_definition
  | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
  | {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
  | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]
      [index_name] [index_type] (index_col_name,...)
  | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)
  | [CONSTRAINT [symbol]] FOREIGN KEY
      [index_name] (index_col_name,...) [reference_definition]
  | CHECK (expr)

column_definition:
    col_name data_type [NOT NULL | NULL] [DEFAULT default_value]
      [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
      [COMMENT 'string'] [reference_definition]


-- 行业产业代码表(MYSQL脚本)
DROP TABLE IF EXISTS DM_HY_CY;
CREATE TABLE DM_HY_CY(
XH INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '序号',
MLDM VARCHAR(1) COMMENT '门类代码',
MLMC VARCHAR(120) COMMENT '门类名称',
CYDM VARCHAR(1) COMMENT '产业代码',
CYMC VARCHAR(30) COMMENT '产业名称'
)ENGINE=MYISAM AUTO_INCREMENT=1 DEFAULT CHARSET=GBK  COMMENT '行业产业代码表';

-- 初始化数据(DB2和MySQL通用)
INSERT INTO DM_HY_CY(MLDM,MLMC) VALUES
('A','农、林、牧、渔业'),
('B','采矿业'),
('C','制造业'),
('D','电力、燃气及水的生产和供应业'),
('E','建筑业'),
('F','交通运输、仓储和邮政业'),
('G','信息传输、计算机服务和软件业'),
('H','批发和零售业'),
('I','住宿和餐饮业'),
('J','金融业'),
('K','房地产业'),
('L','租赁和商务服务业'),
('M','科学研究、技术服务和地质勘查业'),
('N','水利、环境和公共设施管理业'),
('O','居民服务和其他服务业'),
('P','教育'),
('Q','卫生、社会保障和社会福利业'),
('R','文化、体育和娱乐业'),
('S','公共管理与社会组织'),
('T','国际组织');
COMMIT;

UPDATE DM_HY_CY
SET CYDM='1',CYMC='第一产业'
WHERE MLDM='A';
COMMIT;

UPDATE DM_HY_CY
SET CYDM='2',CYMC='第二产业'
WHERE MLDM IN('B','C','D','E');
COMMIT;

UPDATE DM_HY_CY
SET CYDM='3',CYMC='第三产业'
WHERE CYDM IS NULL;
COMMIT;


创建数据库表完成后结果如下:
[img]http://fantasyyong840205.iteye.com/upload/picture/pic/7650/0719e154-7e34-3647-8d73-b89418c91779.png [/img]
一、SQL分页

1、静态分页

SELECT XH,MLDM,MLMC FROM DM_HY_CY LIMIT 2,3;

执行结果:
+----+------+------------------------------+
| XH | MLDM | MLMC                         |
+----+------+------------------------------+
|  3 | C    | 制造业                       |
|  4 | D    | 电力、燃气及水的生产和供应业 |
|  5 | E    | 建筑业                       |
+----+------+------------------------------+
截图如下:
[img]http://fantasyyong840205.iteye.com/upload/picture/pic/7652/f587ea21-b781-3bf9-8579-52fed09851d9.png [/img]

2、动态分页
引用
Mysql语法参考:
SQL syntax for prepared statements is based on three SQL statements:

PREPARE stmt_name FROM preparable_stmt 


The PREPARE statement prepares a statement and assigns it a name, stmt_name, by which to refer to the statement later.

PREPARE声明预制了一个声明并且给它赋予一个名称stmt_name,今后通过这个名称来引用这个声明。

Statement names are not case sensitive. preparable_stmt is either a string literal or a user variable that contains the text of the statement. The text must represent a single SQL statement, not multiple statements. Within the statement, ‘?’ characters can be used as parameter markers to indicate where data values are to be bound to the query later when you execute it. The ‘?’ characters should not be enclosed within quotes, even if you intend to bind them to string values. Parameter markers can be used only where data values should appear, not for SQL keywords, identifiers, and so forth.

声明的名称不区分大小写。preparable_stmt可能是一个字符串字面,也可能是用户变量,这个变量包含了声明的正文。声明正文必须实现一个单独的SQL声明,而不是多个声明。在这个声明中,“?”字符可以被用作参数标识来指出参数的数据值。在今后执行声明的时候,这些参数会绑定给查询语句。

If a prepared statement with the given name already exists, it is deallocated implicitly before the new statement is prepared. This means that if the new statement contains an error and cannot be prepared, an error is returned and no statement with the given name exists.

The scope of a prepared statement is the client session within which it is created. Other clients cannot see it.

EXECUTE stmt_name [USING @var_name [, @var_name] ...] 


After preparing a statement, you execute it with an EXECUTE statement that refers to the prepared statement name. If the prepared statement contains any parameter markers, you must supply a USING clause that lists user variables containing the values to be bound to the parameters. Parameter values can be supplied only by user variables, and the USING clause must name exactly as many variables as the number of parameter markers in the statement.

You can execute a given prepared statement multiple times, passing different variables to it or setting the variables to different values before each execution.

{DEALLOCATE | DROP} PREPARE stmt_name 


To deallocate a prepared statement, use the DEALLOCATE PREPARE statement. Attempting to execute a prepared statement after deallocating it results in an error.

If you terminate a client session without deallocating a previously prepared statement, the server deallocates it automatically.

The following SQL statements can be used in prepared statements: CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, and most SHOW statements. supported. ANALYZE TABLE, OPTIMIZE TABLE, and REPAIR TABLE are supported as of MySQL 5.0.23. Other statements are not yet supported.

The following examples show two equivalent ways of preparing a statement that computes the hypotenuse of a triangle given the lengths of the two sides.

实例1:
The first example shows how to create a prepared statement by using a string literal to supply the text of the statement:

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;

执行结果:
+------------+
| hypotenuse |
+------------+
|          5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;


实例2:
The second example is similar, but supplies the text of the statement as a user variable:

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;

执行结果:
+------------+
| hypotenuse |
+------------+
|         10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;




PREPARE STMT1 FROM 'SELECT XH,MLDM,MLMC FROM DM_HY_CY LIMIT ?,?';
SET @START=2;
SET @SIZE=3;
EXECUTE STMT1 USING @START,@SIZE;


说明:

预制语句的SQL语法基于三个SQL语句:

PREPARE stmt_name FROM preparable_stmt; 

stmt_name 是预处理语句的标识,是一个将要执行的SQL语句。里面如果有参数,则用“?”替换,“?”在这里也叫占位符。类似JDBC预处理SQL语句。

EXECUTE stmt_name [USING @var_name [, @var_name] ...]; 
执行一个预处理语句stmt_name,USING表示使用了动态变量(变量名前有“@”标识符),@var_name [, @var_name] ... 是参数列表,按顺序赋值给预处理SQL中的(占位)参数。

{DEALLOCATE | DROP} PREPARE stmt_name;
删除或者分配存储单元给预处理语句。

说明:在MySQL5中,可以使用动态变量,动态变量的类型是不确定的,可以多次赋不同类型的值,动态变量的类型取决于其值的具体类型。动态变量定义的定义和使用就像随地大小便一样,有需要就当即解决。定义的方式也很简单:SET @var_name=...,在定义的时候就给定了值。

执行结果和1一样,截图如下:
[img]http://fantasyyong840205.iteye.com/upload/picture/pic/7654/017afee4-3763-343c-b2bd-b3836cf4401b.png [/img]

二、存储过程分页
--创建存储过程Mysql语法说明:
CREATE
    [DEFINER = { user | CURRENT_USER }]
    PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body

CREATE
    [DEFINER = { user | CURRENT_USER }]
    FUNCTION sp_name ([func_parameter[,...]])
    RETURNS type
    [characteristic ...] routine_body
    
proc_parameter:
    [ IN | OUT | INOUT ] param_name type
    
func_parameter:
    param_name type

type:
    Any valid MySQL data type

characteristic:
    LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
  | COMMENT 'string'


-- 设定语句定界符为 $$
DELIMITER $$
-- 预防性删除存储过程
DROP PROCEDURE IF EXISTS testdb.SP_PAGINATION$$
 
-- 声明创建存储过程
CREATE PROCEDURE SP_PAGINATION(IN IN_START INTEGER(11), IN IN_SIZE INTEGER(11))
-- ------------------------------------------
-- 说明:MySQL5存储过程分页
-- 语言:MySQL
-- 作者:熔 岩
-- 日期:2007-9-1
-- ------------------------------------------
BEGIN
 
-- 定义两个动态变量,接收存储过程中的分页参数
SET @START=IN_START;
SET @SIZE=IN_SIZE;
 
-- 定义预处理SQL查询语句
PREPARE STMT FROM 'SELECT MLDM,MLMC FROM DM_HY_CY LIMIT ?,?';
 
-- 执行预处理语句,并用动态变量替换参数占位符
EXECUTE STMT USING @START,@SIZE;
 
END
-- 存储过程声明结束
$$
-- 设定语句定界符为 “;”,以保证后来的以分号结尾的SQL正常执行
DELIMITER ;

存储过程部署截图:
[img]http://fantasyyong840205.iteye.com/upload/picture/pic/7656/1b72b533-9dab-3486-93f8-e9828e0cdda8.png [/img]

然后用命令执行:
CALL SP_PAGINATION(2,3);

返回结果如下:
[img]http://fantasyyong840205.iteye.com/upload/picture/pic/7660/ebfa5c1c-13fb-3580-b70c-0671909abfa6.png [/img]

反面教材:如果不使用预处理SQL,不管你怎么搞,这个动态根据传递参数分页都是无法实现的。

下面我就给出我刚开始用DB2的经验实现MySQL5存储过程分页的例子,结果当然是失败了。现在给出来,大家看看:

DELIMITER $$
DROP PROCEDURE IF EXISTS testdb.SP_PAGINATION$$
CREATE PROCEDURE SP_PAGINATION(IN IN_START INTEGER(11), IN IN_SIZE INTEGER(11))
-- ------------------------------------------
-- 说明:反面教材,切勿模仿!MySQL5存储过程分页
-- 语言:MySQL
-- 作者:熔 岩
-- 日期:2007-9-1
-- ------------------------------------------
BEGIN
 
-- 直接利用调用参数在LIMIT子句中用
SELECT MLDM,MLMC FROM DM_HY_CY LIMIT IN_START,IN_SIZE;
 
END
$$
DELIMITER ;

不过这个反面教材在DB2下是完全可行的。

引用

总结:MySQL5存储过程分页目前我所知道就这几种,也许MySQL会在将来新版本中支持LIMIT的表达式参数,但眼前的是要解决问题。希望这篇文章能对您MySQL过程分页提供一种解决方案,节省摸索研究的时间。也希望各位博友广开言路,提出更多的见解。

分享到:
评论

相关推荐

    C++实现MySQL分页查询

    本篇文章将深入探讨如何利用C++实现MySQL的分页查询功能,这对于处理大量数据时提高系统性能和用户体验至关重要。 首先,我们需要引入MFC(Microsoft Foundation Classes)库,这是一个由Microsoft为Windows平台...

    易语言MYSQL数据库分页查询

    3. **执行SQL**:使用易语言的“执行SQL”命令,将创建好的SQL语句发送到MySQL服务器执行,获取查询结果。 4. **处理结果**:易语言的“获取记录数”命令可以用来获取总记录数,这在计算总页数时非常有用。然后,...

    0.3 MySQL基础查询、分页查询

    MySQL基础查询、分页查询 本文将对 MySQL 基础查询、分页查询进行详细的介绍,并提供相关...这些知识点包括 desc 查询表结构、select 查询表数据、导入导出文件、分页查询、使用 # 号添加注释、新建查询和查询结果等。

    mysql数据库实现分页

    分页是将数据库查询结果分割成多个页面,每次请求只返回一部分数据,而不是一次性返回所有数据。这在Web应用中尤其常见,如搜索引擎、电商网站等,用户通常会通过点击“下一页”或“上一页”来浏览更多内容。 二、...

    nodejs mysql 实现分页的方法

    这两天学习了nodejs mysql 实现分页,很重要,所以,今天添加一点小笔记。 代码如下 var express = require('express'); var router = express.Router(); var settings = require('../settings.js'); var mysql =...

    如何优化Mysql千万级快速分页

    在实际开发中,我们经常会遇到 MySQL 数据库的性能问题,特别是在处理千万级数据时,分页查询的性能会变得非常慢。在这篇文章中,我们将探讨如何优化 MySQL 千万级快速分页,详细介绍解决方案。 问题描述 我们有一...

    JDBC-MySQL分页查询

    本教程将深入探讨如何使用JDBC和MySQL实现分页查询。 首先,我们需要理解分页的基本概念。分页是将大型数据集分割成较小、更易管理的部分,通常每页包含一定数量的记录。在Web应用中,这通常通过设置“每页条目数”...

    java web mysql 通用分页

    4. **返回结果**:将查询结果转换为JSON或其他格式,通过HTTP响应返回给前端。 5. **前端渲染**:前端接收到数据后,进行渲染展示,同时可能需要计算总页数,以便生成完整的分页导航。 在实际开发中,我们还需要...

    mysql存储过程实现分页

    ### MySQL存储过程实现分页 #### 背景与需求 在数据库操作中,分页是一种常见的需求,尤其是在处理大量数据时。通过分页技术,可以有效地减少每次查询的数据量,提高系统的响应速度和用户体验。MySQL作为一种广泛...

    ssm的mysql分页查询

    下面我们将深入探讨如何在SSM框架下实现MySQL的分页查询。 首先,我们来理解分页查询的基本概念。分页查询是指在获取数据时,不是一次性获取所有数据,而是按照一定的页码和每页的数据量来获取数据。这在展示大量...

    JSP+JavaBean实现MySQL子查询数据库分页

    本教程将详细讲解如何使用JSP(JavaServer Pages)配合JavaBean来实现MySQL数据库的子查询分页功能。在Eclipse 3.4环境下,我们可以轻松地完成这一过程。 首先,我们需要理解JSP和JavaBean的基本概念。JSP是一种...

    高效的MySQL分页

    总结来说,实现高效的MySQL分页查询需要考虑索引优化、使用新的SQL特性,以及借助合适的开发工具。同时,持续关注数据库性能监控,及时调整和优化查询策略,对于保持系统稳定和提升用户体验具有重要意义。

    MySQL 百万级分页优化(Mysql千万级快速分页)

    ### MySQL 百万级分页优化(Mysql千万级快速分页) #### 背景与挑战 在处理大规模数据集时,例如拥有数百万乃至数千万条记录的数据库表,传统的分页查询方法可能会遇到性能瓶颈。特别是使用`LIMIT`进行分页时,随着...

    accss, mysql asp通用分页自定义分页样式

    在这些数据库中,当查询结果集过大时,我们不会一次性将所有数据加载到页面上,而是通过分页技术分批加载,减轻服务器压力,提升用户浏览效率。 ASP是一种服务器端脚本语言,用于创建动态交互式网页。在ASP中,我们...

    mysql分页查询

    本文将深入探讨MySQL分页查询的原理、方法以及在Java开发中的应用。 ### 分页查询的基本概念 分页查询是指从数据库中获取特定范围的数据,通常是以页为单位进行加载。这种方式可以有效地减少网络传输的数据量,...

    mysql 分页源代码

    在分页场景中,JavaBean通过JDBC建立与MySQL数据库的连接,执行上述构造的SQL查询语句,然后处理返回的结果集。 MySQL是广泛使用的开源关系型数据库管理系统,支持高效的SQL查询和各种数据库操作。在分页查询时,...

    MySQL JAVA 分页

    本文将深入探讨MySQL与Java结合实现分页查询的技术细节。 首先,我们需要理解什么是分页。分页是将大量数据分为多个部分(页)进行显示,而不是一次性加载所有数据,这样可以减少内存占用,提高页面响应速度,并使...

    Gridview连接mysql以及分页显示

    为了将查询结果填充到GridView,我们需要使用数据集(DataSet)或数据表(DataTable)。以下是如何将数据读取到DataTable: ```csharp DataTable dataTable = new DataTable(); dataTable.Load(reader); ``` 然后...

    Oracle,SQl,MySql实现分页查询

    ### Oracle、SQL、MySQL 实现分页查询方法详解 在数据库操作中,分页查询是一项非常重要的技术,尤其是在处理大量数据时。本文将基于提供的文件信息,深入探讨三种不同的分页查询方法及其在Oracle、SQL Server...

Global site tag (gtag.js) - Google Analytics