从给查询结果集增加行号说起
在Linux下,我们可以用cat -n foo.c输出文件foo.c中的内容,并给每行加上行号。例如:
$ cat -n foo.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 int main(void)
6 {
7 printf("Hello, world!\\n");
8 exit(0);
9 }
10
类似的,我们也可以采用nl -b a foo.c得到同样的结果。例如:
$ nl -b a foo.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 int main(void)
6 {
7 printf("Hello, world!\\n");
8 exit(0);
9 }
10
Shell命令cat和nl的选项以及功能还是有些区别的,具体的差别可以查看man pages。在数据库应用中,有时也需要类似的功能,例如:给结果集中的每条元组依次编号。SQL标准并没有对此做出规定,不同的DBMS产品中实现该功 能的方式也就大相径庭了。
假设我们所要用的表及其元组为:
CREATE TABLE Student (SNO INT, SName CHAR(8), PRIMARY KEY(SNO));
INSERT INTO Student VALUES (1, 'Mary');
INSERT INTO Student VALUES (2, 'Bill');
INSERT INTO Student VALUES (3, 'Johnson');
我们所用的DBMS版本为(都是Windows版本):
MySQL 5.0.19
PostgreSQL 8.1.0
ORACLE 10g
MSSQL 2000
MySQL:
mysql> SET @rownum := 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @rownum := @rownum + 1 AS rownum, SNO, SName FROM Student;
+--------+-----+---------+
| rownum | SNO | SName |
+--------+-----+---------+
| 1 | 1 | Mary |
| 2 | 2 | Bill |
| 3 | 3 | Johnson |
+--------+-----+---------+
3 rows in set (0.01 sec)
PostgreSQL:
postgres=# CREATE TEMP SEQUENCE SEQ;
CREATE SEQUENCE
postgres=# SELECT NEXTVAL('SEQ'), SNO, SNAME
postgres-# FROM Student;
nextval | sno | sname
---------+-----+----------
1 | 1 | Mary
2 | 2 | Bill
3 | 3 | Johnson
(3 rows)
ORACLE:
SQL> SELECT ROWNUM, SNO, SNAME
2 FROM Student;
ROWNUM SNO SNAME
\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-
1 1 Mary
2 2 Bill
3 3 Johnson
MSSQL:
没有特别简单直观的玩法,MSSQL2000中的各种花样可以参考: http://www.databasejournal.com/features/mssql/article.php/10894_2244821_1。MSSQL2005中的做法可以参考: http://aspnet.4guysfromrolla.com/articles/031506-1.aspx#postadlink。
数据库应用中更多的是需要取出结果集中某个行号范围内的元组,以减少不必要的运行代价。最典型的应该是所谓的TOP N查询,即找出前N个符合要求的元组,而不是返回整个结果集。这些功能显然也可以用ROWNUM来完成。不过DBMS一般还提供了其他的办法。例如:我们 只需要上述结果集中从第二条元组开始的2条元组。
MySQL:
http://dev.mysql.com/doc/refman/5.0/en/select.html
mysql> SELECT SNO, SName
-\> FROM Student
-\> LIMIT 2 OFFSET 1;
+-----+---------+
| SNO | SName |
+-----+---------+
| 2 | Bill |
| 3 | Johnson |
+-----+---------+
2 rows in set (0.00 sec)
PostgreSQL:
postgres=# SELECT SNO, SName
postgres-# FROM Student
postgres-# LIMIT 2 OFFSET 1;
sno | sname
-----+----------
2 | Bill
3 | Johnson
(2 rows)
ORACLE:
SQL> SELECT * FROM
2 (SELECT SNO, SName FROM Student ORDER BY SNO)
3 WHERE ROWNUM < 3;
SNO SNAME
\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-
1 Mary
2 Bill
但是:
SQL> SELECT * FROM
2 (SELECT SNO, SName FROM Student ORDER BY SNO)
3 WHERE ROWNUM > 1 AND ROWNUM < 3;
no rows selected
更多复杂的玩法参见:
http://www.orafaq.com/faqsql.htm
http://www.psoug.org/reference/pseudocols.html
http://www.devx.com/gethelpon/10MinuteSolution/16608
MSSQL:
SELECT TOP 2 SNO, SName
FROM Student;
SNO SName
\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-
1 Mary
2 Bill
(所影响的行数为 2 行)
Comparison of different SQL implementations 是一个非常好的参考文献,它提供了不同DBMS之间很多特性的比较。
Copyright 2000-2006,zedware_at_gmail_dot_com
Last modified on Thursday, 2006-05-18