SQL语句简介及练习

SQL语言的兴起与语法标准

20世纪70年代,IBM开发出SQL,用于DB2

1981年,IBM推出SQL/DS数据库

业内标准微软和Sybase的T-SQL,Oracle的PL/SQL

SQL作为关系型数据库所使用的标准语言,最初是基于IBM的实现在1986年被批准的。1987年,“国际标准化组织(ISO)”把ANSI(美国国家标准化组织) SQL作为国际标准。

SQL:ANSI SQL

SQL-86, SQL-89, SQL-92, SQL-99, SQL-03

SQL语言规范

在数据库系统中,SQL语句不区分大小写(建议用大写)

但字符串常量区分大小写

SQL语句可单行或多行书写,以“;”结尾

关键词不能跨多行或简写

用空格和缩进来提高语句的可读性

子句通常位于独立行,便于编辑,提高可读性

注释:

SQL标准:

/*注释内容*/ 多行注释

-- 注释内容 单行注释,注意有空格

MySQL注释:

除了SQL标准外还可以用#

数据库对象

数据库的组件(对象):

数据库、表、索引、视图、用户、存储过程、函数、触发器、事件调度器等

命名规则:

必须以字母开头

可包括数字和三个特殊字符(# _ $,#和$尽量别用)

不要使用MySQL的保留字

同一database(Schema)下的对象不能同名,即使是不同类型的对象

SQL语句分类

SQL语句分类:

DDL: Data Defination Language

CREATE, DROP, ALTER

DML: Data Manipulation Language

INSERT, DELETE, UPDATE

DCL:Data Control Language

GRANT, REVOKE

DQL:Data Query Language

SELECT

SQL语句构成

SQL语句构成:

Keyword组成clause(子句)

多条clause组成语句

示例:

SELECT * SELECT子句

FROM products FROM子句

WHERE price>400 WHERE子句

说明:此为一组SQL语句,由三个子句构成,SELECT,FROM和WHERE是关键字

数据库操作

创建数据库:

CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME'; #创建数据库

CHARACTER SET 'character set name' #指定字符集

COLLATE 'collate name' #指定排序方式

删除数据库

DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';

查看支持所有字符集:SHOW CHARACTER SET;

查看支持所有排序规则:SHOW COLLATION;

获取命令使用帮助:

mysql> HELP KEYWORD;

例:HELP CREATE DATABASE;

看到基本用法及帮助文档的链接,可以去看

URL: http://dev.mysql.com/doc/refman/5.5/en/create-database.html

查看数据库列表:

mysql> SHOW DATABASES;

[[email protected] ~]#cat /var/lib/mysql/db1/db.opt

default-character-set=latin1

default-collation=latin1_swedish_ci

表:二维关系

设计表:遵循规范

定义:字段,索引

字段:字段名,字段数据类型,修改符

约束,索引:应该创建在经常用作查询条件的字段上

创建表

创建表:CREATE TABLE

(1) 直接创建

(2) 通过查询现存表创建;新表会被直接插入查询而来的数据

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options]

[partition_options] select_statement

(3) 通过复制现存的表的表结构创建,但不复制数据

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKE old_tbl_name) }

注意:

Storage Engine是指表类型,也即在表创建时指明其使用的存储引擎,同一库中不同表可以使用不同的存储引擎

同一个库中表建议要使用同一种存储引擎类型

创建表

CREATE TABLE [IF NOT EXISTS] 'tbl_name' (col1 type1 修饰符, col2 type2 修饰符, ...) #[IF NOT EXISTS]字段在脚本中一般要加

字段信息

?col type1

?PRIMARY KEY(col1,...)

?INDEX(col1, ...)

?UNIQUE KEY(col1, ...)

表选项:

?ENGINE [=] engine_name

SHOW ENGINES;查看支持的engine类型

?ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}

获取帮助:mysql> HELP CREATE TABLE;

表操作

查看所有的引擎:SHOW ENGINES

查看表:SHOW TABLES [FROM db_name]

查看表结构:DESC [db_name.]tb_name

删除表:DROP TABLE [IF EXISTS] tb_name

查看表创建命令:SHOW CREATE TABLE tbl_name

查看表状态:SHOW TABLE STATUS LIKE 'tbl_name'

查看库中所有表状态:SHOW TABLE STATUS FROM db_name

数据类型

数据类型:

数据长什么样?

数据需要多少空间来存放?

系统内置数据类型和用户定义数据类型

MySql支持多种列类型:

数值类型

日期/时间类型

字符串(字符)类型

https://dev.mysql.com/doc/refman/5.5/en/data-types.html

选择正确的数据类型对于获得高性能至关重要,三大原则:

更小的通常更好,尽量使用可正确存储数据的最小数据类型

简单就好,简单数据类型的操作通常需要更少的CPU周期

尽量避免NULL,包含为NULL的列,对MySQL更难优化(可填个默认值)

数据类型

 

数据类型

1、整型

tinyint(m) 1个字节 范围(-128~127)

smallint(m) 2个字节 范围(-32768~32767)

mediumint(m) 3个字节 范围(-8388608~8388607)

int(m) 4个字节 范围(-2147483648~2147483647)

bigint(m) 8个字节 范围(+-9.22*10的18次方)

取值范围如果加了unsigned,则最大值翻倍,如tinyint unsigned的取值范围为(0~255)

int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,规定了MySQL的一些交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说,Int(1)和Int(20)是相同的

BOOL,BOOLEAN:布尔型,是TINYINT(1)的同义词。zero值被视为假。非zero值视为真

2、浮点型(float和double),近似值

float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位

double(m,d) 双精度浮点型16位精度(8字节) m总个数,d小数位

设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位

3、定点数

在数据库中存放的是精确值,存为十进制

decimal(m,d) 参数m<65 是总个数,d<30且 d<m 是小数位

MySQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。例如,decimal(18,9)小数点两边将各存储9个数字,一共使用9个字节:小数点前的数字用4个字节,小数点后的数字用4个字节,小数点本身占1个字节

浮点类型在存储同样范围的值时,通常比decimal使用更少的空间。float使用4个字节存储。double占用8个字节

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用decimal——例如存储财务数据。但在数据量比较大的时候,可以考虑使用bigint代替decimal

4、字符串(char,varchar,_text)

char(n) 固定长度,最多255个字符

varchar(n)可变长度,最多65535个字符

tinytext 可变长度,最多255个字符

text 可变长度,最多65535个字符

mediumtext 可变长度,最多2的24次方-1个字符

longtext 可变长度,最多2的32次方-1个字符

BINARY(M) 固定长度,可存二进制或字符,长度为0-M字节

VARBINARY(M) 可变长度,可存二进制或字符,允许长度为0-M字节

内建类型:ENUM枚举, SET集合

char和varchar:

?1.char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉。所以char类型存储的字符串末尾不能有空格,varchar不限于此。

?2.char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n< n>255),所以varchar(4),存入3个字符将占用4个字节。

?3.char类型的字符串检索速度要比varchar类型的快

varchar和text:

?1.varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n< n>255),text是实际字符数+2个字节。

?2.text类型不能有默认值

?3.varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text

5.二进制数据:BLOB

?BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob是以二进制方式存储,不分大小写

?BLOB存储的数据只能整体读出

?TEXT可以指定字符集,BLOB不用指定字符集

6.日期时间类型

?date 日期 '2008-12-2'

?time 时间 '12:25:36'

?datetime 日期时间 '2008-12-2 22:06:44'

?timestamp 自动存储记录修改时间

?YEAR(2), YEAR(4):年份

timestamp字段里的时间数据会随其他字段修改的时候自动刷新,这个数据类型的字段可以存放这条记录最后被修改的时间

修饰符

所有类型:

?NULL 数据列可包含NULL值

?NOT NULL 数据列不允许包含NULL值

?DEFAULT 默认值

?PRIMARY KEY 主键

?UNIQUE KEY 唯一键

?CHARACTER SET name 指定一个字符集

数值型

?AUTO_INCREMENT 自动递增,适用于整数类型

?UNSIGNED 无符号

示例

CREATE TABLE students (id int UNSIGNED NOT NULL PRIMARY KEY,name VARCHAR(20)NOT NULL,age tinyint UNSIGNED);

DESC students;

CREATE TABLE students2 (id int UNSIGNED NOT NULL ,name VARCHAR(20) NOT NULL,age tinyint UNSIGNED,PRIMARY KEY(id,name));

表操作

DROP TABLE [IF EXISTS] 'tbl_name'; [CASCADE](级联删除)

ALTER TABLE 'tbl_name'

字段:

添加字段:add

ADD col1 data_type [FIRST|AFTER col_name]

删除字段:drop

修改字段:

alter(默认值), change(字段名), modify(字段属性)

索引:

添加索引:add index

删除索引: drop index

表选项

修改:

查看表上的索引:SHOW INDEXES FROM [db_name.]tbl_name;

查看帮助:Help ALTER TABLE

修改表示例

ALTER TABLE students RENAME s1;

ALTER TABLE s1 ADD phone varchar(11) AFTER name;

ALTER TABLE s1 MODIFY phone int;

ALTER TABLE s1 CHANGE COLUMN phone mobile char(11);

ALTER TABLE s1 DROP COLUMN mobile;

Help ALTER TABLE 查看帮助

修改表示例

ALTER TABLE students ADD gender ENUM('m','f')(enum单选/枚举,set多选)

ALETR TABLE students CHANGE id sid int UNSIGNED NOT NULL PRIMARY KEY;

ALTER TABLE students ADD UNIQUE KEY(name);

ALTER TABLE students ADD INDEX(age);

DESC students;

SHOW INDEXES FROM students;

ALTER TABLE students DROP age;

DML语句

DML:INSERT, DELETE, UPDATE, SELECT

INSERT:

一次插入一行或多行数据

语法

INSERT [L OW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]

[INTO] tbl_name [(col_name,...)]

{VALUES | VALUE} ({expr | DEFAULT},...),(...),...

[ ON DUPLICATE KEY UPDATE 如果重复更新之

col_name=expr

[, col_name=expr] ... ]

简化写法:

INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)

DML语句

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]

[INTO] tbl_name

SET col_name={expr | DEFAULT}, ...

[ ON DUPLICATE KEY UPDATE

col_name=expr

[, col_name=expr] ... ]

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]

[INTO] tbl_name [(col_name,...)]

SELECT ...

[ ON DUPLICATE KEY UPDATE

col_name=expr

[, col_name=expr] ... ]

DML语句

UPDATE:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference

SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...

[WHERE where_condition]

[ORDER BY ...]

[LIMIT row_count]

注意:一定要有限制条件,否则将修改所有行的指定字段

限制条件:

WHERE

LIMIT

Mysql 选项:--safe-updates| --i-am-a-dummy|-U

DML语句

DELETE:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name

[WHERE where_condition]

[ORDER BY ...]

[LIMIT row_count]

可先排序再指定删除的行数

注意:一定要有限制条件,否则将清空表中的所有数据

限制条件:

WHERE

LIMIT

TRUNCATE TABLE tbl_name; 清空表

DQL语句

SELECT

[ALL | DISTINCT | DISTINCTROW ]

[SQL_CACHE | SQL_NO_CACHE]

select_expr [, 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}]

[FOR UPDATE | LOCK IN SHARE MODE]

SELECT

字段显示可以使用别名:

col1 AS alias1, col2 AS alias2, ...(AS可不写)

WHERE子句:指明过滤条件以实现“选择”的功能:

过滤条件:布尔型表达式

算术操作符:+, -, *, /, %

比较操作符:=, !=, <>, <=, >, >=, <, <=

BETWEEN min_num AND max_num

IN (element1, element2, ...)

IS NULL

IS NOT NULL

SELECT

DISTINCT 去除重复列

SELECT DISTINCT gender FROM students;

LIKE:

%: 任意长度的任意字符

_:任意单个字符

RLIKE:正则表达式,索引失效,不建议使用

REGEXP:匹配字符串可用正则表达式书写模式,同上

逻辑操作符:

NOT

AND

OR

XOR

SELECT

GROUP:根据指定的条件把查询结果进行“分组”以用于做“聚合”运算

avg(), max(), min(), count(), sum()

建议:一旦用分组,前边select只需要写用以分组的字段,和统计的函数,写别的字段没有意义

HAVING: 对分组聚合运算后的结果指定过滤条件(在分组前做过滤用where)

ORDER BY: 根据指定的字段对查询结果进行排序

升序:ASC

降序:DESC

示例:

MariaDB [db1]> select * from students order by score; 顺序,NULL在前

MariaDB [db1]> select * from students order by -score desc; 顺序,但NULL在后

LIMIT [[offset,]row_count]:对查询的结果进行输出行数数量限制

对查询结果中的数据请求施加“锁”

FOR UPDATE: 写锁,独占或排它锁,只有一个读和写

LOCK IN SHARE MODE: 读锁,共享锁,同时多个读(但只能有一个写)

示例

DESC students;

INSERT INTO students VALUES(1,'tom','m'),(2,'alice','f');

INSERT INTO students(id,name) VALUES(3,'jack'),(4,'allen');

SELECT * FROM students WHERE id < 3;

SELECT * FROM students WHERE gender='m';

SELECT * FROM students WHERE gender IS NULL;

SELECT * FROM students WHERE gender IS NOT NULL;

SELECT * FROM students ORDER BY name DESC LIMIT 2;

SELECT * FROM students ORDER BY name DESC LIMIT 1,2;

SELECT * FROM students WHERE id >=2 and id <=4

SELECT * FROM students WHERE BETWEEN 2 AND 4

SELECT * FROM students WHERE name LIKE 't%'

SELECT * FROM students WHERE name RLIKE '.*[lo].*';

SELECT id stuid,name as stuname FROM students

练习

练习数据库下载链接:https://pan.baidu.com/s/11Qk9yI9lx6oZVCGXhvQ6PQ

下载其中的hellodb_innodb.sql,输命令mysql < hellodb_innodb.sql生成一个hellodb数据库:

[[email protected] ~]#mysql  #连接mariadb

MariaDB [(none)]> use hellodb  #使用hellodb数据库

MariaDB [hellodb]> show tables;  #共有7张表

+-------------------+

| Tables_in_hellodb |

+-------------------+

| classes           |

| coc               |

| courses           |

| scores            |

| students          |

| teachers          |

| toc               |

+-------------------+

MariaDB [hellodb]> select * from students;  #学生表

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     1 | Shi Zhongyu   |  22 | M      |       2 |         3 |

|     2 | Shi Potian    |  22 | M      |       1 |         7 |

|     3 | Xie Yanke     |  53 | M      |       2 |        16 |

|     4 | Ding Dian     |  32 | M      |       4 |         4 |

|     5 | Yu Yutong     |  26 | M      |       3 |         1 |

|     6 | Shi Qing      |  46 | M      |       5 |      NULL |

|     7 | Xi Ren        |  19 | F      |       3 |      NULL |

|     8 | Lin Daiyu     |  17 | F      |       7 |      NULL |

|     9 | Ren Yingying  |  20 | F      |       6 |      NULL |

|    10 | Yue Lingshan  |  19 | F      |       3 |      NULL |

|    11 | Yuan Chengzhi |  23 | M      |       6 |      NULL |

|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL |

|    13 | Tian Boguang  |  33 | M      |       2 |      NULL |

|    14 | Lu Wushuang   |  17 | F      |       3 |      NULL |

|    15 | Duan Yu       |  19 | M      |       4 |      NULL |

|    16 | Xu Zhu        |  21 | M      |       1 |      NULL |

|    17 | Lin Chong     |  25 | M      |       4 |      NULL |

|    18 | Hua Rong      |  23 | M      |       7 |      NULL |

|    19 | Xue Baochai   |  18 | F      |       6 |      NULL |

|    20 | Diao Chan     |  19 | F      |       7 |      NULL |

|    21 | Huang Yueying |  22 | F      |       6 |      NULL |

|    22 | Xiao Qiao     |  20 | F      |       1 |      NULL |

|    23 | Ma Chao       |  23 | M      |       4 |      NULL |

|    24 | Xu Xian       |  27 | M      |    NULL |      NULL |

|    25 | Sun Dasheng   | 100 | M      |    NULL |      NULL |

+-------+---------------+-----+--------+---------+-----------+

MariaDB [hellodb]> select * from teachers;  #老师表

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | Miejue Shitai |  77 | F      |

|   4 | Lin Chaoying  |  93 | F      |

+-----+---------------+-----+--------+

MariaDB [hellodb]> select * from classes;  #班级表

+---------+----------------+----------+

| ClassID | Class          | NumOfStu |

+---------+----------------+----------+

|       1 | Shaolin Pai    |       10 |

|       2 | Emei Pai       |        7 |

|       3 | QingCheng Pai  |       11 |

|       4 | Wudang Pai     |       12 |

|       5 | Riyue Shenjiao |       31 |

|       6 | Lianshan Pai   |       27 |

|       7 | Ming Jiao      |       27 |

|       8 | Xiaoyao Pai    |       15 |

+---------+----------------+----------+

MariaDB [hellodb]> select * from courses;  #课程表

+----------+----------------+

| CourseID | Course         |

+----------+----------------+

|        1 | Hamo Gong      |

|        2 | Kuihua Baodian |

|        3 | Jinshe Jianfa  |

|        4 | Taiji Quan     |

|        5 | Daiyu Zanghua  |

|        6 | Weituo Zhang   |

|        7 | Dagou Bangfa   |

+----------+----------------+

MariaDB [hellodb]> select * from coc;  #班级选课表

+----+---------+----------+

| ID | ClassID | CourseID |

+----+---------+----------+

|  1 |       1 |        2 |

|  2 |       1 |        5 |

|  3 |       2 |        2 |

|  4 |       2 |        6 |

|  5 |       3 |        1 |

|  6 |       3 |        7 |

|  7 |       4 |        5 |

|  8 |       4 |        2 |

|  9 |       5 |        1 |

| 10 |       5 |        9 |

| 11 |       6 |        3 |

| 12 |       6 |        4 |

| 13 |       7 |        4 |

| 14 |       7 |        3 |

+----+---------+----------+

MariaDB [hellodb]> select * from scores;  #分数表

+----+-------+----------+-------+

| ID | StuID | CourseID | Score |

+----+-------+----------+-------+

|  1 |     1 |        2 |    77 |

|  2 |     1 |        6 |    93 |

|  3 |     2 |        2 |    47 |

|  4 |     2 |        5 |    97 |

|  5 |     3 |        2 |    88 |

|  6 |     3 |        6 |    75 |

|  7 |     4 |        5 |    71 |

|  8 |     4 |        2 |    89 |

|  9 |     5 |        1 |    39 |

| 10 |     5 |        7 |    63 |

| 11 |     6 |        1 |    96 |

| 12 |     7 |        1 |    86 |

| 13 |     7 |        7 |    83 |

| 14 |     8 |        4 |    57 |

| 15 |     8 |        3 |    93 |

+----+-------+----------+-------+

MariaDB [hellodb]> select * from toc;  #空表

Empty set (0.04 sec)

以下是练习题:

(1) 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄

MariaDB [hellodb]> SELECT name,age FROM students WHERE age>25 AND gender='M';

+--------------+-----+

| name         | age |

+--------------+-----+

| Xie Yanke    |  53 |

| Ding Dian    |  32 |

| Yu Yutong    |  26 |

| Shi Qing     |  46 |

| Tian Boguang |  33 |

| Xu Xian      |  27 |

| Sun Dasheng  | 100 |

+--------------+-----+

(2) 以ClassID为分组依据,显示每组的平均年龄

MariaDB [hellodb]> SELECT classid,avg(age) FROM students GROUP BY classid;

+---------+----------+

| classid | avg(age) |

+---------+----------+

|    NULL |  63.5000 |

|       1 |  20.5000 |

|       2 |  36.0000 |

|       3 |  20.2500 |

|       4 |  24.7500 |

|       5 |  46.0000 |

|       6 |  20.7500 |

|       7 |  19.6667 |

+---------+----------+

(3) 显示第2题中平均年龄大于30的分组及平均年龄

MariaDB [hellodb]> SELECT classid,avg(age) FROM students GROUP BY classid HAVING avg(age)>30;

+---------+----------+

| classid | avg(age) |

+---------+----------+

|    NULL |  63.5000 |

|       2 |  36.0000 |

|       5 |  46.0000 |

+---------+----------+

(4) 显示以L开头的名字的同学的信息

MariaDB [hellodb]> SELECT * FROM students WHERE name like 'L%';

MariaDB [hellodb]> SELECT * FROM students WHERE name like 'L%';

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name        | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|     8 | Lin Daiyu   |  17 | F      |       7 |      NULL |

|    14 | Lu Wushuang |  17 | F      |       3 |      NULL |

|    17 | Lin Chong   |  25 | M      |       4 |      NULL |

+-------+-------------+-----+--------+---------+-----------+

(5) 显示TeacherID非空的同学的相关信息

MariaDB [hellodb]> SELECT * FROM students WHERE teacherid is not null;

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name        | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|     1 | Shi Zhongyu |  22 | M      |       2 |         3 |

|     2 | Shi Potian  |  22 | M      |       1 |         7 |

|     3 | Xie Yanke   |  53 | M      |       2 |        16 |

|     4 | Ding Dian   |  32 | M      |       4 |         4 |

|     5 | Yu Yutong   |  26 | M      |       3 |         1 |

+-------+-------------+-----+--------+---------+-----------+

(6) 以年龄排序后,显示年龄最大的前10位同学的信息

MariaDB [hellodb]> SELECT * FROM students ORDER BY -age LIMIT 10;

+-------+--------------+-----+--------+---------+-----------+

| StuID | Name         | Age | Gender | ClassID | TeacherID |

+-------+--------------+-----+--------+---------+-----------+

|    25 | Sun Dasheng  | 100 | M      |    NULL |      NULL |

|     3 | Xie Yanke    |  53 | M      |       2 |        16 |

|     6 | Shi Qing     |  46 | M      |       5 |      NULL |

|    13 | Tian Boguang |  33 | M      |       2 |      NULL |

|     4 | Ding Dian    |  32 | M      |       4 |         4 |

|    24 | Xu Xian      |  27 | M      |    NULL |      NULL |

|     5 | Yu Yutong    |  26 | M      |       3 |         1 |

|    17 | Lin Chong    |  25 | M      |       4 |      NULL |

|    23 | Ma Chao      |  23 | M      |       4 |      NULL |

|    18 | Hua Rong     |  23 | M      |       7 |      NULL |

+-------+--------------+-----+--------+---------+-----------+

(7) 查询年龄大于等于20岁,小于等于25岁的同学的信息

MariaDB [hellodb]> SELECT * FROM students WHERE age >=20 and age <=25;

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     1 | Shi Zhongyu   |  22 | M      |       2 |         3 |

|     2 | Shi Potian    |  22 | M      |       1 |         7 |

|     9 | Ren Yingying  |  20 | F      |       6 |      NULL |

|    11 | Yuan Chengzhi |  23 | M      |       6 |      NULL |

|    16 | Xu Zhu        |  21 | M      |       1 |      NULL |

|    17 | Lin Chong     |  25 | M      |       4 |      NULL |

|    18 | Hua Rong      |  23 | M      |       7 |      NULL |

|    21 | Huang Yueying |  22 | F      |       6 |      NULL |

|    22 | Xiao Qiao     |  20 | F      |       1 |      NULL |

|    23 | Ma Chao       |  23 | M      |       4 |      NULL |

+-------+---------------+-----+--------+---------+-----------+

SQL JOINS

表连接图示

多表查询

交叉连接:笛卡尔乘积

内连接:

等值连接:让表之间的字段以“等值”建立连接关系;

不等值连接

自然连接:去掉重复列的等值连接

自连接

外连接:

左外连接:

FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col

右外连接

FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col

#要求掌握内连接,左外连接,右外连接

示例:

由于输出结果太长,就不贴上来了,感兴趣的可以试试体会一下

#内连接INNER JOIN

MariaDB [hellodb]> select s.name as studentname,t.name as teachername from teachers as t inner join students as s on s.teacherid=t.tid;

#交叉连接,笛卡尔乘积CROSS JOIN

MariaDB [hellodb]> select * from students cross join teachers;

#左外连接LEFT OUTER JOIN

MariaDB [hellodb]> select s.name as studentname,t.name as teachername from students as s left outer join teachers as t on s.teacherid=t.tid;

#对调过来左外连接

MariaDB [hellodb]> select s.name as studentname,t.name as teachername from teachers as t right outer join students as s on s.teacherid=t.tid;

#右外连接

MariaDB [hellodb]> select s.name as studentname,t.name as teachername from students as s right outer join teachers as t on s.teacherid=t.tid;

#左外连接去除交集

MariaDB [hellodb]> select s.name as studentname,t.name as teachername from students as s left outer join teachers as t on s.teacherid=t.tid and t.name is null;

#因MySQL不支持FULL OUTER JOIN,这里用UNION联合查询

MariaDB [hellodb]> select stuid,name from students union select tid,name from teachers;

#完全外连接,左外连接union右外连接即可

MariaDB [hellodb]> select s.name as studentname,t.name as teachername from students as s left outer join teachers as t on s.teacherid=t.tid UNION select s.name as studentname,t.name as teachername from students as s right outer join teachers as t on s.teacherid=t.tid;

#完全外连接去除交集

MariaDB [hellodb]> SELECT * FROM (select s.name as studentname,t.name as teachername from students as s left outer join teachers as t on s.teacherid=t.tid UNION select s.name as studentname,t.name as teachername from students as s right outer join teachers as t on s.teacherid=t.tid) as aWHERE studentname is null or teachername is null;

#自内连接

MariaDB [hellodb]> select s1.name as emp, s2.name as leader from students as s1 inner join students as s2 on s1.teacherid=s2.stuid;

#自左外连接

MariaDB [hellodb]> select s1.name as emp, s2.name as leader from students as s1 left outer join students as s2 on s1.teacherid=s2.stuid;

多表查询

子查询:在查询语句嵌套着查询语句,性能较差

基于某语句的查询结果再次进行的查询

例:MariaDB [hellodb]> select st.name,sc.score from students as st inner join scores as sc on st.stuid=sc.stuid and score > ( select avg(score) from scores); #成绩大于平均成绩的学生的姓名和分数

用在WHERE子句中的子查询:

用于比较表达式中的子查询;子查询仅能返回单个值

SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM students);

用于IN中的子查询:子查询应该单键查询并返回一个或多个值从构成列表

SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);

用于EXISTS

多表查询

用于FROM子句中的子查询

使用格式:SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;

示例:

SELECT s.aage,s.ClassID FROM (SELECT avg(Age) AS aage,ClassID FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;

联合查询:UNION

SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;

#联合查询的字段数和字段类型必须一致

SELECT语句执行流程

练习

导入hellodb_innodb.sql,以下操作在students表上执行

1、以ClassID分组,显示每班的同学的人数

MariaDB [hellodb]> SELECT classid,count(stuid) FROM students GROUP BY classid;

+---------+--------------+

| classid | count(stuid) |

+---------+--------------+

|    NULL |            2 |

|       1 |            4 |

|       2 |            3 |

|       3 |            4 |

|       4 |            4 |

|       5 |            1 |

|       6 |            4 |

|       7 |            3 |

+---------+--------------+

2、以Gender分组,显示其年龄之和

MariaDB [hellodb]> SELECT gender,sum(age) FROM students GROUP BY gender;

+--------+----------+

| gender | sum(age) |

+--------+----------+

| F      |      190 |

| M      |      495 |

+--------+----------+

3、以ClassID分组,显示其平均年龄大于25的班级

MariaDB [hellodb]> SELECT classid,sum(age) FROM students GROUP BY classid HAVING avg(age)>25;

+---------+----------+

| classid | sum(age) |

+---------+----------+

|    NULL |      127 |

|       2 |      108 |

|       5 |       46 |

+---------+----------+

4、以Gender分组,显示各组中年龄大于25的学员的年龄之和

MariaDB [hellodb]> SELECT gender,sum(age) FROM students WHERE age>25 GROUP BY gender;

+--------+----------+

| gender | sum(age) |

+--------+----------+

| M      |      317 |

+--------+----------+

5、显示前5位同学的姓名、课程及成绩

MariaDB [hellodb]> SELECT st.name,co.course,sc.score FROM (SELECT * FROM students WHERE stuid <=5) st INNER JOIN courses co INNER JOIN scores sc ON st.stuid=sc.stuid AND sc.courseid=co.courseid;

+-------------+----------------+-------+

| Name        | course         | score |

+-------------+----------------+-------+

| Shi Zhongyu | Kuihua Baodian |    77 |

| Shi Zhongyu | Weituo Zhang   |    93 |

| Shi Potian  | Kuihua Baodian |    47 |

| Shi Potian  | Daiyu Zanghua  |    97 |

| Xie Yanke   | Kuihua Baodian |    88 |

| Xie Yanke   | Weituo Zhang   |    75 |

| Ding Dian   | Daiyu Zanghua  |    71 |

| Ding Dian   | Kuihua Baodian |    89 |

| Yu Yutong   | Hamo Gong      |    39 |

| Yu Yutong   | Dagou Bangfa   |    63 |

+-------------+----------------+-------+

6、显示其成绩高于80的同学的名称及课程;

MariaDB [hellodb]> SELECT st.name,co.course FROM students st INNER JOIN scores sc INNER JOIN courses co ON st.stuid=sc.stuid AND sc.courseid=co.courseid AND sc.score>80;

+-------------+----------------+

| name        | course         |

+-------------+----------------+

| Shi Zhongyu | Weituo Zhang   |

| Shi Potian  | Daiyu Zanghua  |

| Xie Yanke   | Kuihua Baodian |

| Ding Dian   | Kuihua Baodian |

| Shi Qing    | Hamo Gong      |

| Xi Ren      | Hamo Gong      |

| Xi Ren      | Dagou Bangfa   |

| Lin Daiyu   | Jinshe Jianfa  |

+-------------+----------------+

7、求前8位同学每位同学自己两门课的平均成绩,并按降序排列

MariaDB [hellodb]> SELECT st.name,avg(sc.score) as avg_score FROM students st INNER JOIN scores sc ON st.stuid=sc.stuid GROUP BY name ORDER BY avg_score desc;

+-------------+-----------+

| name        | avg_score |

+-------------+-----------+

| Shi Qing    |   96.0000 |

| Shi Zhongyu |   85.0000 |

| Xi Ren      |   84.5000 |

| Xie Yanke   |   81.5000 |

| Ding Dian   |   80.0000 |

| Lin Daiyu   |   75.0000 |

| Shi Potian  |   72.0000 |

| Yu Yutong   |   51.0000 |

+-------------+-----------+

8、显示每门课程课程名称及学习了这门课的同学的个数

MariaDB [hellodb]> SELECT co.course,count(stuid) FROM students st INNER JOIN courses co INNER JOIN coc ON st.classid=coc.classid AND coc.courseid=co.courseid GROUP BY co.course;

+----------------+--------------+

| course         | count(stuid) |

+----------------+--------------+

| Dagou Bangfa   |            4 |

| Daiyu Zanghua  |            8 |

| Hamo Gong      |            5 |

| Jinshe Jianfa  |            7 |

| Kuihua Baodian |           11 |

| Taiji Quan     |            7 |

| Weituo Zhang   |            3 |

+----------------+--------------+

9、如何显示其年龄大于平均年龄的同学的名字

MariaDB [hellodb]> SELECT name FROM students WHERE age>(SELECT avg(age) FROM students);

+--------------+

| name         |

+--------------+

| Xie Yanke    |

| Ding Dian    |

| Shi Qing     |

| Tian Boguang |

| Sun Dasheng  |

+--------------+

10、如何显示其学习的课程为第1、2,4或第7门课的同学的名字

MariaDB [hellodb]> SELECT s.name FROM students AS s INNER JOIN (SELECT * FROM coc WHERE courseid IN (1,2,4,7)) AS co ON s.classid=co.classid GROUP BY s.name;

+---------------+

| name          |

+---------------+

| Diao Chan     |

| Ding Dian     |

| Duan Yu       |

| Hua Rong      |

| Huang Yueying |

| Lin Chong     |

| Lin Daiyu     |

| Lu Wushuang   |

| Ma Chao       |

| Ren Yingying  |

| Shi Potian    |

| Shi Qing      |

| Shi Zhongyu   |

| Tian Boguang  |

| Wen Qingqing  |

| Xi Ren        |

| Xiao Qiao     |

| Xie Yanke     |

| Xu Zhu        |

| Xue Baochai   |

| Yu Yutong     |

| Yuan Chengzhi |

| Yue Lingshan  |

+---------------+

23 rows in set (0.01 sec)

11、如何显示其成员数最少为3个的班级的同学中年龄大于同班同学平均年龄的同学

MariaDB [hellodb]> SELECT s.name,s.age,s.classid FROM students s INNER JOIN (SELECT avg(age) as avg_age,classid FROM students GROUP BY classid HAVING count(stuid)>=3) AS a ON s.classid=a.classid WHERE age>avg_age;

+---------------+-----+---------+

| name          | age | classid |

+---------------+-----+---------+

| Shi Potian    |  22 |       1 |

| Xie Yanke     |  53 |       2 |

| Ding Dian     |  32 |       4 |

| Yu Yutong     |  26 |       3 |

| Yuan Chengzhi |  23 |       6 |

| Xu Zhu        |  21 |       1 |

| Lin Chong     |  25 |       4 |

| Hua Rong      |  23 |       7 |

| Huang Yueying |  22 |       6 |

+---------------+-----+---------+

12、统计各班级中年龄大于全校同学平均年龄的同学

MariaDB [hellodb]> SELECT name,age,classid FROM students WHERE age >(SELECT avg(age) FROM students);

+--------------+-----+---------+

| name         | age | classid |

+--------------+-----+---------+

| Xie Yanke    |  53 |       2 |

| Ding Dian    |  32 |       4 |

| Shi Qing     |  46 |       5 |

| Tian Boguang |  33 |       2 |

| Sun Dasheng  | 100 |    NULL |

+--------------+-----+---------+

视图

视图:VIEW,虚表,保存有实表的查询结果

创建方法:

CREATE VIEW view_name [(column_list)]

AS select_statement

[WITH [CASCADED | LOCAL] CHECK OPTION]

查看视图定义:SHOW CREATE VIEW view_name

删除视图:

DROP VIEW [IF EXISTS]

view_name [, view_name] ...

[RESTRICT | CASCADE]

视图中的数据事实上存储于“基表”中,因此,其修改操作也会针对基表实现;其修改操作受基表限制

视图是虚拟的,相当于一个别名

物化视图:把视图生成为一个实体表,MySQL不支持,某些别的数据库支持

原文地址:http://blog.51cto.com/13695854/2134412

时间: 2024-11-06 09:44:03

SQL语句简介及练习的相关文章

SQLite数据库简介以及通过sql语句进行增删改查

本次内容主要讲解Android开发过程中,如何利用sql语句进行SQLite数据库的操作. 一.SQLite数据库的介绍 Android系统集成了一个轻量级的嵌入式数据库--->SQLite,SQLite并不像Mysql.SQLserver.Oracle那样专业的数据库.SQLite数据库只是一个嵌入式的数据库引擎,专门适用于资源有限的设备上,SQLite可以存储多达2T的数据量. 二.SQLite的操作 SQLite的操作方式,从本质上来看,只是一种更为便捷的文件操作.创建一个SQLite数据

LINQ to SQL语句Concat/Union/Intersect/Except--2017年2月22日

Concat/Union/Intersect/Except操作 适用场景:对两个集合的处理,例如追加.合并.取相同项.相交项等等. Concat(连接) 说明:连接不同的集合,不会自动过滤相同项:延迟. 1.简单形式: var q = ( from c in db.Customers select c.Phone ).Concat( from c in db.Customers select c.Fax ).Concat( from e in db.Employees select e.Home

[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)

原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下) ——通过知识共享树立个人品牌. 继上六篇: [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程之四:把游标说透(

SQL语句的用法

SQL语句的用法 SQL 简介 SELECT DISTINCT WHERE AND OR IN 函数 INCLUDE HAVING 简介 SQL语句教程 SELECT SELECT "列名" FROM "表格名"; 列名可以为多个,该选中的列显示出来 DISTINCT SELECT DISTINCT "列名" FROM "表格名"; 只显示不同的值,重复值不显示,如果有多个列,则每一个列的值都相同时视作相同.如下表,执行sel

Mybatis使用之动态SQL语句

Mybatis使用之动态SQL语句 一:简介 Mybatis动态SQL语句可帮助我们根据需要动态拼接SQL语句.主要在配置文件中使用<where> <if><choose><when><otherwise> <set> <trim><foreach>标签来实现. 二:具体使用方式 2.1 where 2.1.1 功能 语句的作用主要是简化SQL语句中where中的条件判断,where元素的作用是会在写入wher

oracle sql语句中使用if逻辑

l在 SQL 语句中使用IF-THEN-ELSE 逻辑 l l使用两种方法: •CASE 表达式:SQL99的语法,类似Basic,比较繁琐 •DECODE 函数:Oracle自己的语法,类似Java,比较简介 1 SQL> select ename,job, sal, case job when 'PRESIDENT' then 1.1*sal 2 2 when 'MANAGER' then 1.2*sal 3 3 when 'CLERK' then 1.3*sal 4 4 else 1.4*

《万能数据库查询分析器》实现使用SQL语句直接高效地访问文本文件

<万能数据库查询分析器>实现使用SQL语句直接高效地访问文本文件 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 摘要    用SQL语句来直接访问文本文件?是在做梦吗? 本文详细地介绍了"万能数据库查询分析器",中文版本<DB 查询分析器>.英文版本<DB Query Analyzer>在 文本文件处理方面非常强大的功能,你可以直接用SQL语句来访问这些文本文件,访问250万条记录的文件的复杂的关联操作,也不过用时59秒钟.需要注意

数据库技能实战进阶之常用结构化sql语句(上)

常用的结构化查询语言主要分为数据定义语言(DDL).数据操作语言(DML).数据控制语言(DCL)和数据查询语言(DQL).特别在关系型的数据库例如(mysql.mariadb. percona.DB2.Oracle.SQL server)等都是采用共同的SQL语句来实现增删改查等数据的管理.本文会针对以下的四种类型的结构化SQL来进行介绍. DDL 数据定义语言  create     drop     alter DML 数据操作语言  insert    delete   update D

夜黑风高的夜晚用SQL语句做了一些想做的事&#183;&#183;&#183;&#183;&#183;&#183;&#183;

     IT这条漫漫长路注定是孤独的,陪伴我们的只有那些不知冷暖的代码语句和被手指敲打的磨掉了键上的标识的键盘. 之所以可以继续坚持下去,是因为心中有一份永不熄灭的激情. 成功的路上让我们为自己带盐~~~~     想知道SQL语句的强大功能就先让我给你讲讲什么是SQL吧 SQL简介:        SQL能做什么?            专业人士说:在进行数据管理时,如果每次创建数据库,表或者从数据库中读取数据,都需要手动在SQL Server Management  Studio  中进行