系列文章目录
SQL全方位攻略:1.数据库介绍
SQL全方位攻略:2.SQL介绍
SQL全方位攻略:3.SQL标准
SQL全方位攻略:4. 标准SQL和SQL“方言”
文章目录
- 系列文章目录
- SQL “方言”大比拼:Oracle、MySQL、PostgreSQL限制检索行数语法详解(分页查询)
- 1. Oracle中使用ROWNUM或者ROW_NUMBER()函数实现限制检索行数和分页查询
- 1. 使用ROWNUM实现分页查询
- 语法1:随机获取表中的前n条数据
- 语法2:按照某列排序,获取表中的前n条数据(Top-N)
- 语法3:实现分页查询
- 2. 使用ROW_NUMBER()实现分页查询
- 语法1:获取表中的前n条数据
- 语法2:实现分页查询
- 2. MySQL使用LIMIT实现限制检索行数和分页查询
- 语法1:获取表中的前n条数据
- 语法2:LIMIT实现分页查询
- 语法3:LIMIT和OFFSET实现分页查询(兼容PostgreSQL)
- 3. PostgreSQL使用LIMIT和OFFSET实现限制检索行数和分页查询
- 语法1:获取表中的前n条数据
- 语法2:LIMIT和OFFSET实现分页查询
- 总结
【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。
编辑|SQL和数据库技术(ID:SQLplusDB)
SQL “方言”大比拼:Oracle、MySQL、PostgreSQL限制检索行数语法详解(分页查询)
Oracle、MySQL和PostgreSQL等关系型数据库中基本都支持标准SQL,虽然SQL的基本语法在这些数据库中是类似的,但是在一些特定的功能和语法上仍然存在差异。
在MySQL和PostgreSQL中,可以使用LIMIT和OFFSET关键字来实现分页查询(限制SELECT语句返回结果行数)的操作,而Oracle中则需要使用ROWNUM或者ROW_NUMBER()函数实现。
它们的具体用法如下:
1. Oracle中使用ROWNUM或者ROW_NUMBER()函数实现限制检索行数和分页查询
在Oracle中,使用ROWNUM或者ROW_NUMBER()函数都可以实现分页查询,用于限制SELECT语句返回结果行数。具体操作如下:
1. 使用ROWNUM实现分页查询
ROWNUM是Oracle中一个伪列,用于表示返回结果集中的行数。通过使用ROWNUM和WHERE语句,可以实现分页查询的操作。
语法1:随机获取表中的前n条数据
sql">SELECT *
FROM table_name
WHERE ROWNUM <= n;
语法2:按照某列排序,获取表中的前n条数据(Top-N)
sql">SELECT *
FROM (SELECT * FROM table_name ORDER BY table_column)
WHERE ROWNUM < n;
语法3:实现分页查询
sql">SELECT *
FROM (
SELECT ROWNUM rn, t.*
FROM (
SELECT *
FROM table_name
WHERE conditions
ORDER BY sort_key
) t
WHERE ROWNUM <= page_size * page_index
) t1
WHERE rn > page_size * (page_index - 1);
其中,page_size表示每页显示的记录数,page_index表示当前页数。这个查询语句中,先按照sort_key排序,然后取出前page_size * page_index个记录并加上ROWNUM,再通过WHERE语句过滤出第page_size * (page_index - 1) + 1到page_size * page_index行的记录。
2. 使用ROW_NUMBER()实现分页查询
ROW_NUMBER()函数是Oracle 9i及以上版本中引入的一个窗口函数,在排序后的结果中为每条记录分配一个序号。通过在SELECT语句中使用ROW_NUMBER()函数,并结合OVER子句和WHERE子句,也可以实现分页查询的操作,示例代码如下。
语法1:获取表中的前n条数据
sql">SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY column1, column2) AS rownum, column1, column2
FROM table_name
)
WHERE rownum <= :page_size;
其中,table_name为要查询的表名,column1和column2为要排序的列名,:page_size为每页显示的记录数。
上述SQL语句中,ROW_NUMBER()函数会按照column1和column2两个列的升序排列,并为每一行数据分配一个唯一的序号(rownum)。然后通过WHERE子句限制查询结果只返回前page_size条记录,即每页显示的数据。
需要注意的是,ROW_NUMBER()函数只能用于查询语句中,不能直接用于更新语句中。如果需要在更新语句中对数据进行排序,则需要使用ORDER BY子句。
语法2:实现分页查询
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY sort_key) rn, t.*
FROM table_name t
WHERE conditions
) WHERE rn > page_size * (page_index - 1) AND rn <= page_size * page_index;
SQL语句先按照sort_key排序,然后使用ROW_NUMBER()函数为每条记录分配一个序号,再通过WHERE语句过滤出第page_size * (page_index - 1) + 1到page_size * page_index行的记录。
总的来说,使用ROWNUM或者ROW_NUMBER()函数都可以实现Oracle中的分页查询,需要根据具体需求选择合适的语法。同时,需要注意在使用ROWNUM时要先排序再进行筛选,而使用ROW_NUMBER()则可以在OVER子句中指定排序方式。
参考:
ROWNUM Pseudocolumn
ROW_NUMBER
2. MySQL使用LIMIT实现限制检索行数和分页查询
MySQL中同样提供了限制检索行数语法,但是和Oracle不同使用LIMIT关键字。
在分页查询中,使用LIMIT还可以将结果集分成多个页面。
LIMIT {[offset,] row_count | row_count OFFSET offset}
语法1:获取表中的前n条数据
MySQL使用LIMIT关键字来限制返回结果集中的行数,语法如下:
sql">SELECT *
FROM table_name
LIMIT n;
其中,n为希望返回行数的值。
例:
sql">mysql> select count(*) from actor;
+----------+
| count(*) |
+----------+
| 200 |
+----------+
1 row in set (0.03 sec)
mysql> select * from actor limit 10;
+----------+------------+--------------+---------------------+
| actor_id | first_name | last_name | last_update |
+----------+------------+--------------+---------------------+
| 1 | PENELOPE | GUINESS | 2006-02-15 04:34:33 |
| 2 | NICK | WAHLBERG | 2006-02-15 04:34:33 |
| 3 | ED | CHASE | 2006-02-15 04:34:33 |
| 4 | JENNIFER | DAVIS | 2006-02-15 04:34:33 |
| 5 | JOHNNY | LOLLOBRIGIDA | 2006-02-15 04:34:33 |
| 6 | BETTE | NICHOLSON | 2006-02-15 04:34:33 |
| 7 | GRACE | MOSTEL | 2006-02-15 04:34:33 |
| 8 | MATTHEW | JOHANSSON | 2006-02-15 04:34:33 |
| 9 | JOE | SWANK | 2006-02-15 04:34:33 |
| 10 | CHRISTIAN | GABLE | 2006-02-15 04:34:33 |
+----------+------------+--------------+---------------------+
10 rows in set (0.00 sec)
语法2:LIMIT实现分页查询
为了实现分页查询,需要限制结果集中的行数同时还要跳过一定的行数,使用LIMIT可以将结果集分成多个页面,下面是LIMIT语法的详细说明:
sql">SELECT *
FROM table_name
LIMIT offset, row_count;
语法说明:
- offset表示查询结果的起始位置,即跳过多少条记录,取下一条记录作为返回记录。
- row_count表示要返回的记录数,也就是取几条记录。例:如果row_count为5,表示返回5条记录。
- 如果只给出LIMIT row_count,则默认offset为0,从第1条记录开始返回row_count条记录,即LIMIT row_count 等于 LIMIT 0, row_count。
- 如果查询结果不足指定的row_count条记录,则返回实际可用的记录数。
例:查询第2到12条记录
sql">mysql> select * from actor limit 2,10;
+----------+------------+--------------+---------------------+
| actor_id | first_name | last_name | last_update |
+----------+------------+--------------+---------------------+
| 3 | ED | CHASE | 2006-02-15 04:34:33 |
| 4 | JENNIFER | DAVIS | 2006-02-15 04:34:33 |
| 5 | JOHNNY | LOLLOBRIGIDA | 2006-02-15 04:34:33 |
| 6 | BETTE | NICHOLSON | 2006-02-15 04:34:33 |
| 7 | GRACE | MOSTEL | 2006-02-15 04:34:33 |
| 8 | MATTHEW | JOHANSSON | 2006-02-15 04:34:33 |
| 9 | JOE | SWANK | 2006-02-15 04:34:33 |
| 10 | CHRISTIAN | GABLE | 2006-02-15 04:34:33 |
| 11 | ZERO | CAGE | 2006-02-15 04:34:33 |
| 12 | KARL | BERRY | 2006-02-15 04:34:33 |
+----------+------------+--------------+---------------------+
10 rows in set (0.00 sec)
mysql>
语法3:LIMIT和OFFSET实现分页查询(兼容PostgreSQL)
为了兼容PostgreSQL,MySQL也支持LIMIT row_count OFFSET offset语法。
可以使用LIMIT和OFFSET关键字,语法如下:
SELECT *
FROM table_name
LIMIT n OFFSET m;
其中,n为希望返回的行数,m为需要跳过的行数。
对于上面的【查询第2到12条记录】的例子,还可以用LIMIT row_count OFFSET offset语法实现。
例:
sql">mysql> select * from actor limit 10 OFFSET 2;
+----------+------------+--------------+---------------------+
| actor_id | first_name | last_name | last_update |
+----------+------------+--------------+---------------------+
| 3 | ED | CHASE | 2006-02-15 04:34:33 |
| 4 | JENNIFER | DAVIS | 2006-02-15 04:34:33 |
| 5 | JOHNNY | LOLLOBRIGIDA | 2006-02-15 04:34:33 |
| 6 | BETTE | NICHOLSON | 2006-02-15 04:34:33 |
| 7 | GRACE | MOSTEL | 2006-02-15 04:34:33 |
| 8 | MATTHEW | JOHANSSON | 2006-02-15 04:34:33 |
| 9 | JOE | SWANK | 2006-02-15 04:34:33 |
| 10 | CHRISTIAN | GABLE | 2006-02-15 04:34:33 |
| 11 | ZERO | CAGE | 2006-02-15 04:34:33 |
| 12 | KARL | BERRY | 2006-02-15 04:34:33 |
+----------+------------+--------------+---------------------+
10 rows in set (0.00 sec)
mysql>
参考:
https://dev.mysql.com/doc/refman/8.0/en/select.html
3. PostgreSQL使用LIMIT和OFFSET实现限制检索行数和分页查询
在 PostgreSQL 中,可以使用 LIMIT
和 OFFSET
子句来限制检索的行数和进行分页查询。
SELECT select_list
FROM table_expression
[ ORDER BY … ]
[ LIMIT { number | ALL } ] [ OFFSET number ]
语法说明:
- SELECT select_list:从数据库中选取列的列表。您可以指定一个或多个列,使用逗号分隔。如果要检索所有列的数据,也可以使用通配符
*
。 - FROM table_expression:从数据库中选取数据的表名或视图。
- ORDER BY:按升序或降序排列检索的数据。可以根据一个或多个列进行排序,如果没有指定
ORDER BY
子句,则检索出的数据将以任意顺序返回。 - LIMIT { number | ALL }:限制要返回的记录数的数量。如果指定为数字,则表示要返回的记录数。如果设置为 ALL,则返回表中的所有记录。
- OFFSET number:从查询的结果集的开头开始省略前 number 个记录。
语法1:获取表中的前n条数据
要限制要检索的行数,可以仅使用 LIMIT
子句。
sql">SELECT * FROM table_name
LIMIT n;
在 PostgreSQL 的 SELECT 查询语句中,LIMIT 子句指定检索记录的最大数量。如果指定了 LIMIT 子句,将只返回指定数量的记录,即使实际情况下表中存在更多记录。但是,如果查询本身返回的行数少于 LIMIT 子句所指定的数量,则只会返回查询所产生的行数。
例如,假设执行如下查询:
SELECT * FROM my_table LIMIT 10;
如果 my_table 中只有 5 行,则只返回这 5 行,并且 LIMIT 子句将被保留。如果 my_table 中有 20 行,则只返回前 10 行。
语法2:LIMIT和OFFSET实现分页查询
要执行分页查询,需要同时使用 LIMIT
和 OFFSET
子句。
另外,在进行分页查询时,需要确保在表中有某种排序规则,以便在每次查询时都可以得到正确的结果。所以通常需要使用 ORDER BY
子句来指定表中的排序规则。
例如,下面是一个分页查询的示例:
sql">-- 创建表 table1
CREATE TABLE table1 (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
create_date TIMESTAMP NOT NULL
);
-- 插入一些数据
INSERT INTO table1 (name, create_date) VALUES
('John', '2020-11-01 09:00:00'),
('Mary', '2020-11-02 10:00:00'),
('Tom', '2020-11-03 11:00:00'),
('Kate', '2020-11-04 12:00:00'),
('Bob', '2020-11-05 13:00:00'),
('Lisa', '2020-11-06 14:00:00'),
('Peter', '2020-11-07 15:00:00'),
('Alice', '2020-11-08 16:00:00'),
('David', '2020-11-09 17:00:00'),
('Jane', '2020-11-10 18:00:00'),
('Alex', '2020-11-11 19:00:00'),
('Sarah', '2020-11-12 20:00:00'),
('Mike', '2020-11-13 21:00:00'),
('Lucy', '2020-11-14 22:00:00');
-- 运行查询
SELECT *
FROM table1
ORDER BY create_date
LIMIT 10
OFFSET 10;
执行结果输出例:
mydb1=# select * from table1;
id | name | create_date
----+-------+---------------------
1 | John | 2020-11-01 09:00:00
2 | Mary | 2020-11-02 10:00:00
3 | Tom | 2020-11-03 11:00:00
4 | Kate | 2020-11-04 12:00:00
5 | Bob | 2020-11-05 13:00:00
6 | Lisa | 2020-11-06 14:00:00
7 | Peter | 2020-11-07 15:00:00
8 | Alice | 2020-11-08 16:00:00
9 | David | 2020-11-09 17:00:00
10 | Jane | 2020-11-10 18:00:00
11 | Alex | 2020-11-11 19:00:00
12 | Sarah | 2020-11-12 20:00:00
13 | Mike | 2020-11-13 21:00:00
14 | Lucy | 2020-11-14 22:00:00
(14 rows)
mydb1=# SELECT *
mydb1-# FROM table1
mydb1-# ORDER BY create_date
mydb1-# LIMIT 10
mydb1-# OFFSET 10;
id | name | create_date
----+-------+---------------------
11 | Alex | 2020-11-11 19:00:00
12 | Sarah | 2020-11-12 20:00:00
13 | Mike | 2020-11-13 21:00:00
14 | Lucy | 2020-11-14 22:00:00
(4 rows)
mydb1=#
在上面的示例中,我们创建了一个名为 table1 的表,并插入一些数据。然后,我们运行了与原始 SQL 语句相同的查询,检索满足条件的前10行,从第11行开始显示。
我们在 create_date 列上对表进行排序,并检索从第11行开始的10行记录。由于表中仅有14条数据,所以最终的输出为4条数据。
参考:
>7.6. LIMIT and OFFSET
https://www.sql>postgresql.org/docs/14/sql-select.html
https://www.sql>postgresql.org/docs/14/queries-limit.html
总结
本文我们介绍了 Oracle、MySQL 和 PostgreSQL 数据库实现限制检索行数(分页查询)的语法及其不同之处。