数据约束主要是给表添加约束,以此来约束用户的行为。 约束主要有 1. 默认值约束; 2. 非空约束; 3. 唯一约束; 4. 主键约束; 5. 自增长约束; 6. 外键约束; 下面分别进行说明。 MySQL的注释方式是 “– “,即两个-,再加一个空格; 1.默认值约束,关键字是DEFAULT: 首先创建一个数据库:
CREATE DATABASE testdb;使用这个数据库
USE testdb;默认值(default)
CREATE TABLE student( id INT, NAME VARCHAR(20), gender VARCHAR(4) DEFAULT '男' );这样,在数据库中插入一条数据,如果gender没有插入数据,会进行默认设置,如果设置的值为null,则该条数据的值为null;
INSERT INTO student(id,NAME) VALUES(1,'kite');2.非空约束,关键字为 NOT NULL; 这里把上次创建的表删除,重新建立一个student表,同时下面每次创建Student表都是先删除原来的表: DROP TABLE student;
CREATE TABLE student( id INT, NAME VARCHAR(20) NOT NULL, gender VARCHAR(4) );下面这条语句有错误,不能执行: – not INSERT INTO student(NAME,gender) VALUES(NULL,’boy’); 下面这条语句可以执行:
-- ok INSERT INTO student(gender) VALUES('boy');3.唯一约束,关键字是UNIQUE;
-- 唯一约束 CREATE TABLE student( id INT UNIQUE, NAME VARCHAR(20), gender VARCHAR(4) ); -- ok INSERT INTO student(id,NAME,gender) VALUES(1,NULL,'boy'); -- not ok INSERT INTO student(id,NAME,gender) VALUES(1,'tom','boy');4.主键约束,关键字是PRIMARY KEY;
-- 主键约束(primary key)(唯一+非空) CREATE TABLE student( id INT PRIMARY KEY, NAME VARCHAR(20), gender VARCHAR(4) ); -- ok INSERT INTO student(NAME,gender) VALUES(NULL,'boy'); -- not ok 默认为0,必须要实现自增长才可以不写,否则主键都是0,重复了 INSERT INTO student(NAME,gender) VALUES('funny','boy'); -- not ok 主键不能为0 INSERT INTO student(id,NAME,gender) VALUES(NULL,'funny','boy'); -- ok INSERT INTO student(id,NAME,gender) VALUES(1,'tom','boy');5.自增长约束,关键字为AUTO_INCREMENT,一般定义到主键上;
-- 自增长约束(auto_increment) CREATE TABLE student( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), gender VARCHAR(4) ); -- ok INSERT INTO student(NAME,gender) VALUES(NULL,'boy'); -- ok INSERT INTO student(NAME,gender) VALUES('ded','boy');6.外键约束,关键字为FOREIGN KEY; 外键约束: 只有多种表才会有外键,一个表没有外键。 约束两种表的情况,出现外键是因为出现了冗余字段。 例如下面的这个表:一个学生表,有id,name,gender,schoolID,schoolName,schoolAdd这几个列,从这个表中可以看出,Student表只需要关联schoolID这个字段就可以了,因为通过这个字段可以找到学校的名字和地址。
当有了外键约束之后,操作数据的顺序如下: 插入数据: 先插入主表的数据,再插入副表数据 修改数据: 先修改主表数据,再修改副表数据 删除数据: 先删除副表数据,再删除主表数据 CREATE TABLE student( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), gender VARCHAR(4), schoolID INT, schoolName VARCHAR(40), schoolAdd VARCHAR(40) ); INSERT INTO student(NAME,gender,schoolID,schoolName,schoolAdd) VALUES('wy','boy',1,'qinghua','beijing'); INSERT INTO student(NAME,gender,schoolID,schoolName,schoolAdd) VALUES('tom','boy',2,'peking','beijing');将上面的sutdent表重新设计为student表和school表:
– 由于上面的表有冗余,现在需要把这个表分成两个表,一个学生表,一个学校表,这两个表是有关系的,比如学生一定是有所属学校的 – 不存在学生的学校不在学校表中。
– 只能先创建school表
CREATE TABLE school( id INT PRIMARY KEY, schoolName VARCHAR(40), schoolAddress VARCHAR(40) );– 后创建学生表,不然这个外键没有位置,这里student表有个外键, CONSTRAINT stu_school_fk FOREIGN KEY(schoolID) REFERENCES school(id) *其中CONSTRAINT 是约束 stu_school_fk是外键名字; FOREIGN KEY(schoolID)是本表的外键; REFERENCES参照; school(id) 参照school表的id字段。*
CREATE TABLE student( id INT PRIMARY KEY, NAME VARCHAR(20), gender VARCHAR(4), schoolID INT, CONSTRAINT stu_school_fk FOREIGN KEY(schoolID) REFERENCES school(id) );给这两个表插入数据:
INSERT INTO school VALUES(1,'npu','shanxixiaan'); INSERT INTO school VALUES(2,'beijingdaxue','beijing'); INSERT INTO school VALUES(3,'qinghua','bejing'); INSERT INTO school VALUES(4,'nanda','nanjing'); INSERT INTO school VALUES(5,'zheda','nanjing'); INSERT INTO student(id,NAME,gender,schoolID) VALUES(1,'wy','boy',1); INSERT INTO student(id,NAME,gender,schoolID) VALUES(2,'tom','boy',2); INSERT INTO student(id,NAME,gender,schoolID) VALUES(3,'jack','boy',3); INSERT INTO student(id,NAME,gender,schoolID) VALUES(4,'tommy','jack',3); INSERT INTO student(id,NAME,gender,schoolID) VALUES(5,'yuhck','boy',4);内连接就是将两个表满足一定条件的连接起来:
-- 内连接 SELECT stu.name,sch.schoolName FROM student stu,school sch WHERE stu.schoolID=sch.id; -- 内连接的另一种语法 SELECT stu.name,sch.schoolName FROM student stu INNER JOIN school sch ON stu.schoolID=sch.id;左外连接是把LEFT OUTER JOIN这几个关键字左边表的所选字段全部显示,如果右边的表没有相应的内容,则用null;即如果学生的schoolName没有值,使用null显示;
-- 左外连接 SELECT stu.name,sch.schoolName FROM school sch LEFT OUTER JOIN student stu ON stu.schoolID=sch.id;右外连接类似,只是关键字RIGHT OUTER JOIN右边的表所选字段全部显示,左边的表的字段如果没有相应的值,使用null显示;
-- 右外连接 SELECT stu.name,sch.schoolName FROM student stu RIGHT OUTER JOIN school sch ON stu.schoolID=sch.id;级联技术是连接两个表,如果其中一个表删除了一条数据,如果另一表中还在使用该条数据,则在不通知他的情况下直接操作相关的数据条目; 例如下面两个表,一个学生表,一个学校表,学生表在delete操作上级联school表,因此当删除学校id为3的时候,学生表中学校id为3的学生也直接删除; 因此级联技术要谨慎使用;
-- 级联技术 CREATE TABLE school( id INT PRIMARY KEY, schoolName VARCHAR(40), schoolAddress VARCHAR(40) ); CREATE TABLE student( id INT PRIMARY KEY, NAME VARCHAR(20), gender VARCHAR(4), schoolID INT, CONSTRAINT stu_school_fk FOREIGN KEY(schoolID) REFERENCES school(id) ON UPDATE CASCADE ON DELETE CASCADE ); INSERT INTO school VALUES(1,'npu','shanxixiaan'); INSERT INTO school VALUES(2,'beijingdaxue','beijing'); INSERT INTO school VALUES(3,'qinghua','bejing'); INSERT INTO school VALUES(4,'nanda','nanjing'); INSERT INTO school VALUES(5,'zheda','nanjing'); INSERT INTO student(id,NAME,gender,schoolID) VALUES(1,'wy','boy',1); INSERT INTO student(id,NAME,gender,schoolID) VALUES(2,'tom','boy',2); INSERT INTO student(id,NAME,gender,schoolID) VALUES(3,'jack','boy',3); INSERT INTO student(id,NAME,gender,schoolID) VALUES(4,'tommy','jack',3); INSERT INTO student(id,NAME,gender,schoolID) VALUES(5,'yuhck','boy',4); INSERT INTO student(id,NAME,gender,schoolID) VALUES(5,'wwl','girl',4); DELETE FROM school WHERE id=3;数据库设计有一定的规范,按照要求级别不同,分为范式。
第一范式为: 要求表的每个字段必须独立的不可分割的单元;例如学生表的name字段,里面有firstname和lastname,那么则需要将name字段分开为两个字段;
第二范式: 在第一范式的基础上,要求表的除主键以外的字段都和主键有依赖关系的。一张表应该只表达一个意思。如上面的学生表和学校表,需要分开;
第三范式:在第二范式基础上,要求表的除主键外的字段都只能和主键有直接决定的依赖关系。如上面的学生表中,只能存在学校id,如果再加入学校地址,则这个地址既可以通过学校id找到,又可以通过学生ID找到,有冗余,第三范式不允许。
特点: 1)存储过程保存到数据库服务器端,通过数据库客户端工具调用存储过程 2)存储过程的效率会非常高!因为存储过程是在数据库服务器端执行。 3)存储过程的移植性非常差的! 语法:
DELIMITER 结束符号 CREATE PROCEDURE 存储过程名称 (形式参数列表) BEGIN 多个sql语句 END 结束符号– 调用存储过程
CALL 存储过程名称(实际参数列表);参数类型: IN: 输入参数,可以携带数据到存储过程中 OUT: 输出参数,可以携带数据到存储过程外面。 INOUT: 输入输出参数。
mysql数据库三种变量: 1)全局变量。mysql内置的变量,mysql程序关闭的时候全局变量才会失效!! -- show variables:产看全局变量 -- character_set_client: mysql接收的客户端的数据编码 -- character_set_results: mysql使用什么编码输出给客户端数据 -- 查看某个全局变量: select @@变量名 -- 修改某个全局变量: set @@变量名=值 2) 会话变量。变量只在某次登录的会话中有效!退出连接,会话变量数据失效!! -- 查看某个会话变量: select @变量名 -- 修改/定义某个会话变量: set @变量名=值 -- 案例:演示查询和更改会话变量 3) 局部变量:在存储过程中定义的变量。存储过程结束局部变量失效!! -- 查看某个局部变量: select 变量名 -- 修改某个局部变量: set 变量名=值 -- 定义某个局部变量: declare 变量名 数据类型;下面使用会话变量来接收输出参数;
有输入输出参数的存储过程 创建存储过程: DELIMITER CREATEPROCEDUREproQueryNameById(INsIdINT,OUTsNameVARCHAR(20))BEGINSELECTNAMEINTOsNameFROMstudentWHEREid=sId;END
调用存储过程:
CALL pro_QueryNameById(2,@sName); SELECT @sName;删除存储过过程
DROP PROCEDURE pro_QueryNameById;触发器是当用户进行了某项操作,会出发它,进行日志记录,这样可以记录用户进行了哪些操作,以便进行了错误操作进行回滚。 首先创建一个日志表,用于保存用户进行了哪些操作;
-- create a student operation log CREATE TABLE stuLog( id INT PRIMARY KEY AUTO_INCREMENT, content VARCHAR(20) );下面是定义一个插入触发器,当用户进行插入操作,往日志表中插入一条数据:’do insert’
-- insert log CREATE TRIGGER tri_stuInsert AFTER INSERT ON student FOR EACH ROW INSERT INTO stuLog(content) VALUES('do insert'); INSERT INTO student(NAME) VALUES('周华健');下面是定义一个更新触发器,当用户进行更新操作,往日志表中插入一条数据:’update’
-- update log CREATE TRIGGER tri_stuUpdate AFTER UPDATE ON student FOR EACH ROW INSERT INTO stuLog(content) VALUES('update'); UPDATE student SET NAME='wwwww' WHERE id=3;下面是定义一个删除触发器,当用户进行删除操作,往日志表中插入一条数据:’delete’
-- delete log CREATE TRIGGER tri_stuDelete AFTER DELETE ON student FOR EACH ROW INSERT INTO stuLog(content) VALUES('delete'); DELETE FROM student WHERE id=3;分配查询testdb数据库的student表的权限给eric用户,密码为‘123456’
GRANT SELECT ON testdb.student TO 'eric'@'localhost' IDENTIFIED BY '123456';