13.2.9单表查询 select
语句的功能就是查询数据。select
语句也是SQL
语句中功能最丰富的语句,select
语句不仅可以执行单表查询,而且可以执行多表连接查询,还可以进行子查询,select
语句用于从一个或多个数据表中选出特定行、特定列的交集。select
语句最简单的功能如图13.10所示。
测试数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 SET FOREIGN_KEY_CHECKS= 0 ;DROP TABLE IF EXISTS `student_table`;CREATE TABLE `student_table` ( `student_id` int (11 ) NOT NULL AUTO_INCREMENT, `student_name` varchar (255 ) DEFAULT NULL , `java_teacher` int (11 ) DEFAULT NULL , PRIMARY KEY (`student_id`), KEY `java_teacher` (`java_teacher`), CONSTRAINT `student_table_ibfk_1` FOREIGN KEY (`java_teacher`) REFERENCES `teacher_table` (`teacher_id`) ) ENGINE= InnoDB AUTO_INCREMENT= 10 DEFAULT CHARSET= utf8; INSERT INTO `student_table` VALUES ('1' , '张三' , '1' );INSERT INTO `student_table` VALUES ('2' , '张三' , '1' );INSERT INTO `student_table` VALUES ('3' , '李四' , '1' );INSERT INTO `student_table` VALUES ('4' , '王五' , '2' );INSERT INTO `student_table` VALUES ('5' , '_王五' , '2' );INSERT INTO `student_table` VALUES ('6' , null , '2' );INSERT INTO `student_table` VALUES ('7' , '赵六' , '3' );DROP TABLE IF EXISTS `teacher_table`;CREATE TABLE `teacher_table` ( `teacher_id` int (11 ) NOT NULL AUTO_INCREMENT, `teacher_name` varchar (255 ) DEFAULT NULL , PRIMARY KEY (`teacher_id`) ) ENGINE= InnoDB AUTO_INCREMENT= 4 DEFAULT CHARSET= utf8; INSERT INTO `teacher_table` VALUES ('1' , 'Yeeku' );INSERT INTO `teacher_table` VALUES ('2' , 'Leegang' );INSERT INTO `teacher_table` VALUES ('3' , 'Martine' );
语法格式 单表查询的select
语句的语法格式如下:
1 2 3 select column1,column2,...from 数据源[where condition ]
数据源可以是表、视图等 。
select
后的列表用于确定选择哪些列
where
条件用于确定选择哪些行
选择所有行 只有满足where
条件的记录才会被选择出来;如果没有where
条件,则默认选出所有行 。
选择所有列 如果想选择出所有列,则可使用星号(*
)代表所有列 。
选择特定行特定列 如果增加where
条件,则只选择出符合where
条件的记录。如下SQL
语句将选择出student_table
表中java_teacher
值大于3
的记录的student_name
列的值。
1 2 3 select student_name from student_table where java_teacher> 3 ;
运行结果:
1 2 3 4 5 6 7 8 9 10 mysql> select student_name from student_table where java_teacher>2 ; +--------------+ | student_name | +--------------+ | 赵六 | +--------------+ 1 row in set
选择所有行所有列 下面的SQL
语句将会选择出teacher_table
表中的所有行、所有列的数据。
1 select * from teacher_table;
运行效果:
1 2 3 4 5 6 7 8 9 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set
使用算术运算符 常亮 变量 当使用select
语句进行查询时,还可以在select
语句中使用算术运算符(+
、-
、*
、/
),从而形成算术表达式。使用算术表达式的规则如下。
对**数值型
数据列**、变量
、常量
可以使用算术运算符(+
、-
、*
、/
)创建表达式;
对**日期型
数据列、变量、常量可以使用部分算术运算符(+
、-
)创建表达式,两个日期之间可以进行减法运算 , 日期
和数值
之间可以进行加、减运算**;
运算符不仅可以在列
和常量
、变量
之间进行运算,也可以在两列之间
进行运算。不论从哪个角度来看,数据列都很像一个变量,只是这个变量的值具有指定的范围——逐行计算表中的每条记录时,数据列的值依次变化。因此能使用变量的地方,基本上都可以使用数据列。 下面的select
语句中使用了算术运算符。
实例 把数据列当成一个变量
1 2 select teacher_id+ 5 from teacher_table;
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select teacher_id+5 from teacher_table; +--------------+ | teacher_id+5 | +--------------+ | 6 | | 7 | | 8 | +--------------+ 3 rows in set
查询出teacher_table
表中teacher_id*3>4
的记录
1 2 3 select * from teacher_table where teacher_id* 3 > 4 ;
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select * from teacher_table where teacher_id*3 >4 ; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 2 | Leegang | | 3 | Martine | +------------+--------------+ 2 rows in set
select后写常亮变量 需要指出的是,select
后的不仅可以是数据列,也可以是表达式,还可以是变量、常量等。例如,如下语句也是正确的。
1 2 select 3 * 5 ,20 from teacher_table;
运行结果:
1 2 3 4 5 6 7 8 9 10 mysql> select 3 *5 ,20 from teacher_table; +-----+----+ | 3 *5 | 20 | +-----+----+ | 15 | 20 | | 15 | 20 | | 15 | 20 | +-----+----+ 3 rows in set
运算符优先级 SQL
语句中算术运算符的优先级与Java
语言中的运算符优先级完全相同,乘法和除法的优先级高于加法和减法,同级运算的顺序是从左到右,表达式中使用括号可强行改变优先级的运算顺序。
字符串连接运算 MySQL
中没有提供字符串连接运算符,即无法使用加号(+)将字符串常量、字符串变量或字符串列连接起来。MySQL
使用concat
函数来进行字符串连接运算。
1 2 select concat(teacher_name,'-教授' )from teacher_table;
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select concat(teacher_name,'-教授') from teacher_table; +------------------------------+ | concat(teacher_name,'-教授') | +------------------------------+ | Yeeku-教授 | | Leegang-教授 | | Martine-教授 | +------------------------------+ 3 rows in set
与null运算 对于MySQL
而言, **如果在算术表达式中使用null
,将会导致整个算术表达式的返回值为null
**; **如果在字符串连接运算中出现null
,将会导致连接后的结果也是null
**。 如下SQL
语句将会返回null
。
1 2 select concat(teacher_name,null )from teacher_table;
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select concat(teacher_name,null) from teacher_table; +---------------------------+ | concat(teacher_name,null) | +---------------------------+ | NULL | | NULL | | NULL | +---------------------------+ 3 rows in set mysql>
而对某些数据库而言,如果让字符串和null
进行连接运算,它会把null
当成空字符串处理。
取别名 给列取别名 如果不希望直接使用列名作为列标题,则可以为数据列或表达式起一个别名,为数据列或表达式起别名时,别名紧跟数据列,中间以空格隔开,或者使用as
关键字隔开。如下SQL
语句所示:
1 2 select teacher_id+ 5 as MY_IDfrom teacher_table
查询效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select teacher_id+5 as MY_ID from teacher_table; +-------+ | MY_ID | +-------+ | 6 | | 7 | | 8 | +-------+ 3 rows in set mysql> select teacher_id+5 from teacher_table; +--------------+ | teacher_id+5 | +--------------+ | 6 | | 7 | | 8 | +--------------+ 3 rows in set mysql>
别名中有特殊字符的情况: 添加双引号 为列起别名,可以改变列的标题头,用于表示计算结果的具体含义。如果列别名中使用特殊字符(例如空格),或者需要强制大小写敏感,都可以通过为别名添加双引号 来实现。如下SQL语句所示:
1 2 select teacher_id+ 5 "MY`'#@! &%ID"from teacher_table;
查询效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select teacher_id+5 "MY`'#@! &%ID" from teacher_table; +--------------+ | MY`'#@! &%ID | +--------------+ | 6 | | 7 | | 8 | +--------------+ 3 rows in set mysql>
多列取别名 如果需要选择多列,并为多列起别名,则列与列之间以逗号隔开,但列和列别名之间以空格隔开。如下SQL
语句所示:
1 2 select teacher_id+ 5 MY_ID,teacher_name 老师名from teacher_table;
查询效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select teacher_id+5 MY_ID,teacher_name 老师名 from teacher_table; +-------+---------+ | MY_ID | 老师名 | +-------+---------+ | 6 | Yeeku | | 7 | Leegang | | 8 | Martine | +-------+---------+ 3 rows in set
给表取别名 不仅可以为列或表达式起别名,也可以为表起别名,为表起别名的语法和为列或表达式起别名的语法完全一样,如下SQL
语句所示:
1 2 3 select teacher_id+ 5 MY_ID,teacher_name 老师名#为teacher_table起别名t from teacher_table t;
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mysql> select * from teacher_table; + | teacher_id | teacher_name | + | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | + 3 rows in set mysql> select teacher_id+ 5 MY_ID,teacher_name 老师名 #为teacher_table起别名t from teacher_table t;+ | MY_ID | 老师名 | + | 6 | Yeeku | | 7 | Leegang | | 8 | Martine | + 3 rows in set
多列运算 前面已经提到,列名可以当成变量处理,所以运算符也可以在多列之间进行运算,如下SQL
语句所示:
1 2 3 4 select teacher_id+ 5 MY_TD,concat(teacher_name,teacher_id) teacher_name_id from teacher_tablewhere teacher_id* 2 > 3 ;
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select teacher_id+5 MY_TD, concat(teacher_name,teacher_id) teacher_name_id from teacher_table where teacher_id*2 >3 ; +-------+-----------------+ | MY_TD | teacher_name_id | +-------+-----------------+ | 7 | Leegang2 | | 8 | Martine3 | +-------+-----------------+ 2 rows in set
不出现列名 甚至可以在select
、where
子句中都不出现列名,如下SQL
语句所示:
1 2 3 select 5 + 4 from teacher_tablewhere 2 < 9 ;
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mysql> select * from teacher_table; +------------+--------------+ | teacher_id | teacher_name | +------------+--------------+ | 1 | Yeeku | | 2 | Leegang | | 3 | Martine | +------------+--------------+ 3 rows in set mysql> select 5 +4 from teacher_table where 2 <9 ; +-----+ | 5 +4 | +-----+ | 9 | | 9 | | 9 | +-----+ 3 rows in set
这种情况比较特殊:where
语句后的条件表达式总是true
,所以会把teacher_table
表中的每条记录都选择出来——但SQL
语句没有选择任何列,仅仅选择了一个常量,所以SQL
会把该常量当成一列,teacher_table
表中有多少条记录,该常量就出现多少次。
选择常量 对于选择常量的情形,指定数据表可能没有太大的意义,所以MySQL
提供了一种扩展语法,允许select
语句后没有from
子句,即可写成如下形式:
查询结果:
1 2 3 4 5 6 7 mysql> select 5 +4 ; +-----+ | 5 +4 | +-----+ | 9 | +-----+ 1 row in set
上面这种语句并不是标准SQL
语句。例如,Oracle
就提供了一个名为dual
的虚表(最新的MySQL
数据库也支持dual
虚表),它没有任何意义,仅仅相当于from
后的占位符。如果选择常量,则可使用如下语句:
结果:
1 2 3 4 5 6 7 mysql> select 5 +4 from dual; +-----+ | 5 +4 | +-----+ | 9 | +-----+ 1 row in set
清除重复行 select
默认会把所有符合条件的记录全部选出来,即使两行记录完全一样。如果想去除重复行,则可以使用distinct
关键字从查询结果中清除重复行。比较下面两条SQL
语句的执行结果:
1 2 3 4 5 6 #包括重复行 select student_name,java_teacherfrom student_table;#去除重复行 select distinct student_name,java_teacherfrom student_table;
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 mysql> select * from student_table; +------------+--------------+--------------+ | student_id | student_name | java_teacher | +------------+--------------+--------------+ | 1 | 张三 | 1 | | 2 | 张三 | 1 | | 3 | 李四 | 1 | | 4 | 王五 | 2 | | 5 | _王五 | 2 | | 6 | NULL | 2 | | 7 | 赵六 | 3 | +------------+--------------+--------------+ 7 rows in set mysql> select student_name,java_teacher from student_table; +--------------+--------------+ | student_name | java_teacher | +--------------+--------------+ | 张三 | 1 | | 张三 | 1 | | 李四 | 1 | | 王五 | 2 | | _王五 | 2 | | NULL | 2 | | 赵六 | 3 | +--------------+--------------+ 7 rows in set mysql> #去除重复行 select distinct student_name,java_teacher from student_table; +--------------+--------------+ | student_name | java_teacher | +--------------+--------------+ | 张三 | 1 | | 李四 | 1 | | 王五 | 2 | | _王五 | 2 | | NULL | 2 | | 赵六 | 3 | +--------------+--------------+ 6 rows in set
注意使用distinct
去除重复行时,distinct
紧跟在select
关键字后面。它的作用是去除后面字段组合的重复值,而不管对应记录在数据库里是否重复 。例如,(1,ˈaˈ,ˈbˈ)和(2,ˈaˈ,ˈbˈ)两条记录在数据库里是不重复的,但如果仅选择后面两列,则distinct
会认为两条记录重复。