分享一些最近的学习笔记叭
------------------------Day 6.19 多态--------------------------
1.父类引用指向子类对象
Animal a=new Cat();
成员变量访问特点:编译看左面,运行看左面
成员方法访问特点:编译看左面,执行看右面(因为子类进行了重写,所以调用了子类,但如果没有重写子类,则是运行父类)
2.多态中的转型:
向上转型:父类引用指向子类对象(比如Animal a=new Cat();)
多态的向上转型指的是把当前对象的类型提升为当前对象对应的类的父类类型或者当前对象对应的类实现的接口类型
向下转型:子类型 对象名=(子类型)父类引用;(比如Cat c=(Cat)a;)
为什么要向下转型:
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥 有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子 类特有的方法,必须做向下转型。
多态向下转型格式:
子类类型 变量名 = (子类类型) 父类变量名;
多态向下转型的前提:
必须是有一个已经向上转型的子类对象,才能将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型.
public class Ye{
String name = "爷爷";
public void method(){
System.out.println("爷爷类"); }
}
public class Fu extends Ye{
String name = "父类";
public void method(){
System.out.println("父类"); }
}
public class ShuShu extends Ye{
String name = "叔叔类";
public void method(){
System.out.println("叔叔类");}
}
public class Zi extends Fu{
String name = "子类";
public void method(){
System.out.println("子类");}
}
public class Demo{
public static void main(String[] args) {
_______ }
}
下列代码填入横线处,代码能够正常运行的是( )
A:Ye ye = new Fu(); Fu f = (Fu)ye;
B:Ye ye = new Fu(); ShuShu f = (ShuShu)ye;
C:Ye ye = new Fu(); Zi f = (Zi)ye;
D:Ye ye = new Zi(); Fu f = (Fu)ye;
向下转型的注意点:最多只能向下转成本身,不能转成其他类,即使是其子类也不行。
选项:该选项正确。
B选项:该选项错误,ShuShu类和Fu类没有任何关系,只是共同继承于一个父类,两个没有任何关系的类是不能互相转换的。
C选项:该选项错误,此时因为创建的父类对象,所以最多只能向下转成父类类型,不能强制转换成子类类型。
D选项:该选项正确。
2.父类的成员变量和成员方法(即属性和行为)可以继承,但是构造方法不可以继承
3.抽象类的④大特点:
1)抽象类和抽象方法必须用abstract关键字修饰
2)抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
3)抽象类不能实例化对象(若想实例化,则只能是参照多态的方式,通过子类对象实例化即类似 Animal a=new Cat();)
4)抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类
3.1抽象类的成员特点:
1)成员变量:既可以是变量,也可以是常量
2)构造方法:空参构造,有参构造
3)成员方法:抽象方法,普通方法
4.接口:特殊类(java中的接口更多的体现在对行为的抽象)
类中所有方法都是抽象方法,与抽象类不同(允许有非抽象方法,即普通方法)
4.1 接口的特点:
1)接口用关键字interface修饰
2)类实现接口用implements表示
3)接口不可实例化对象,比如不可 jummping j=new jummping();只能是参照多态的方式,通过实现类对象实例化,这叫接口多态,比如jummping j=new Cat();
4)接口的子类
要么重写接口中的所有抽象方法
要么子类也是抽象类
4.2接口的成员特点:
1)成员变量:只能是常量,默认修饰符是public static final(即使不写,也默认添加,? 常量只能被赋值一次,且一定要手动赋值,默认初始化值不算。)
2)构造方法:没有,因为接口主要是扩展功能的,而没有具体存在
3)成员方法:只能是抽象方法,而且所有的都是抽象方法,默认修饰符:public abstract
即使不写,也默认添加。
定义接口中的方法默认会加入abstract, abstract关键字不能和static共存 (原因 : 如果允许, 就可以通过静态的类名.调用没有方法体的抽象方法了, 这样做没有意义)
4.3
1> 类与类的关系:继承关系,只能单继承,但是可以多层继承
2> 类与接口的关系:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时时实现多个接口
3> 接口与接口的关系:继承关系,可以单继承,也可以多继承。
多态的三个前提条件:
必须要有继承或者实现关系。
要有方法的重写,如果没有则没有任何意义,但是语法不会报错!!!!
用多态方式创建对象时,可以使用以下三种方式:
1.父类引用指向子类对象。
2.间接父类引用指向子类对象。
3.接口类型引用指向实现类对象。
被final修饰的变量值不能变:
如果是基本数据类型:数据值不能改变。
如果是引用数据类型:地址值不能改变
被final修饰的变量必须进行赋值,有两种赋值方式:
方式一:在定义的时候直接赋值
方式二:通过构造方法进行赋值,但必须所有的构造方法都给该变量进行赋值。
!!!!!!!!!!
被final修饰的类可以被实例化,被abstract修饰的类不能被实例化
被final修饰的类不能被继承,但是可以继承其他类。
抽象类不能被实例化,需要子类去继承该抽象父类,从而创建子类对象。所以抽象类是需要被继承的,而final修饰的类不能被继承,所以被final修饰的类不能是抽象类。
非抽象子类实现接口:
1. 必须重写接口中所有抽象方法。
2. 实现了接口的默认方法,即可以直接调用,也可以重写
------------------------------Day 6.21 内部类------------------
1..简述String类中的equals方法与Object类中的equals方法的不同点。
String类中的equals方法是用来判断两个对象的内容是否相同,而Object 类中的equals方法是用来判断两个对象是否是同一个对象,所谓同一个对象指的是内存中的同一块存储空间。
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2); //fase
System.out.println(s1.equals(s2));//true
2.public class ToStringTest{
static inti= 1;
public static void main(String args[]){
System.out.println("love " + new ToStringTest());//love java ///字符串和对象拼接,会调用方法把对象转成字符串,拼接结束之后输出。
ToStringTest a = new ToStringTest();
a.i++;
System.out.println("me " + a.i);//me 2
}
public String toString(){ ///重写方法 ,先调用
System.out.print("I ");//I
return "java ";
}
}
运行结果:I love java me 2
原因:当执行代码的时候,首先加载静态变量,然后执行main方法,由于main方法内部第一行代码为输出语句,里面new了此类对象,当执行此行代码时会先创建了本类的对象,由于此类重写了toString方法,会先执行toString方法的打印输出,然后返回“java ”,再执行main方法第一行打印输出。在Java中“System.out.println(类对象名);”实际输出的是该对象的toString()方法返回的字符串,即括号中的内容等价于类对象名.toString(),toString方法的好处是在碰到println方法的时候会被自动调用,不用显示的写出来。
3.内部类
成员内部类的权限修饰符可以是四种中的任意一种
但局部内部类的权限修饰符只能是默认修饰符,不可以是private之类的其它修饰符。
4.匿名内部类没有名字,所以只能在定义这个类的同时,根据这个类创建一个对象。
匿名内部类除了可以在方法内部定义外,也可以在成员位置定义。
写匿名内部类的目的就是为了少定义一个类,我们平时写的匿名内部类new 接口/类(){}这个整体其实是一个对象,就是匿名内部类的对象,当使用这个对象的时候,也是传递这个对象的地址值,跟传递普通的对象一样。
匿名内部类可以用一个变量去接收,可以方便匿名内部类的复用。此时等号左边是接口类型,右边是匿名内部类对象,是一个多态。
只可以创建一个对象,但是匿名内部类的方法可以调用多次。使用一个父类或接口引用指向匿名内部类对象即可.
------------------------------Day6.22 日期/异常--------------------------
1.int型可以定义整型数字,而integer类除了可以定义一个整型数字,还包含各种方法,供我们直接使用。
8种基本数据类型对应的封装数据类型:(java.lang包下)
byte——Byte
short----Short
异常:程序中出现的错误
继承的体系结构:1>Throwable
2>Error:代表不可处理的异常(比如内存溢出、硬件问题)
2>Exception:代表可处理的异常
3>RunTimeException:运行时异常
3>编译时异常
try:代码监视块
Catch:异常的捕获块
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
Throws的成员方法
1>get Message()
public void printStackTrace():把异常详细的错误信息输出
catch块是多重的
throws回避:(并不是正面处理异常,只是暂时规避)
不管是编译时异常还是运行时异常,都可以通过使用throws作抛出处理,只是但其并不能解决实际问题,要想处理异常,那么谁调用谁处理.
-------------------------------Day 6.24 Collection集合----------------------------
1.集合:可变长度的数据容器
2.迭代器对象:循环读取数据。
3.栈:底层容器一般采用。 !!!!!记得看两天的作业题
单列:collection:接口
4.List接口特点
- 有索引
- 可以存储重复元素
- 元素存取有序
5.- ArrayList集合
底层是数组结构实现,查询快、增删慢
- LinkedList集合
底层是链表结构实现,查询慢、增删快
6.请简述迭代器的实现原理
当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
-------------------------------Day 6.25 set集合-------------------------
1.set集合特点:
不包含重复元素的集合。
无序,没有带索引的方法,所以不能使用普通for循环遍历,只能通过迭代器或增强for循环遍历。
2.哈希值简介:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
如何获取哈希值:Objects类中的 public int hashCode():返回对象的哈希码值
哈希值的特点:同一个对象多次调用Hashcode()方法返回的哈希值是相同的。
默认情况下,不同对象的哈希值是不同的,而重写hashCode()方法,可以实 现让不同对象的哈希值相同
3.HashSet集合的特点:
1>.不包含重复元素的集合
2>.底层数据结构是哈希表
3>.对集合的迭代顺序不作保证,也就是说不保证存储和取出的元素顺序一致。
4.HashSet集合保证元素唯一性源码分析:重写hashCode()和equals()方法
5.LinkedHashSet集合特点:(因为是链表,所以可保证元素有序)
1>哈希表和链表实现的Set接口,具有可预测的迭代次序
2>由链表保证元素有序,也就是说元素的存储和取出顺序是一致的。
3>由哈希表保证元素唯一,也就是说没有重复的元素。
6.TreeSet集合
元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
其中两种排序方法:
1>自然排序Comparable的使用:
- 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
2>比较器排序Comparator
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
byte[]bs={97,98,99}
String str=new String(bs);
str.equals("abc)
如果让你重写equals方法,则应该是把字符串转换成对应的字符数组进行比较//97 98 99 //97 98 99 两个数组进行比较,先比较长度,如果长度都不相等,那么直接返回。之后再比较内容。(就类似hashcode)
7.不同对象有不同的哈希值,所以数据都可以添加进去。
8.泛型的好处
- 把运行时期的问题提前到了编译期间
- 避免了强制类型转换
9.可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
修饰符 返回值类型 方法名(数据类型… 变量名) { }
10.请简述HashSet去除重复元素的原理。
?调用被添加元素的hashCode(),和HashSet中已有元素的hashCode比较是否相同
?如果不相同,直接存储
?如果相同,调用equals方法比较是否相同
?不相同,直接存储元素
?相同,认为是同一元素.不存储
11.简述Comparable和Comparator两个接口的区别。
?Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
?Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
------------------------------Day 6.26 map集合--------------------------
1.map的特点:
1>Map每个元素由键与值两部分组成
2>Map键不能重复,每个键对应一个值,值可以重复
3>键和值可以为null
4>元素存取无序
2.map集合的一些常用方法
put(K key,V value):添加元素
remove(Object key):根据键删除键值对元素
void clear():移除所有的键值对元素
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty();判断集合是否为空
int size():集合长度
3.Entry键值对对象遍历Map集合的原理:
Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map 中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
4.map集合的获取功能
get(Object key):根据键获取值
Set<K> keySet():获取所有键的集合
Set<String> keySet = map.keySet();
for(String key : keySet) {
System.out.println(key);
Collection<V> values():获取所有值的集合
Collection<String> values = map.values();
for(String value : values) {
System.out.println(value);
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for (Map.Entry<String, String> me : entrySet) {
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "," + value);
--------------------------------Day 6.28 I/O流--------------------------------
1.字符流更擅长于中文的读取。每次处理一字符
字节流每次处理一字节。字节流是万能流。
2.无论应用程序遇到什么情况,finally语句均会执行。(所以关闭资源的语句最好放到finally语句中)
比如在try catch语句中
如果把关闭资源的语句放在try语句中,如果try出错就不会执行try语句,直接转到
-------------------------------Day 6.29 字节流----------------------------------
1.缓冲区刷新的两种方式:
每到8k自动刷新 手动刷新flush缓冲区(带关闭的输出流有flush()方法,而输入流则不含此方法)
2.读取效率最高的方式:
字节缓冲流+一次读取一个数组(60ms)
3.字节流分为带缓冲的和不带缓冲的
而字节流则是全部带缓冲区的。
-------------------------------Day 6.30 序列化-------------------------------
1.一个对象要想被序列化,该对象所属的类必须实现Serializable接口,不识闲此接口的类将不胡任何序列化或反序列化
2.Serializable是一个标记接口,实现该接口,不需要重写任何方法。
3.序列化完一个类之后,如果对这个方法进行改动,那么就无法进行反序列化。
如果改动小的话,可以生成一个private修饰符修饰的序列号。
------------------------------Day 7.2 线程-----------------------------------
1.成员变量如果是个类的话,比如Person中有身份证的属性,而身份证又有身份证号以及签发机关等属性,所以可以对成员变量先创建对象。
2.(面试)进程:正在执行的某个应用程序(里面可能有多个线程)
3.多种同步情况下的同步锁对象问题
{同步代码块
{同步方法{static静态方法:
{普通方法:
继承Thread开启多线程的步骤
1.创建子类继承Thread类 2.重写run()方法 3.创建子类对象 4.调用start()方法件系统
实现Runnable开启多线程的步骤 1.创建类实现Runnable接口 2.重写run()方法 3.创建实现类对象 4.创建线程对象并将实现类对象传入构造方法 5.调用线程对象的start()方法系统
多线程安全问题的产生原因 有多个线程、有共享数据、多个线程操作共享数据系统
解决多线程安全问题的方式有 同步代码块、 同步方法、 Lock锁
-----------------------------Day 7.5 lambda表达式----------------------------
1.Lambda表达式的注意事项:
1>使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
2>必须有上下文环境,才能推导出Lambda对应的接口
根据局部变量的赋值得知Lambda对应的接口
Runnable r = () -> System.out.println("Lambda表达式");
根据调用方法的参数得知Lambda对应的接口
new Thread(() -> System.out.println("Lambda表达式")).start();
2.Lambda表达式和匿名内部类的区别
所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口
使用限制不同
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
3.接口中默认方法的定义格式
格式:public default 返回值类型 方法名(参数列表) { }
范例:public default void show3() { }
接口中默认方法的注意事项
默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
public可以省略,default不能省略
4.接口中静态方法的定义格式
格式:public static 返回值类型 方法名(参数列表) { }
范例:public static void show() { }
接口中静态方法的注意事项
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略
5.接口中私有方法的注意事项
默认方法可以调用私有的静态方法和非静态方法
静态方法只能调用私有的静态方法
6.
组成Lambda表达式的三要素:
形式参数,箭头,代码块
Lambda表达式的格式:(参数列表)-> {一些代码}
Lambda表达式的省略规则:
1.(参数列表):括号中参数列表的数据类型,可以省略不写。
2.(参数列表):括号中的参数如果只有一个,那么类型和()都可以省略。
3.{一些代码}:如果{}中的代码只有一行,无论是否有返回值,都可以省略({},return,分号)
注意:要省略{},return,分号必须一起省略!!!!
小括号内参数的类型可以省略;(所以其肯定正确)
如果小括号内有且仅有一个参,则小括号可以省略;
如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
7.方法引用的格式:对象名::方法名
打印语句中System.out是对象名,print是方法名,所以方法引用写法是: System.out::println
8.接口的组成
常量
public static final
抽象方法
public abstract
默认方法(Java 8)
静态方法(Java 8)
私有方法(Java 9)
9.Lambda表达式的使用条件{接口中的抽象方法有且仅有一个
{有一个接口
------------------------------Day 7.9 mysql数据库------------------------------
1.数据库:用于存储和管理数据的仓库。
特点:
1. 持久化存储数据的。其实数据库就是一个文件系统
2. 方便存储和管理数据
3. 使用了统一的方式操作数据库
2. 卸载
1. 去mysql的安装目录找到my.ini文件
* 复制 datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
2. 卸载MySQL
3. 删除C:/ProgramData目录下的MySQL文件夹。
3.SQL通用语法
1. SQL 语句可以单行或多行书写,以分号结尾。
2. 可使用空格和缩进来增强语句的可读性。
3. MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写。
4. 3 种注释
* 单行注释: -- 注释内容 或 # 注释内容(mysql 特有)
* 多行注释: /* 注释 */
4.SQL分类!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1) DDL(Data Definition Language)数据定义语言
用来定义数据库对象:数据库,表,列等。
关键字:create, drop,alter 等
2) DML(Data Manipulation Language)数据操作语言
用来对数据库中表的数据进行增删改。
关键字:insert, delete, update 等
3) DQL(Data Query Language)数据查询语言
用来查询数据库中表的记录(数据)。
关键字:select, where 等
4) DCL(Data Control Language)数据控制语言(了解)
用来定义数据库的访问权限和安全级别,及创建用户。
关键字:GRANT, REVOKE 等
5.创建数据库:create database db1;(CRUD)
修改数据库;alter database db1 charater set gbk;
删除数据库;drop database db1;
查询数据库:show databases;
6.创建表:create table 表名(
列名 数据类型1,
列名 数据类型
); !!! 注意:最后一列,不需要加逗号(,)
复制表:create table 表名 like 被复制的表名;
查询表:show tables;查询表结构:* desc 表名;
修改表:1. 修改表名
alter table 表名 rename 新表名;
2. 修改表的字符集
alter table 表名 character set 字符集名称;
3. 添加一列!!!!!!!!!!
alter table 表名 add 列名 数据类型;
4. 修改列名称 类型
alter table 表名 change 列名 新列名 新数据类型;
alter table 表名 modify 列名新数据类型;(只能修改某列的数据类型)
5. 删除列
alter table 表名 drop 列名;
删除表:drop table 表名; drop table if exists 表名 ;
7.添加数据:insert into 表名(列名1,列名2,...) values(值1,值2,....);
删除数据:delete from 表名 where(条件);
修改数据:update 表名 set 列名1=值1,列名2=值2,...where(条件);(无from)
查询数据:select * from 表名;
添加数据注意:
1. 列名和值要一一对应。
2. 如果表名后,不定义列名,则默认给所有列添加值
insert into 表名 values(值1,值2,...值n);
3. 除了数字类型,其他类型需要使用引号(单双都可以)引起来
删除数据需注意:
1. 如果不加条件,则删除表中所有记录。
2. 如果要删除所有记录
1. delete from 表名;
-- 不推荐使用。有多少条记录就会执行多少次删除操作
2. TRUNCATE TABLE 表名;
-- 推荐使用,效率更高 先删除表,然后再创建一张一样的空表。
修改数据需注意:
1. 如果不加任何条件,则会将表中所有记录全部修改。
查询数据:
!!!注意:
null和任何数据计算都为null,可以使用ifnull(字段, 默认值)来解决问题
条件相关的知识
>,<,=,!=(<>),>=,<=
&&(and) , ||(or), !(not)
between and: 和>= and <=一样的效果; between and 小的必须放到前面
between 50 and 80:正确写法
between 80 and 50:错误写法
age <= 80 && age >= 50
in(集合) 简化 多个or的书写
null不可以使用=和!=来判断,应该用is或者is not来判断
like--->模糊查询
_:匹配一个
%:匹配多个
1.语法:
select
字段列表
from
表名列表
where
条件列表
group by
分组字段
having
分组之后的条件
order by
排序
limit
分页限定
2.基础查询
1.多个字段的查询
select 字段1,字段2,... from 表名;* 注意:如果查询所有字段,则可以使用*来替代字段列表。
2.去除重复;(一般去重查询只针对一个字段)
select distinct class FROM stu_score;
3.计算列(一般针对数字列(int或者double类型的列))
SELECT *,chinese+math+english AS 总分 FROM stu_score;
SELECT *,chinese+math+english 总分 FROM stu_score;(AS可以省略)
起别名:as也可以省略
* ifnull(表达式1,表达式2):null参与的运算,计算结果都为null
* 表达式1:哪个字段需要判断是否为null
* 如果该字段为null后的替换值。
select math 数学,chinese 语文,chinese+math+english 总分 FROM stu_score;
4. 多个OR的语句很麻烦,可以使用in这个简化书写
SELECT * FROM stu_score WHERE id = 1 OR id = 3 OR id = 5;
SELECT * FROM stu_score WHERE id IN(1,3,5);
数据类型:
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个字符
* zhangsan 8个字符 张三 2个字符
注!!VARCHAR后面必须加上小括号()指明长度而double后面的(4,1)添加不添加均可
7. 运算符
* > 、< 、<= 、>= 、= 、<>
* BETWEEN...AND
* IN( 集合)
* LIKE:模糊查询
* 占位符:
* _:单个任意字符
* %:多个任意字符
* IS NULL
* and 或 &&
* or 或 ||
* not 或 !
-- 查询年龄大于20岁
SELECT * FROM student WHERE age > 20;
SELECT * FROM student WHERE age >= 20;
-- 查询年龄等于20岁
SELECT * FROM student WHERE age = 20;
-- 查询年龄不等于20岁
SELECT * FROM student WHERE age != 20;
SELECT * FROM student WHERE age <> 20;
-- 查询年龄大于等于20 小于等于30
SELECT * FROM student WHERE age >= 20 && age <=30;
SELECT * FROM student WHERE age >= 20 AND age <=30;
SELECT * FROM student WHERE age BETWEEN 20 AND 30;
-- 查询年龄22岁,18岁,25岁的信息
SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25
SELECT * FROM student WHERE age IN (22,18,25);
-- 查询英语成绩为null
SELECT * FROM student WHERE english = NULL; -- 不对的。null值不能使用 = (!=) 判断
SELECT * FROM student WHERE english IS NULL;
-- 查询英语成绩不为null
SELECT * FROM student WHERE english IS NOT NULL;
-- 查询姓马的有哪些? like
SELECT * FROM student WHERE NAME LIKE '马%';
-- 查询姓名第二个字是化的人
SELECT * FROM student WHERE NAME LIKE "_化%";
-- 查询姓名是3个字的人
SELECT * FROM student WHERE NAME LIKE '___';
-- 查询姓名中包含德的人
SELECT * FROM student WHERE NAME LIKE '%德%';
-------------------------------Day 7.14 mysql-------------------------
1. DQL:查询语句
1. 排序查询 order by 排序字段1 排序方式1 ,排序字段2 排序方式2...
2. 聚合函数 将一列数据作为一个整体,进行纵向的计算。
3. 分组查询 group by 分组字段;
4. 分页查询 limit 开始的索引,每页查询的条数;
1.1排序查询:
语法:order by 子句
* order by 排序字段1 排序方式1 , 排序字段2 排序方式2...
* 排序方式:
* ASC:升序,默认的。
* DESC:降序。
* 注意:
* 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。
1.2聚合函数:将一列数据作为一个整体,进行纵向的计算。
1.count:计算个数
1.一般选择非空的列:主键
2.count(*)
2.max:计算最大值
3.min:计算最小值
4.sum:计算和
5.avg:计算平均值
注意:聚合函数的计算,排除null值。
解决方案:
1.选择不包含非空的列进行计算。
2.IFNULL函数
1.3分组查询
1.语法:group by 分组字段;
2.注意:
1.分组之后查询的字段:分组字段、聚合函数
2.where和having的区别:
1.where在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来。
2.where后不可以跟聚合函数,having可以进行聚合函数的判断。
-- 按照性别分组。分别查询男、女同学的平均分
select sex,avg(math) from student group by sex;
-- 按照性别分组。分别查询男、女同学的平均分,人数
select sex,avg(math),count(id) from student group by sex;
-- 按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组
select sex,avg(math),count(id) from student where math<70 group by sex;
-- 按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组,分组之后。人数要大于2个人
select sex,avg(math),count(id) from student where math<70 group by sex having count(id)>2;
1.4 分页查询
1. 语法:limit 开始的索引,每页查询的条数;
2. 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
-- 每页显示3条记录
SELECT * FROM student LIMIT 0,3; -- 第1页
SELECT * FROM student LIMIT 3,3; -- 第2页
3. limit 是一个MySQL"方言"
2.约束:
1. 主键约束:primary key
2. 非空约束:not null
3. 唯一约束:unique
4. 外键约束:foreign key
2.1 非空约束:not null,某一列的值不能为null
1. 创建表时添加约束
CREATE TABLE stu(
id INT,
NAME VARCHAR(20) NOT NULL -- name为非空
);
2. 创建表完后,添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
3. 删除name的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
2.2 唯一约束:unique,某一列的值不能重复
1. 注意:
* 唯一约束可以有NULL值,但是只能有一条记录为null
2. 在创建表时,添加唯一约束
CREATE TABLE stu(
id INT,
phone_number VARCHAR(20) UNIQUE -- 手机号
);
3. 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
4. 在表创建完后,添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
2.3:primary key
1. 注意:
1. 含义:非空且唯一
2. 一张表只能有一个字段为主键
3. 主键就是表中记录的唯一标识
2. 在创建表时,添加主键约束
create table stu(
id int primary key,-- 给id添加主键约束
name varchar(20)
);
3. 删除主键
-- 错误 alter table stu modify id int ;
ALTER TABLE stu DROP PRIMARY KEY;
4. 创建完表后,添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
5.自动增长:
1. 概念:如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长
2. 在创建表时,添加主键约束,并且完成主键自增长
create table stu(
id int primary key auto_increment,-- 给id添加主键约束
name varchar(20)
);
3. 删除自动增长
ALTER TABLE stu MODIFY id INT;
4. 添加自动增长
ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
2.4
* 外键约束:foreign key,让表于表产生关系,从而保证数据的正确性。
1. 在创建表时,可以添加外键
* 语法:
create table 表名(
....
外键列
constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
);
2. 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
3. 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
数据库的设计:
1. 实现关系:
1. 一对多(多对一):
* 如:部门和员工
* 实现方式:在多的一方建立外键,指向一的一方的主键。
2. 多对多:
* 如:学生和课程
* 实现方式:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
3. 一对一(了解):
* 如:人和身份证
* 实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键。
-----------------------------------Day 7.14 mysql----------------------
1.笛卡尔积:
* 有两个集合A,B .取这两个集合的所有组成情况。
* 要完成多表查询,需要消除无用的数据!!!!!!
2.多表查询的分类:
1. 内连接查询:从哪些表中查询数据
条件是什么
查询哪些字段
1. 隐式内连接:使用where条件消除无用数据
SELECT
t1.name, -- 员工表的姓名
t1.gender,-- 员工表的性别
t2.name -- 部门表的名称
FROM
emp t1,
dept t2
WHERE
t1.`dept_id` = t2.`id`;
2. 显式内连接:
* 语法: select 字段列表 from 表名1 [inner] join 表名2 on 条件
例如:* SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;
* SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;
2. 外连接查询:
1. 左外连接:
* 语法:select 字段列表 from 表1 left [outer] join 表2 on 条件;
* 查询的是左表所有数据以及其交集部分。
-- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称
SELECT t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
3. 子查询:
* 概念:查询中嵌套查询,称嵌套查询为子查询。
* 子查询不同情况
1. 子查询的结果是单行单列的:
-- 查询员工工资小于平均工资的人
SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);
2. 子查询的结果是多行单列的:
* 子查询可以作为条件,使用运算符in来判断
3. 子查询的结果是多行多列的:
* 子查询可以作为一张虚拟表参与查询
-- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
-- 子查询
SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id;
-- 普通内连接
SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11'
6.查询所有员工的select姓名及其直接上级的姓名,没有领导的员工也需要查询
SELECT
t1.`ename`,
t1.`mgr`,
t2.`ename`,
t2.`emp_id`
FROM
emp t1
LEFT JOIN
emp t2
ON
t2.`emp_id`=t1.`mgr`; |
|