Javaweb

Junit单元测试

  1. 黑盒测试:不需要写代码、给输入值、看程序能否输出期望的值
  2. 白盒测试需要写代码、关注程序的具体执行流程(Junit测试就是白盒测试的一种)

Junit的使用

  1. 定义一个测试类(测试用例)
  2. 定义测试方法:可以独立运行
  3. 给方法加注解@Test
  4. 判定结果

计算器类

package com.junit;
//计算器类
public class Calculator {
    //加法
    public int add(int a,int b){
        return a+b;
    }
    //减法
    public int sub(int a,int b){
        return a-b;
    }
}

测试类

package com.test;
import com.junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class CalculatorTest {
    //初始化方法、所有测试方法在执行前都会先执行此方法
    @Before
    public void init(){
        System.out.println("init,,,,,,");
    }
    //释放资源、在所有方法执行完后、都会自动执行该方法
    @After
    public void close(){
        System.out.println("after,,,,");
    }
    //测试add方法
    @Test
    public void testAdd(){
        //1、创建计算器对象
        Calculator c=new Calculator();
        //2、调用add方法
        int result1= c.add(1,5);
        //System.out.println(result1);
        //3、断言
        Assert.assertEquals(6,result1);
    }

    //测试sub方法
    @Test
    public void testSub(){
        //1、创建计算器对象
        Calculator c=new Calculator();
        //2、调用sub方法
        int result2=c.sub(5,6);
        //System.out.println(result2);
        Assert.assertEquals(-1,result2);
    }
}

反射

  1. 反射:框架设计的灵魂
  2. 框架:半成品软件、可以在框架的基础上进行软件开发、简化编码
  3. 反射:将类的各个组成部分封装为其他对象、这就是反射机制
  4. 好处:可以在程序运行过程中操作这些对象、可以解耦提高程序的可扩展性
    在这里插入图片描述

获取字节码class对象的三种方式

  1. Class.forName("全类名”):将字节码文件加载进内存、返回class对象多用于配置文件将类名定义在配置文件中、读取文件加载类
  2. 类名.class:通过类名的属性class获取 多用于参数的传递
  3. 对象.getclass():getclass()方法在object类中定义 多用于对象的获取字节码的方式
  4. 同一个字节码文件(*.class)在一次程序运行过程中、只会被加载一次、不论通过哪一种方法获取的class对象都是同一个

Person类

package com.domain;
public class Person {
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试类

package com.reflect;
import com.domain.Person;
public class ReflectDemo1 {
        /**
         *  1. Class.forName("全类名”):将字节码文件加载进内存、返回class对象
         *  2. 类名.class:通过类名的属性class获取
         *  3. 对象.getclass():getclass()方法在object类中定义
         */
        public static void main(String[] args) throws Exception {
                // 1. Class.forName("全类名”)
                Class cls1 = Class.forName("com.domain.Person");
                System.out.println(cls1);
                //2. 类名.class
                Class cls2 = Person.class;
                System.out.println(cls1);
                //3. 对象.getclass()
                Person person=new Person();
                Class cls3=person.getClass();
                System.out.println(cls3);
                //==比较三个对象
                System.out.println(cls1==cls2);
                System.out.println(cls1==cls3);
        }

}

class对象功能

  1. 获取功能:获取成员变量、获取构造方法、获取成员方法、获取类名

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Person类

package com.domain;
public class Person {
    private String name;
    private int age;
    public String a;
    protected String b;
    String c;
    private String d;
    public Person(){
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
    public void eat(){
        System.out.println("eat......");
    }
    public void eat(String food){
        System.out.println("eat......"+food);
    }
}


ReflectDemo2类

package com.reflect;
import com.domain.Person;
import java.lang.reflect.Field;
public class ReflectDemo2 {
        public static void main(String[] args) throws Exception {
                //获取Person的Class对象
                Class personClass = Person.class;
                //1、Field[]getFields()获取所有public修饰的成员变量
                Field[] fields = personClass.getFields();
                for (Field field : fields) {
                        System.out.println(field);
                }
                System.out.println("==================");
                //2、Field[]getField()获取指定public修饰的成员变量
                Field a = personClass.getField("a");
                //获取成员变量a的值
                Person person=new Person();
                Object vaule1 = a.get(person);
                System.out.println(vaule1);
                //设置a的值
                a.set(person,"王文超");
                System.out.println(person);

                System.out.println("===================");
                //获取所有的成员变量、不考虑修饰符
                Field[] declaredFields = personClass.getDeclaredFields();
                for (Field declaredField : declaredFields) {
                        System.out.println(declaredField);
                }

                Field d = personClass.getDeclaredField("d");
                //忽略访问权限修饰符的安全检查
                d.setAccessible(true);//暴力反射
                Object value2 = d.get(person);
                System.out.println(value2);
        }

}

ReflectDemo3类

package com.reflect;
import com.domain.Person;
import java.lang.reflect.Constructor;
public class ReflectDemo3 {
        public static void main(String[] args) throws Exception {
                //获取Person的Class对象
                Class personClass = Person.class;
                Constructor constructor = personClass.getConstructor(String.class, int.class);
                System.out.println(constructor);
                //创建对象
                Object person = constructor.newInstance("张三", 23);
                System.out.println(person);

                System.out.println("===================");
                Constructor constructor1 = personClass.getConstructor();
                System.out.println(constructor1);
                //创建对象
                Object person1 = constructor1.newInstance();
                System.out.println(person1);

                Object person2 = personClass.newInstance();//构造结果和上面的一样
                System.out.println(person2);
        }
}

ReflectDemo4类

package com.reflect;
import com.domain.Person;

import java.lang.reflect.Method;

public class ReflectDemo4 {
        public static void main(String[] args) throws Exception {
                //获取Person的Class对象
                Class personClass = Person.class;
                //获取指定名称的方法
                Method eat_method = personClass.getMethod("eat");
                Person p=new Person();
                //执行方法
                eat_method.invoke(p);

                Method eat_method2 = personClass.getMethod("eat", String.class);
                eat_method2.invoke(p,"饭");

                System.out.println("=========================");
                //获取所有public修饰的方法
                Method[] methods = personClass.getMethods();
                for (Method method : methods) {
                        System.out.println(method);
                        String name = method.getName();
                        System.out.println(name);
                        //method.setAccessible(true);
                }

                //获取类名
                String classname = personClass.getName();
                System.out.println(classname);

        }
}

反射——案例

写一个”框架“、可以帮我们创建任意类的对象、并且执行其中的任意方法 前提:不能改变该类的任何代码

实现:1、配置文件 。2、反射
步骤
1、将需要创建对象的全类名和需要执行的方法定义在配置文件中
2、在程序中加载读取配置文件
3、使用反射技术来加载类文件进内存
4、创建对象
5、执行方法

Student类

package com.domain;
public class Student {
    public void sleep(){
        System.out.println("sleep......");
    }
}

pro.properties配置文件

className=com.domain.Student
methodName=sleep

ReflectTest类

package com.reflect;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

//框架类
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //可以创建任意类的对象、可以执行任意方法  前提:不能改变该类的任何代码
        //1、加载配置文件
        //1.1创建Properties对象
        Properties pro=new Properties();
        //1.2加载配置文件、转换为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        //2、获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3、加载该类进内存
        Class cls = Class.forName(className);
        //4、创建对象
        Object obj = cls.newInstance();
        //5、获取方法对象
        Method method = cls.getMethod(methodName);
        //6、执行方法
        method.invoke(obj);
    }
}

注解

概念:说明程序的。给计算机看的
注释:用文字描述程序的。给程序员看的

jdk内置注解
@Override :检测被该注解标注的方法是否是继承自父类(接口)的
@ @Deprecated:该注解标注的内容、表示已过时
@SuppressWarnings:压制警告 —一般传递参数all—@SuppressWarnings(“all”)

package com.annotation;

import java.util.Date;

/**
 * jdk中预定义的一些注解
 * @Override :检测被该注解标注的方法是否是继承自父类(接口)的
 * @ @Deprecated:该注解标注的内容、表示已过时
 *  @SuppressWarnings:压制警告
 */
@SuppressWarnings("all")
public class AnnoDemo2 {
    @Override
    public String toString(){
        return super.toString();
    }

    @Deprecated
    public void show1(){
        //有缺陷
    }
    public void show2(){
        //替代show1方法
    }
    public void demo(){
        show1();
        Date date=new Date();
    }
}

自定义注解
格式
元注解
public @interface 接口名{属性列表;}

本质:注解本质上就是一个接口、该接口默认继承Annotation接口

属性:接口中的抽象方法
1、属性的返回值类型:基本数据类型、String、枚举、注解、以上类型的数组
2、定义了属性、使用时需要给属性赋值 如果使用default关键字给属性默认初始化值、则使用时可以不进行属性的赋值-------如果只有一个属性、并且属性的名称是value时,可以省略属性名称、直接定义值—数组赋值时、使用{}包裹、如果数组只有一个值、可以省略{}

在这里插入图片描述
Calculator类

package com.demo;

public class Calculator {
    //加法
    @Check
    public void add(){
        System.out.println("1+0="+(1+0));
    }
    //减法
    @Check
    public void sub(){
        System.out.println("1-0="+(1-0));
    }
    //乘法
    @Check
    public void mul(){
        System.out.println("1*0="+(1*0));
    }
    //除法
    @Check
    public void div(){
        System.out.println("1/0="+(1/0));
    }
    public void show(){
        System.out.println("================");
    }
}

Check注解

package com.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}

TestCheck测试类

package com.demo;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

//简单的测试框架
//当主方法执行后、会自动自行被检测的所有方法(加了check注解的方法)判断方法是否有异常、记录到文件中
public class TestCheck {
    public static void main(String[] args) throws IOException {
        //1、创建计算机对象
        Calculator calculator=new Calculator();
        //2、获取字节码文件对象
        Class cls = calculator.getClass();
        //3、获取所有的方法
        Method[] methods = cls.getMethods();
        int number=0;//出现异常的次数
        BufferedWriter bw=new BufferedWriter(new FileWriter("bug.txt"));
        for (Method method : methods) {
            //4、判断方法上是否有check注解
            if (method.isAnnotationPresent(Check.class)){
                //5、有、执行
                try {
                    method.invoke(calculator);
                }catch (Exception e){
                    //6、捕获异常
                    //记录到文件中
                    number++;
                    bw.write(method.getName()+"方法出异常了");
                    bw.newLine();
                    bw.write("异常的名称:"+e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因:"+e.getCause().getMessage());
                    bw.newLine();
                    bw.write("=========================");
                    bw.newLine();
                }
            }
        }
        bw.write("本次测试一共出现"+number+"次异常");
        bw.flush();
        bw.close();


    }
}

SQL简介

  • 英文:Structured Query Language,简称 SQL
  • 结构化查询语言,一门操作关系型数据库的编程语言
  • 定义操作所有关系型数据库的统一标准
  • 对于同一个需求,每一种数据库操作的方式可能会存在一些不一样的地方,我们称为“方言”

通用语法

  • SQL 语句可以单行或多行书写,以分号结尾
  • MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写
  • 注释----单行注释: – 注释内容 或 #注释内容(MySQL 特有)
  • 注意:使用-- 添加单行注释时,–后面一定要加空格,而#没有要求
  • 多行注释: /* 注释 */

SQL分类

  • DDL(Data Definition Language) : 数据定义语言,用来定义数据库对象:数据库,表,列等
    DDL简单理解就是用来操作数据库,表等
    在这里插入图片描述

  • DML(Data Manipulation Language) 数据操作语言,用来对数据库中表的数据进行增删改
    DML简单理解就对表中数据进行增删改
    在这里插入图片描述

  • DQL(Data Query Language) 数据查询语言,用来查询数据库中表的记录(数据)
    DQL简单理解就是对数据进行查询操作。从数据库表中查询到我们想要的数据。

  • DCL(Data Control Language) 数据控制语言,用来定义数据库的访问权限和安全级别,及创建用户
    DML简单理解就是对数据库进行权限控制。比如我让某一个数据库表只能让某一个用户进行操作等。

注意: 以后我们最常操作的是 DML 和 DQL ,因为我们开发中最常操作的就是数据。
在这里插入图片描述

DDL:操作数据库、表

操作数据库:CRUD
1、C(create):创建
2、R(Retrieve):查询
3、U(Update):修改
4、D(Delete):删除
5、使用数据库

查询所有的数据库名称

show databases;

查看创建数据库的语句

show create database 数据库名;

如果不存在此数据库则创建

create database if not exists 数据库;

指定数据库的编码

create database 数据库 character set gbk;

修改数据库的字符集

alter database 数据库名称 character set 字符集名称;

删除数据库

drop database 数据库名称;

如果数据库存在则删除

drop database if exists 数据库名称;

*查询当前正在使用的数据库

select database();

使用数据库

use 数据库名称;
操作表:
1、C(create):创建
2、R(Retrieve):查询
3、U(Update):修改
4、D(Delete):删除
5、使用数据库

查询某个数据库中所有表的名称

show tables;

查询表结构

desc 表名;

创建表:语法
create table 表名
(列名1 数据类型1,
列名2 数据类型2,
.。。。。。);

数据库类型
1、int:整数类型------age int,
2、double:小数类型----score double(5,2)
3、date:日期----只包含年月日、yyyy-MM-dd
4、datetime:日期、包含年月日时分秒:yyyy-MM-dd HH:mm:ss
5、timestamp:时间戳类型:包含年月日时分秒yyyy-MM-dd HH:mm:ss -----如果将来不给这个字段赋值、或赋值为null、则默认使用当前的系统时间、自动赋值
6、varchar:字符串类型—name varchar(20):姓名最大20个字符

创建表

create table student(
						id int,
						name varchar(32),
						age int,
						score double(4,1),
						birthday date,
						insert_time timestamp);

复制表

create table 表名 like 被复制的表名;

删除表

drop table if exists 表名;

修改表名

alter table 表名 rename to 新的表名;

修改表的字符集

alter table 表名 character set 字符集名称;

添加一列

alter table 表名 add 列名 数据类型;

修改列名称 类型

alter table 表名 change 列名 新列名 新数据类型;  
alter table 表名 modify 列名 新数据类型;

删除列

alter table 表名 drop 列名;

DML:增删改表中的数据

添加数据

insert into 表名(列名1,列名2,...) values(1,2,...);

注意:列名和值要一 一对应、如果表名后不定义列名则默认给所有列添加值、除了数字类型其他的需要用引号

删除数据

delete from 表名 where 条件;

注意:若不添加条件则删除表中所有记录
若要删除所有记录
1、delete from 表名; 不推荐使用-有多少条记录、就会执行多少次删除操作
2、truncate table 表名;–先删除表、在创建一张一样的空表

修改数据

update 表名 set 列名1=1,列名2=2,...... where 条件;

注意:若不添加条件则修改表中所有记录

DQL:查询表中的记录

select *from 表名;
语法:
	select
		字段列表
	from
		表名列表
	where
		条件列表
	group by
		分组字段
	having
		分组之后的条件
	order by
		排序
	limit
		分页限定
	
		

基础查询

CREATE TABLE student (
id int, -- 编号
name varchar(20), -- 姓名
age int, -- 年龄
sex varchar(5), -- 性别
ddress varchar(100), -- 地址
math double(5,2), -- 数学成绩
english double(5,2), -- 英语成绩
hire_date date -- 入学时间
);
-- 添加数据
INSERT INTO stu(id,NAME,age,sex,address,math,english,hire_date)
VALUES
(1,'马运',55,'男','杭州',66,78,'1995-09-01'),
(2,'马花疼',45,'女','深圳',98,87,'1998-09-01'),
(3,'马斯克',55,'男','香港',56,77,'1999-09-02'),
(4,'柳白',20,'女','湖南',76,65,'1997-09-05'),
(5,'柳青',20,'男','湖南',86,NULL,'1998-09-01'),
(6,'刘德花',57,'男','香港',99,99,'1998-09-01'),
(7,'张学右',22,'女','香港',99,99,'1998-09-01'),
(8,'德玛西亚',18,'男','南京',56,65,'1994-09-02');

多个字段的查询

SELECT 字段列表 FROM 表名;
SELECT * FROM 表名; -- 查询所有数据
 select name,age from student;--查询name、age两列
 select * from student;--查询所有列的数据,列名的列表可以使用*替代

去除重复

SELECT DISTINCT 字段列表 FROM 表名;

计算列

select name,math as 数学成绩,english as 英文成绩,math+english as 总分 from student;
select name,ifnull(math,0) as 数学成绩,ifnull(english,0) as 英文成绩,math+english as 总分 from student;
--ifnull(表达式1,表达式2)
--表达式1:哪个字段需要判断是否为null
--表达式2:如果该字段为null后的替换值

起别名

--查询姓名、数学成绩、英语成绩。并通过as给math和english起别名(as关键字可以省略)
select name,math as 数学成绩,english as 英文成绩 from student;
select name,math 数学成绩,english 英文成绩 from student;

条件查询

语法
SELECT 字段列表 FROM 表名 WHERE 条件列表;
条件
在这里插入图片描述

条件查询练习

--查询年龄大于20岁的学员信息
select * from stu where age > 20;

--查询年龄大于等于20岁的学员信息
select * from stu where age >= 20;

--查询年龄大于等于20岁 并且 年龄 小于等于 30岁 的学员信息
select * from stu where age >= 20 && age <= 30;
select * from stu where age >= 20 and age <= 30;
--上面语句中 && 和 and 都表示并且的意思。建议使用 and 。
也可以使用 between ... and 来实现上面需求
select * from stu where age BETWEEN 20 and 30;

--查询入学日期在'1998-09-01' 到 '1999-09-01' 之间的学员信息
select * from stu where hire_date BETWEEN '1998-09-01' and '1999-09-01';

--查询年龄等于18岁的学员信息
select * from stu where age = 18;

--查询年龄不等于18岁的学员信息
select * from stu where age != 18;
select * from stu where age <> 18;


--查询年龄等于18岁 或者 年龄等于20岁 或者 年龄等于22岁的学员信息
select * from stu where age = 18 or age = 20 or age = 22;
select * from stu where age in (18,20 ,22);


--查询英语成绩为 null的学员信息
null值的比较不能使用 = 或者 != 。需要使用 is 或者 is not
select * from stu where english = null; -- 这个语句是不行的
select * from stu where english is null;
select * from stu where english is not null;

模糊查询练习

模糊查询使用like关键字,可以使用通配符进行占位:
(1)_ : 代表单个任意字符
(2)% : 代表任意个数字符

--查询姓'马'的学员信息
select * from stu where name like '马%';

--查询第二个字是'花'的学员信息
select * from stu where name like '_花%';

--查询名字中包含 '德' 的学员信息
select * from stu where name like '%德%';

排序查询

语法
SELECT 字段列表 FROM 表名 ORDER BY 排序字段名1 [排序方式1],排序字段名2 [排序方式2] …;
ASC : 升序排列 (默认值)
DESC : 降序排列
注意:如果有多个排序条件,当前边的条件值一样时,才会根据第二条件进行排序

练习

--查询学生信息,按照年龄升序排列
select * from stu order by age ;

--查询学生信息,按照数学成绩降序排列
select * from stu order by math desc ;

--查询学生信息,按照数学成绩降序排列,如果数学成绩一样,再按照英语成绩升序排列
select * from stu order by math desc , english asc ;

聚合函数

概念:将一列数据作为一个整体,进行纵向计算。
语法:SELECT 聚合函数名(列名) FROM 表;
注意:null 值不参与所有聚合函数运算
练习

--统计班级一共有多少个学生
select count(id) from stu;
select count(english) from stu;

--上面语句根据某个字段进行统计,如果该字段某一行的值为null的话,将不会被统计。所以可以在count(*) 来实现。* 表示所有字段数据,一行中也不可能所有的数据都为null,所以建议使用 count(*)
select count(*) from stu;

--select count(*) from stu;
select max(math) from stu;

--查询数学成绩的最低分
select min(math) from stu;

--查询数学成绩的总分
select sum(math) from stu;

--查询数学成绩的平均分
select avg(math) from stu;

--查询英语成绩的最低分
select min(english) from stu;

分组查询

语法:
SELECT 字段列表 FROM 表名 [WHERE 分组前条件限定] GROUP BY 分组字段名 [HAVING 分组后条件过滤];
注意:分组之后,查询的字段为聚合函数和分组字段,查询其他字段无任何意义

练习

--查询男同学和女同学各自的数学平均分
select sex, avg(math) from stu group by sex;

> 注意:分组之后,查询的字段为聚合函数和分组字段,查询其他字段无任何意义

select name, sex, avg(math) from stu group by sex; -- 这里查询name字段就没有任何意义

--查询男同学和女同学各自的数学平均分,以及各自人数
select sex, avg(math),count(*) from stu group by sex;

--查询男同学和女同学各自的数学平均分,以及各自人数,要求:分数低于70分的不参与分组
select sex, avg(math),count(*) from stu where math > 70 group by sex;

--查询男同学和女同学各自的数学平均分,以及各自人数,要求:分数低于70分的不参与分组,分组之后人数大于2个的
select sex, avg(math),count(*) from stu where math > 70 group by sex having count(*) > 2;

where 和 having 区别:
执行时机不一样:where 是分组之前进行限定,不满足where条件,则不参与分组,而having是分组之后对结果进行过滤。
可判断的条件不一样:where 不能对聚合函数进行判断,having 可以。

分页查询

语法
SELECT 字段列表 FROM 表名 LIMIT 起始索引 , 查询条目数;
注意: 上述语句中的起始索引是从0开始

练习

--从0开始查询,查询3条数据
select * from stu limit 0 , 3;

--每页显示3条数据,查询第1页数据
select * from stu limit 0 , 3;

--每页显示3条数据,查询第2页数据
select * from stu limit 3 , 3;

--每页显示3条数据,查询第3页数据
select * from stu limit 6 , 3;

从上面的练习推导出起始索引计算公式:
起始索引 = (当前页码 - 1) * 每页显示的条数

约束

约束是作用于表中列上的规则,用于限制加入表的数据
例如:我们可以给id列加约束,让其值不能重复,不能为null值。
约束的存在保证了数据库中数据的正确性、有效性和完整性
添加约束可以在添加数据的时候就限制不正确的数据,年龄是3000,数学成绩是-5分这样无效的数据,继而保障数据的
完整性。

分类

  • 非空约束: 关键字是 NOT NULL

  • 唯一约束:关键字是 UNIQUE

  • 主键约束: 关键字是 PRIMARY KEY

  • 检查约束: 关键字是 CHECK

  • 默认约束: 关键字是 DEFAULT

  • 外键约束: 关键字是 FOREIGN KEY

非空约束: 关键字是 NOT NULL
保证列中所有的数据不能有null值。
例如:id列在添加 马花疼 这条数据时就不能添加成功。
=================================================================================================
唯一约束:关键字是 UNIQUE
保证列中所有数据各不相同。
例如:id列中三条数据的值都是1,这样的数据在添加时是绝对不允许的。
=================================================================================================
主键约束: 关键字是 PRIMARY KEY
主键是一行数据的唯一标识,要求非空且唯一。一般我们都会给没张表添加一个主键列用来唯一标识数据。
例如:上图表中id就可以作为主键,来标识每条数据。那么这样就要求数据中id的值不能重复,不能为null值。
=================================================================================================
检查约束: 关键字是 CHECK
保证列中的值满足某一条件。
例如:我们可以给age列添加一个范围,最低年龄可以设置为1,最大年龄就可以设置为300,这样的数据才更合理些。
注意:MySQL不支持检查约束。
这样是不是就没办法保证年龄在指定的范围内了?从数据库层面不能保证,以后可以在java代码中进行限制,一样也
可以实现要求。
================================================================================================
默认约束: 关键字是 DEFAULT
保存数据时,未指定值则采用默认值。
例如:我们在给english列添加该约束,指定默认值是0,这样在添加数据时没有指定具体值时就会采用默认给定的0。
================================================================================================
外键约束: 关键字是 FOREIGN KEY
外键用来让两个表的数据之间建立链接,保证数据的一致性和完整性。
外键约束现在可能还不太好理解,后面我们会重点进行讲解。
================================================================================================

非空约束
非空约束用于保证列中所有数据不能有NULL值

--添加约束
-- 创建表时添加非空约束
CREATE TABLE 表名(
列名 数据类型 NOT NULL,);
-- 建完表后添加非空约束
ALTER TABLE 表名 MODIFY 字段名 数据类型 NOT NULL;

--删除约束
ALTER TABLE 表名 MODIFY 字段名 数据类型;

唯一约束
唯一约束用于保证列中所有数据各不相同
唯一约束可以有null值、但只能有一条记录为null

sql
--添加约束
-- 创建表时添加唯一约束
CREATE TABLE 表名(
列名 数据类型 UNIQUE [AUTO_INCREMENT],
-- AUTO_INCREMENT: 当不指定值时自动增长);
CREATE TABLE 表名(
列名 数据类型,[CONSTRAINT] [约束名称] UNIQUE(列名)
);
-- 建完表后添加唯一约束
ALTER TABLE 表名 MODIFY 字段名 数据类型 UNIQUE;


---- 建完表后添加唯一约束
ALTER TABLE 表名 MODIFY 字段名 数据类型 UNIQUE;`


--删除约束
ALTER TABLE 表名 DROP INDEX 字段名;

主键约束
主键是一行数据的唯一标识,要求非空且唯一
一张表只能有一个主键

--添加约束
-- 创建表时添加主键约束
CREATE TABLE 表名(
列名 数据类型 PRIMARY KEY [AUTO_INCREMENT],);
CREATE TABLE 表名(
列名 数据类型,
[CONSTRAINT] [约束名称] PRIMARY KEY(列名)
);
-- 建完表后添加主键约束
ALTER TABLE 表名 ADD PRIMARY KEY(字段名);


--删除约束
ALTER TABLE 表名 DROP PRIMARY KEY;

默认约束
保存数据时,未指定值则采用默认值

--添加约束
-- 创建表时添加默认约束
CREATE TABLE 表名(
列名 数据类型 DEFAULT 默认值,);
-- 建完表后添加默认约束
ALTER TABLE 表名 ALTER 列名 SET DEFAULT 默认值;


--删除约束
 ALTER TABLE 表名 ALTER 列名 DROP DEFAULT;

外键约束
外键用来让两个表的数据之间建立链接,保证数据的一致性和完整性。

--添加约束
-- 创建表时添加外键约束
CREATE TABLE 表名(
列名 数据类型,[CONSTRAINT] [外键名称] FOREIGN KEY(外键列名) REFERENCES 主表(主表列名)
);
-- 建完表后添加外键约束
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);


--删除约束
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值