本篇博客讲解MySQL一些基本的插入删除更新语句,以及讲解内外左右连接。
delete:删除语句,会删除满足条件的记录或者表
/*delete:删除语句,where指定删除对象,会把所有满足的记录全部删除*/
DELETE FROM instructor
WHERE dept_name='Finance';
/*常见的两个表之间进行删除*/
DELETE FROM instructor
WHERE dept_name IN
(SELECT dept_name
FROM department
WHERE building ='Watson');
insert:插入操作。
/*插入操作,如果不表明插入元素,默认按表元素排列*/
INSERT INTO course
VALUES('CS-437','Database Systems','Comp. Sci.',4);
/*将表A的结果插入到表B中,注意select的元素的类型和数目要一致,不然会报错*/
INSERT INTO instructor
SELECT ID,NAME,dept_name,18000 -- 最后一个18000是工资
FROM student
WHERE dept_name='Physics' AND tot_cred > 10; -- 选取物理系学分大于10的学生
update:更新操作。
/*更新操作,即该表原有表中的记录*/
UPDATE instructor
SET salary = salary * 1.05; -- 这里set是赋值符号,表示将原工资乘与1.05
inner join:内连接,outer join:外连接。先来说一下什么是内连接和外连接。两个表进行连接,会存在某个表的主键不在另外一个表出现的情况。比如学生表和选课表,会出现有的学生没有选到课的情况,如果我们将两个表连接起来,会出现有的学生无法与选课表中记录匹配,那对于那些没有选课的同学怎么办呢?对于内连接会直接无视,即不会放入结果表中;但如果是外连接,虽然有的学生没有修课程,但是我们也可以加入到结果表中,令他们修的课程信息值为null就可以了。总结一下,内连接的表不允许空值,而外连接则允许。
/*只用内连接inner join连接takes和student表*/
SELECT *
FROM student JOIN takes ON student.ID = takes.ID -- on后面加连接条件
/*查询出所有学生的选课情况,包括没有选课的学生,使用左外连接
左外连接就是左边不允许空值,右表可以空值*/
SELECT *
FROM student LEFT OUTER JOIN takes ON student.ID=takes.ID;
上面介绍了左外连接,右外连接同理。那么存在左右外连接吗?是真实存在的,只不过我们不叫左右外连接,而是叫全外连接。MySQL不支持全外连接的语句:full outer join,但是全外连接不就是左外连接合并右外连接嘛,只需一个union就可以搞定了。
SELECT *
FROM (SELECT id,NAME -- select的键必须与下面union的一致
FROM student
WHERE dept_name='Comp. Sci.')
AS Cstudent1 (id , NAME)
LEFT OUTER JOIN
(SELECT id
FROM takes
WHERE semester='Spring' AND YEAR=2009)
AS Cspring1 (id)
ON Cstudent1.id= Cspring1.id
UNION
SELECT *
FROM (SELECT id,NAME
FROM student
WHERE dept_name='Comp. Sci.')
AS Cstudent2 (id , NAME)
RIGHT OUTER JOIN
(SELECT id
FROM takes
WHERE semester='Spring' AND YEAR=2009)
AS Cspring2 (id)
ON Cstudent2.id= Cspring2.id;
讲完了内外连接,接下来我们说一下视图,存储过程,函数和触发器,内容会比较多,但是很实用!view:视图。视图作用相当于建立了一张固定的表,平时我们会在查询中建立一些临时表,一旦查询结束,临时表就会被系统删除。而视图建立后,我们随时都能使用。
/*通过view语句来建立一个视图faculty*/
CREATE VIEW faculty AS
SELECT ID,NAME,dept_name
FROM instructor;
/*建立一个2009年秋季物理课的视图*/
CREATE VIEW physics_fall_2009
AS
SELECT course.course_id,sec_id,building,room_number
FROM course,section
WHERE course.course_id = section.course_id
AND course.dept_name='Physics'
AND section.semester='Fall' AND section.year='2009';
/*对physics_fall_2009视图进行查询,其实视图在查询时跟普通表没什么区别*/
SELECT course_id
FROM physics_fall_2009
WHERE building='Watson';
faculty视图如下所示:
/*在视图的基础上又建立一个视图,禁止套娃!*/
CREATE VIEW physics_fall_2009_Waston
AS
SELECT course_id,room_number
FROM physics_fall_2009
WHERE building='Watson';
上述我们仅仅是对新建立的视图进行查询,那视图可以支持插入和删除操作吗?其实是可以的,但是有局限,那就是该视图必须来自一个表,同时我们进行投影操作建立的视图,其余没有投影的键必须允许为空。
/*这个faculty视图由于只是进行了简单的进行了单表投影选择操作,因此可以支持插入*/
INSERT INTO faculty
VALUES('30765','Green','Music');
/*这里演示了多表查询之下创立的视图不能插入,我估计原因是视图表面上用起来是一个表
其实系统并非实际建了这个视图表,而是通过索引来连接视图和原表,由于该视图涉及到两个表
因此无法插入*/
create view instructor_info
as
select ID, name, building
from instructor, department
where instructor.dept_name = department.dept_name;
-- 插入记录:
insert into instructor_info
values ('69987','White','Taylor');
报错信息如上。这也很好理解为什么报错,该视图是由多个表拼凑起来的,那如果要插入,怎么将插入的数据分配回原来的表呢?视图我们可以看出是一个索引表,而并不是一张真正的表。
视图中还会出现一种情况:比如某个视图展示历史系老师的信息,该视图从instructor表中建立的,当我往该视图中插入一条音乐老师的信息,虽然我们刷新视图发现没有记录,但是查看instructor发现该记录是真是插入的。
/*创建一个历史系老师*/
CREATE VIEW history_instructors
AS
SELECT *
FROM instructor
WHERE dept_name= 'History';
-- 插入一条不是History老师的记录,视图中是不会查询到的,但是instructor表会保存
INSERT INTO history_instructors
VALUES ('25566','Brown','Biology',100000)
-- 这里就可以插入并且能查询到了,因为视图会查询到dept_name= 'History'的老师
INSERT INTO history_instructors
VALUES ('68583','Califieri','History',100000);
-- 然后对视图进行查询
SELECT * FROM history_instructors; -- 会发现没有新插入的记录
with check option:在插入时检测是否符合视图的定义。
-- 使用with check option重建一下视图
CREATE VIEW history_instructors AS
SELECT *
FROM instructor
WHERE dept_name= 'History'
WITH CHECK OPTION;
-- 插入Biology老师的记录,此时会报错,原因是我们的系不是历史系
INSERT INTO history_instructors
VALUES ('25566','Brown','Biology',100000)
/*定义视图时加上了 WITH CHECK OPTION 子句,对该视图进行插入、
修改和删除操作时,RDBMS 会自动加上 dept_name= ’History’的条件。*/
报错如图所示:
先来介绍一下表的一些数据类型
MySQL支持所有标准SQL数值数据类型。
这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。
关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。
BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。
作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。
日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。
TIMESTAMP类型有专有的自动更新特性
字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。
接下来介绍一下建表的一些操作,not null:非空约束,就是不允许为空值
/*非空约束*/
CREATE TABLE instructor
(ID VARCHAR(5), NAME VARCHAR(20) NOT NULL, /*非空约束*/
dept_name VARCHAR(20),
salary NUMERIC(8,2) CHECK (salary > 29000),
PRIMARY KEY (ID),
FOREIGN KEY (dept_name) REFERENCES department ON DELETE SET NULL
);
unique:唯一,特别适合一些主键
/*unique使得name必须唯一*/
CREATE TABLE instructor
(ID VARCHAR(5),
NAME VARCHAR(20) UNIQUE, /*unique 约束*/
dept_name VARCHAR(20),
salary NUMERIC(8,2) CHECK (salary > 29000),
PRIMARY KEY (ID), FOREIGN KEY (dept_name) REFERENCES department ON DELETE SET NULL
);
check:系统会检查并限定填入的数据,之前我们也是用check限制视图的插入。
/*使用check来限定填入的数据*/
CREATE TABLE section
(course_id VARCHAR(8)
, sec_id VARCHAR(8),
semester VARCHAR(6) CHECK (semester IN ('Fall', 'Winter', 'Spring', 'Summer')),
YEAR NUMERIC(4,0) CHECK (YEAR > 1701 AND YEAR < 2100),
building VARCHAR(15),
room_number VARCHAR(7),
time_slot_id VARCHAR(4),
PRIMARY KEY (course_id, sec_id, semester, YEAR)
);
on delete set null:当某个表的记录被删除,该记录为外键的其他表记录设为空值。听着很拗口,举个例子大家就懂了。
-- 可自行在在 department 表中执行 delete 操作,违约后,course 表中相对应元组的
-- det_name 设为空值;
create table course
(course_id varchar(8),
title varchar(50),
dept_name varchar(20),
credits numeric(2,0) check (credits > 0),
primary key (course_id), -- 设置主键
foreign key (dept_name) references department on delete set null
);
on delete cascade:联级删除。
-- 级联删除 on delete cascade
create table course
(course_id varchar(8),
title varchar(50),
dept_name varchar(20),
credits numeric(2,0) check (credits > 0),
primary key (course_id),
foreign key (dept_name) references department on delete cascade
);
-- 可在 department 表中执行 delete 操作,违约后,course 表中相对应元组也被自动删除
create user:创建用户。
/*在本机上创建 s1 用户,但是由于SQLyog版本问题,会无法登录*/
CREATE USER 's1'@'localhost' IDENTIFIED BY 's1';
-- 更换了IDENTIFIED WITH mysql_native_password BY语句,这样就可以登录了
CREATE USER 's1'@'localhost' IDENTIFIED WITH mysql_native_password BY '123';
-- 刷新权限
FLUSH privilege;
grant:赋予权限。
/*将university的department表查询授权给s1用户,其他修改或者删除操作均没有授予*/
GRANT SELECT ON university.department TO 's1'@'localhost'; -- 后面的@localhost表示主机登录才有该权限
/*将university的department表的budget行的更新权限给s1用户 */
GRANT UPDATE(budget) ON university.department TO 's1'@'localhost';
/*查看s1用户的权限*/
SHOW GRANTS FOR s1@localhost;
drop user:删除用户。
/*删除用户*/
DROP USER 's1'@'localhost';
set password for:给用户设置或修改密码。
/*修改用户密码*/
SET PASSWORD FOR '用户名'@'主机' = PASSWORD('新密码');
/*查询root用户的信息,用户的信息都在USER表中,要想访问得有select权限*/
SELECT HOST,USER
FROM USER
WHERE USER='root';
create role:创建角色。角色我认为相当于一个权限的模板,比如我创建一个角色,给角色赋予某些数据库中某些表的权限,只要我把用户加入到该角色中,就拥有了该用户的权限,有点类似Linux的组用户的权限。
/*-创建角色*/
CREATE role instructor;
/*为角色授权*/
GRANT SELECT ON university.takes TO instructor;
/*将 s1 加入到 instructor 中,s1 就拥有了该角色的权限*/
GRANT instructor TO 's1'@'localhost';