MySql数据库基本指令:
SQL约束(重点):
非NULL约束:
mysql> create table product(
-> id int,
-> name varchar(10),
-> p_id int not null 指定非空约束
-> )character set utf8
-> collate utf8_general_ci;
mysql> insert into product values (1,'food',10001); 插入成功
mysql> insert into product (id,name) values (2,'tool');插入失败,默认值为null,但是有非空约束。
因此在做非空约束的时候一般结合默认值使用。
唯一约束:
以上的代码如果指定了默认值,那么如果连续插入两条不指定产品ID的字段的记录那么会默认导致产品的ID重复。因此需要给该列中继续使用唯一性约束。
mysql> alter table product
-> change column p_id p_id int not null unique default 1002; 指定唯一约束
mysql> insert into product (id,name) values (2,'tool'); 插入成功
已经有了唯一的默认值。
mysql> insert into product (id,name) values (3,'tool'); 插入失败
1002该列的值不唯一了,不满足唯一性约束,所以报错。
主键约束
在以上的程序中发现非空和唯一性约束可以结合使用,而且对于产品的ID这类唯一性必须交重要的列属性而言是需要经常会用到的,那么SQL将以上两个约束使用主键约束可以直接替换。主键不仅代替了非空和唯一性约束而且默认为主键的列为索引的默认列(有了索引开发者在使用程序查询数据的时候会更加高效)。
在实际的项目中我们需要对所有的表数据进行频繁的查询操作,因此SQL有一个不成文的规定每一个表中都应该建立至少一个主键。
mysql> create table stu(
-> id int primary key, --->指定主键约束,效果和(非空和唯一约束一致)。
-> name varchar(10)
-> )character set utf8
-> collate utf8_general_ci;
自动增长
对于一些字段,我们只是用来标记插入的顺序的时候,就需要使用自动增长。
形式如下:
mysql> create table stu (
-> id int primary key auto_increment, --->id自动增长
-> name varchar(20));
外键约束:
举例:如果有教师(teacher)和学生(student)两个表结构,
mysql> create table teacher (主表)
-> ( t_id int primary key,--->主键约束
-> t_name varchar(10) not null, --->非空约束
-> t_salary double default 5000
-> )character set utf8
-> collate utf8_general_ci;
mysql> create table student (从表)
-> ( s_id int primary key, --->主键约束
-> s_name varchar(10) not null, --->非空约束
-> st_id int,
-> foreign key (st_id) references teacher (t_id) --->外键约束
-> )character set utf8
-> collate utf8_general_ci;
以上的表结构如果要添加数据,那么必须先有主表数据再有从表数据,因为从表的数据依赖于主表的数据。
因此一般情况下,如果要使用外键约束,都需要结合级联操作( cascade )一起使用。
给主表添加数据:
mysql> insert into teacher values (1,'lsh',8000);
查看主表数据
mysql> select * from teacher;
+-------+--------+----------+
| t_id | t_name | t_salary |
+-------+--------+----------+
| 1 | lsh | 8000 |
+-------+--------+----------+
给从表添加数据
mysql> insert into student values (1001,'zs',1); --> 添加成功,外键存在
mysql> insert into student values (1002,'ls',2); -->添加失败,外键不存在
级联操作(cascade):
问题:大家试着删除或更新(主表的主键)主表中的数据。
mysql> update teacher set t_id=2;-->修改失败,因为该列被从表引用
mysql> delete from teacher;-->修改失败,因为该列被从表引用
在实际的开发中需要级联的对主表和从表的数据进行删除或更新,因此需要级联的操作。
级联更新:
mysql> create table student(
-> s_id int primary key,
-> s_name varchar(10) not null,
-> st_id int,
-> foreign key (st_id) references teacher (t_id) on update cascade -->级联更新
-> )character set utf8
-> collate utf8_general_ci;
级联删除:
mysql> create table student
-> (
-> s_id int primary key,
-> s_name varchar(10) not null,
-> st_id int,
-> foreign key (st_id) references teacher (t_id) on update cascade on delete cascade) -->级联删除
-> character set utf8
-> collate utf8_general_ci;
删除主表数据
mysql> delete from teacher;
查看从表数据
mysql> select * from student;
Empty set (0.00 sec)
正常情况下应该该删除教师将学生中引用的列设置为null。
on delete set null 在删除 主表数据的时候 将字表中对应的数据设置为null
注意:级联的前提是有主表和从表。
表连接:
交叉查询语句:
mysql> select * from department cross join employee; -->(cross join)
该语句和以上SQL等价但是体现了连接思想。所以在实际的项目使用该语句。
交叉连接是所有的其他的连接的数据的基础。交叉连接的数据的记录数 = 表1*表2;
内连接:
问题:如果在交叉连接的基础上查询出来所有的部门员工。
内连接查询:
mysql> select e.emp_id, e.emp_name,d.dep_name from employee as e inner join
department as d on e.dep_id=d.dep_id; --->-->(inner join.....on....)
左外连接查询:
显示所有的员工信息?
mysql> select e.emp_id, e.emp_name,d.dep_name from employee as e left outer join
department as d on e.dep_id=d.dep_id; --->(left outer join.....on.....)
右外连接:
查看所有的部门信息,哪怕该部门没有员工。
mysql> select e.emp_id, e.emp_name,d.dep_name from employee as e right outer join
department as d on e.dep_id=d.dep_id; --->(right outer join....on...)
全连接:
在MySQL中是用左连接与右连接,通过union来连接实现的。
查看所有的员工和部门信息?
mysql> select e.emp_id, e.emp_name, d.dep_id, d.dep_name from employee as e left outer join
-> department as d on e.dep_id=d.dep_id 左外连接
-> union --> 连接符
-> select e.emp_id, e.emp_name,d.dep_id,d.dep_name from employee as e right outer join department as d on e.dep_id=d.dep_id; ---> 右外连接
存储过程
定义:存储过程主要将业务逻辑在数据库层加以实现,使得web应该用层的压力变小。
缺点:是每一个数据库厂商对存储过程的语法规范不同导致很难移植该业务逻辑。
案例:对于一些比较敏感的领域如金融领域开发者在处理业务逻辑的时候不能使用javabean
在这里为了安全期间,必须使用存储过程进行封装业务逻辑,因为存储过程可以加密。
创建存储过程:
?准备工作
在创建存储过程前,必须修改MySQL的默认的结束符号。
delimiter //
?语法
create procudure 存储过程名(参数列表)
begin
SQL语句;
end //
?体验
1.修改结束符
mysql> delimiter //
2.创建存储过程
mysql> create procedure pro1()
-> begin
-> select count(*) as allusers from user;
-> end//
3.调用存储过程
call 存储过程名(实参)//
mysql> call pro1()//
?带参数的存储过程
在存储过程中有时候需要指定形参,在MySQL中参数不仅有数据类型、变量名还有作用类型。
作用类型:IN OUT INOUT
创建带参的存储
mysql> create procedure pro2(in name varchar(10)) 定义一个输入型参数
-> begin
-> select name;
-> set name='lucy';
-> select name;
-> end//
mysql> set @name='jack';// 定义用户变量
查询用户变量
mysql> set @name='jack';//
查询结果如下
mysql> select @name;//
调用存储过程传递用户变量
mysql> call pro2(@name);//
Out参数:
mysql> create procedure pro3(out name varchar(10))
-> begin
-> select name;
-> set name='lucy';
-> select name;
-> end//
mysql> set @myname='jame';//
mysql> call pro3(@myname)//
+------+
| name |
+------+
| NULL | 因为该参数的返回值的作用类型,只保存业务逻辑的数据。
+------+
+------+
| name |
+------+
| lucy |
+------+
Inout参数:
create procedure proc4(inout name varchar(10))
begin
select name;
set name='lucy';
select name;
end//
?局部变量的定义
declare 变量名 数据类型 指定默认值;
举例:
declare l_int int unsigned default 100;
declare l_numeric number(8,2) default 9.99;
declare l_date date default '2012-08-12';
declare l_datetime datetime default '2012-08-12 23:10:59';
declare l_varchar varchar(20) default 'This is MySQL';
案例:计算1~n的累加和?
分析:该实例中必须要定义一个变量来保存计算的结果?需要学习如何在存储过程体中定义局部变量?
mysql> create procedure getsum(in num int)
-> begin
-> declare sum int default 0;
-> declare i int default 0;
-> while i<=num do
-> set sum=sum+i;
-> set i=i+1;
-> end while;
-> select sum;
-> end//
自己练习:定义一个用户变量来接收计算的结果数据?
创建存储过程:
create procedure getout(out outdate int)
begin
declare i int default 0;
declare sum int default 0;
while i <= 10 do
set sum = sum + i;
set i = i + 1;
end while;
set outdate = sum;
end//
定义变量用于接收结果:
set @sum=0//
调用存储过程:
call getout(@sum)//
查询返回结果:
select @sum//
?在存储过程中使用IF ELSE 语句
语法:
IF 条件 THEN
语句
ELSE
语句
END IF;
注意:条件语句中没有双等号的
举例:
CREATE PROCEDURE p12 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
IF variable1 = 0 THEN
INSERT INTO t VALUES (17);
END IF;
IF parameter1 = 0 THEN
UPDATE t SET s1 = s1 + 1;
ELSE
UPDATE t SET s1 = s1 + 2;
END IF;
END; //
?CASE指令
举例:
CREATE PROCEDURE p13 (IN parameter1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = parameter1 + 1;
CASE variable1
WHEN 0 THEN INSERT INTO t VALUES (17);
WHEN 1 THEN INSERT INTO t VALUES (18);
ELSE INSERT INTO t VALUES (19);
END CASE;
END; //
?Loops 循环语句循环语句循环语句循环语句
LOOP循环是靠标记和LEAVE语句结束的!
举例:
CREATE PROCEDURE p16 ()
BEGIN
DECLARE v INT;
SET v = 0;
loop_label: LOOP 作一个标志
INSERT INTO t VALUES (v);
SET v = v + 1;
IF v >= 5 THEN
LEAVE loop_label; 利用标志结束循环
END IF;
END LOOP;
END; //
? WHILE循环
举例:
CREATE PROCEDURE p14 ()
BEGIN
DECLARE v INT;
SET v = 0;
WHILE v < 5 DO
INSERT INTO t VALUES (v);
SET v = v + 1;
END WHILE;
END; //
?REPEAT 循环
与 do-while相同,他用until结束
举例:
CREATE PROCEDURE p15 ()
BEGIN
DECLARE v INT;
SET v = 0;
REPEAT
INSERT INTO t VALUES (v);
SET v = v + 1;
UNTIL v >= 5
END REPEAT;
END; //
触发器:
问题:如果需要统计一篇文章的字符个数应该使用什么SQL语句?
表:文章(id,title,content) ?
select content from 文章 where id=1
isnert into 文章 content 10000表数据。
触发器的语法:
create trigger 触发器名字 指定执行的时间 on 指定在什么表上执行操作
影响的函数 需要执行的任务或业务
举例:
创建数据表,用于表示文章
create table data(
name varchar(20));
创建数字表,用于表示文章的字数
create table chars(
count int(10));
插入初始化数据:
insert into chars (count) values (0);
创建触发器:
create trigger tr1 指定触发器的名字
after insert 指定当什么时候触发
on data指定当哪个表作操作时触发
for each row指定具体的影响程度(每一行变化都触发)
update chars set count=count+char_length(new.name); 指定触发时,执行的操作
char_length(new.name)函数是获取更新的所有字符的长度。
注意:触发器不要单独的调用。主要发生相应的事件MySQL会自动调用。