网络编程和mysql

网络的相关概念
网络通信
1.概念:两台设备之间通过网络实现数据传输
2.网络通信:将数据通过网络从一台设备传输到另一台设备
3.java.net包下提供了一系列的类或接口,供程序员使用,完成网络通信
在这里插入图片描述
在这里插入图片描述
网络的相关概念
ip地址
1.概念:用于唯一标识网络中的每台计算机/主机
2.查看ip地址: ip config
3. ip地址的表示形式:点分十进制XX.XX.XX.XX4.每一个十进制数的范围:0~255
5. ip地址的组成=网络地址+主机地址,比如:192.168.16.69
6. iiPv6是互联网工程任务组设计的用于替代IPv4的下一代IP协议,其地址数量号称可以为全世界的每一粒沙子编上一分地址 。
7.由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
两个字节表示一个端口
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
InetAddress类
●相关方法
1.获取本机InetAddress对象getLocalHost
2.根据指定主机名/域名获取ip地址对象getByName
3.获取InetAddress对象的主机名getHostName
4.获取InetAddress对象的地址getHostAddress

package com.api;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * InetAddress的使用
 */

public class API_ {
    public static void main(String[] args) throws UnknownHostException {
//       获取本机的InetAddress对象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        //2.根据指定主机名获取InetAddress对象
        InetAddress byName = InetAddress.getByName("DESKTOP-6CV6H2R");
        System.out.println("host1 = " + byName);

//        根据域名返回InetAddress对象,比如www.baidu.com
        InetAddress host = InetAddress.getByName("www.baidu.com");
        System.out.println("host = " + host);

//        通过InetAddress对象,获取对应地址
        String hostAddress = host.getHostAddress();
        System.out.println("host对应的IP = " + hostAddress);

//        通过InetAddress对象,获取对应的主机名/或者是域名
        String hostName = host.getHostName();
        System.out.println("host对应的主机名/域名 = " + hostName);
    }
}

在这里插入图片描述
Socket
基本介绍
1.套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
2.通信的两端都要有Socket,是两台机器间通信的端点
3.网络通信其实就是Socket间的通信。
4.Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
5.一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
在这里插入图片描述
客户端和服务器通常情况下,是在不同主机的.
在这里插入图片描述
在这里插入图片描述
难点:要兼顾服务器端和客户端

package com.api;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 */
public class SockTcpServer {
    public static void main(String[] args) throws IOException {
//        在本机的9999端口监听,等待连接
//        细节,要求本机没有其他服务在监听9999
//        细节:这个ServerSocket 可以通过accept()返回多个Socket[多个客户端来连接服务器的并发]
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端,在9999端口监听,等待连接。。。。");
//        当没有客户端连接9999端口时,程序会 阻塞,等待连接
//        如果有客户端连接,会返回Socket对象,程序继续
        Socket  socket = serverSocket.accept();
        System.out.println("socket = " + socket.getClass());
//        通过 socket.getInputStream() 读取
//        客户端写入到数据通道的数据,显示
        InputStream inputStream = socket.getInputStream();
//        IO读取
        byte[] buf = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(buf)) != -1){
            System.out.println(new String(buf,0,readLen));
        }
        inputStream.close();
        socket.close();
        serverSocket.close();//关闭
    }
}
package com.api;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 客户端,发送“hello,server”给服务器
 */
public class SocketTcpClient {
    public static void main(String[] args) throws IOException {
        //     连接服务端(IP,端口)
//        连接本机的9999端口,连接成功,就返回Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("socket返回 = " + socket.getClass());
//        连接上后,生成Socket,通过socket.getOutputStream()
//        得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
//        通过输入流,写入到数据到 通道
        outputStream.write("hello,server".getBytes());
//        关闭流对象和socket,必须关闭
        outputStream.close();
        socket.close();
        System.out.println("客户端退出....");
    }
}

在这里插入图片描述
字节流

package com.api;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 服务器端
 */
public class SockTcpServer {
    public static void main(String[] args) throws IOException {
//        在本机的9999端口监听,等待连接
//        细节,要求本机没有其他服务在监听9999
//        细节:这个ServerSocket 可以通过accept()返回多个Socket[多个客户端来连接服务器的并发]
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端,在9999端口监听,等待连接。。。。");
//        当没有客户端连接9999端口时,程序会 阻塞,等待连接
//        如果有客户端连接,会返回Socket对象,程序继续
        Socket  socket = serverSocket.accept();
        System.out.println("socket = " + socket.getClass());
//        通过 socket.getInputStream() 读取
//        客户端写入到数据通道的数据,显示
        InputStream inputStream = socket.getInputStream();
//        IO读取
        byte[] buf = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(buf)) != -1){
            System.out.println(new String(buf,0,readLen));
        }
//        获取输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,client".getBytes());
//设置结束标记
        socket.shutdownOutput();
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();//关闭
    }
}
package com.api;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 客户端,发送“hello,server”给服务器
 */
public class SocketTcpClient {
    public static void main(String[] args) throws IOException {
        //     连接服务端(IP,端口)
//        连接本机的9999端口,连接成功,就返回Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("socket返回 = " + socket.getClass());
//        连接上后,生成Socket,通过socket.getOutputStream()
//        得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
//        通过输入流,写入到数据到 通道
        outputStream.write("hello,server".getBytes());
//        设置结束标记
        socket.shutdownOutput();
//        获取socket关联的输入流
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(buf)) != -1){
            System.out.println(new String(buf,0,readLen));
        }
//        关闭流对象和socket,必须关闭
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端退出....");
    }
}

在这里插入图片描述
字符流

package com.api;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 服务器端  使用字符流
 */
public class SockTcpServer {
    public static void main(String[] args) throws IOException {
//        在本机的9999端口监听,等待连接
//        细节,要求本机没有其他服务在监听9999
//        细节:这个ServerSocket 可以通过accept()返回多个Socket[多个客户端来连接服务器的并发]
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端,在9999端口监听,等待连接。。。。");
//        当没有客户端连接9999端口时,程序会 阻塞,等待连接
//        如果有客户端连接,会返回Socket对象,程序继续
        Socket  socket = serverSocket.accept();
        System.out.println("socket = " + socket.getClass());
//        通过 socket.getInputStream() 读取
//        客户端写入到数据通道的数据,显示
        InputStream inputStream = socket.getInputStream();
//        IO读取  使用字符流  使用了转换流,将 inpputStream 转成了字符流
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);
//        获取输出流
        OutputStream outputStream = socket.getOutputStream();
//        使用字符流的方式回送信息
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello,client,字符流!");
        bufferedWriter.newLine();//表示回复内容结束
        bufferedWriter.flush();//手动刷新
//设置结束标记
//        socket.shutdownOutput();
//        outputStream.close();
//        inputStream.close();
        bufferedWriter.close();
        bufferedReader.close();
        socket.close();
        serverSocket.close();//关闭
    }
}
package com.api;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 客户端,发送“hello,server”给服务器
 * 使用字符流
 */
public class SocketTcpClient {
    public static void main(String[] args) throws IOException {
        //     连接服务端(IP,端口)
//        连接本机的9999端口,连接成功,就返回Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("socket返回 = " + socket.getClass());
//        连接上后,生成Socket,通过socket.getOutputStream()
//        得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
//        通过输入流,写入到数据到 通道 使用字符流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello,server,字符流");
        bufferedWriter.newLine();//插入一个换行符,表示写入内容结束,要求对方使用readLine()读取
        bufferedWriter.flush();//如果使用的字符流,需要使用手动刷新,否则数据不会写入数据通道
//        设置结束标记
//        socket.shutdownOutput();
//        获取socket关联的输入流
        InputStream inputStream = socket.getInputStream();
//    使用字符流接收信息
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);

//        关闭流对象和socket,必须关闭
//        inputStream.close();
//        关闭外层流  后开的先关
        bufferedReader.close();
//        outputStream.close();
        bufferedWriter.close();
        socket.close();
        System.out.println("客户端退出....");
    }
}

在这里插入图片描述

package com.api;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 文件上传到服务器
 */
public class TCPFileUploadServer {
    public static void main(String[] args) throws IOException {
//服务端在本机监听8888端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务端在8888端口监听。。。。");
//        等待连接
        Socket socket = serverSocket.accept();

//        读取客户端发送的数据
//        通过Socket得到一个输入流
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//        读取数据
        byte[] bytes = StreamUtils.streamToByteArray(bis);
//        将得到的bytes数组,写入到指定的路径,就得到文件
        String destFilePath = "E:\\Java_study\\2.png";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bos.write(bytes);
        bos.close();

//        向客户端回复“收到图片”
//        通过socket 获取到输出流(字符)
        BufferedWriter Writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Writer.write("收到图片");
        Writer.flush();//把内容刷新到数据通道
        socket.shutdownOutput();//设置结束标记

        Writer.close();
        bis.close();
        socket.close();
        serverSocket.close();
    }
}
package com.api;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 */
public class TCPFileUploadClient {
    public static void main(String[] args) throws IOException {
//客户端连接服务器,得到Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
//        创建读取磁盘文件的输入流
        String filePath = "E:\\Java_study\\1.png";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));

//        bytes就是文件filePath对应的字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);

//       将socket获取到的输出流,将bytes数据发送给服务端
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道

//        设置结束的标志
        bis.close();
        socket.shutdownOutput();//写入数据的结束标志

//        ===========接收从服务器回复的消息
        InputStream inputStream = socket.getInputStream();
//        使用StreamUtils 的方法,直接将 inputStream 读取到的内容,转成字符串
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);

//       关闭相关流
        bos.close();
        socket.close();

    }
}
package com.api;

import java.io.*;

/**
 * @author
 * @version 1.0
 * 关于流的读写方法
 */
public class StreamUtils {
    /**
     * 功能:将输入流转换成byte[],即可以把文件的内容读入到byte[]
     * @param is
     * @return
     * @throws IOException
     */
    public static byte[] streamToByteArray(InputStream is) throws IOException {
//        创建一个输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];//字节数组
        int len;
        while ((len = is.read(b)) != -1){//循环读取
            bos.write(b,0,len);//把读取的数据,写入bos
        }
        byte[] array = bos.toByteArray();//r然后将bos转成字节数组
        bos.close();
        return array;
    }

    /**
     * 功能:将InputStream 转成String
     * @param is
     * @return
     */
    public static String streamToString(InputStream is) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
        StringBuilder builder = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null){//当读取到空时,就结束
            builder.append(line + "\r\n");
        }
        return builder.toString();
    }
}

在这里插入图片描述
说明:
(1) Listening表示某个端口在监听
(2)如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息.
(3)可以输入ctrl +c退出指令

TCP网络通信编程
TCP网络通讯不为人知的密码
1.当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的,是随机的
2.示意图
3.程序验证
在这里插入图片描述
UDP网络通信编程[了解]
●基本介绍
1.类 DatagramSocket和 DatagramPacket [数据包/数据报] 实现了基于UDP协议网络程序。
2.UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
3. DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
4.UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。
在这里插入图片描述
在这里插入图片描述

package com.api;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * @author
 * @version 1.0
 * UDP接收端
 */
public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
//    创建一个DatagramSocket 对象,准备在9999接收数据
        DatagramSocket socket = new DatagramSocket(9999);
//        构建一个DatagramPacket 对象,准备接收数据
//        UDP协议,最大为64K
        byte[] buf = new byte[64 * 1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);

//        准备接收数据,调用接收方法,将通过网络传输的DatagramPacket对象
//        填充到 packet 对象
//        当有数据包发送到 本机的9999端口时,就会接收到数据
//        如果没有数据包发送到 本机的 9999 端口,就会阻塞等待
        System.out.println("接收端A 等待接收数据..");
        socket.receive(packet);

//        可以把packet 进行拆包,取出数据,并显示
        int length = packet.getLength();//实际接收到数据的长度
        byte[] data = packet.getData();//接收数据

        String s = new String(data,0,length);
        System.out.println(s);

//        =========回复信息=======
        byte[] datasend = "好的,明天见~~~".getBytes();
        DatagramPacket packet1 =
                new DatagramPacket(datasend, datasend.length, InetAddress.getByName("202.115.166.168"), 9998);
        socket.send(packet1);

//        关闭资源
        socket.close();
        System.out.println("A 端退出!!!!");
    }
}
package com.api;

import java.io.IOException;
import java.net.*;

/**
 * @author
 * @version 1.0
 * 发送端B===》也可以是接收端
 */
public class UDPSenderB {
    public static void main(String[] args) throws IOException {
//        创建 DatagramSocket 对象,准备发送和接收数据
        DatagramSocket socket = new DatagramSocket(9998);
//        将需要发送的数据,封装到DatagramPacket对象
        byte[] data = "hello,明天吃火锅~~".getBytes();
//        封装 DatagramPacket 对象,data 内容字节数组,data.length,主机(IP),端口
        DatagramPacket packet =
                new DatagramPacket(data,data.length, InetAddress.getByName("202.115.166.168"),9999);
        socket.send(packet);

//        =============接收回复信息==========
        byte[] buf = new byte[64 * 1024];
        DatagramPacket packet1 = new DatagramPacket(buf, buf.length);
        socket.receive(packet1);
        int len = packet1.getLength();
        byte[] datarec = packet1.getData();
        String s = new String(datarec,0,len);
        System.out.println(s);

        socket.close();
        System.out.println("B 端退出!!!!");

    }
}

在这里插入图片描述
在这里插入图片描述
服务端

package com.api;


import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author
 * @version 1.0
 * 先写文件下载的服务端
 */
public class HomeWorkServer {
    public static void main(String[] args) throws IOException {
//   创建 9999 端口
        ServerSocket serverSocket = new ServerSocket(9999);
//        等待客户端连接
        Socket socket = serverSocket.accept();
//        读取客户端发送的要下载的文件名
        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int len = 0;
        String downLoadFileName = "";
        while ((len = inputStream.read(b)) != -1){
            downLoadFileName += new String(b,0,len);
        }
        System.out.println("客户端希望下载的文件名:" + downLoadFileName);

        //服务器上有两个文件,无名.mp3高山流水.mp3
//如果客户下载的是 高山流水我们就返回该文件,否则一律返回无名.mp3
        String resFileName = "";

        if ("高山流水".equals(downLoadFileName)){
            resFileName = "E:\\Java_study\\高山流水.mp3";
        }else {
            resFileName = "E:\\Java_study\\无名.mp3";
        }
//        创建一个输入流,读取文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(resFileName));

//        使用工具类StreamUtils,读取文件到一个字节数组
        byte[] bytes =StreamUtils.streamToByteArray(bis);
//        得到Socket关联的输出流
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//        写入到数据通道,返回给客户端
        bos.write(bytes);
        socket.shutdownOutput();
//        关闭相关资源
        bos.close();
        bis.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务器端退出、、、、");
    }
}

客户端

package com.api;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author
 * @version 1.0
 * 客户端
 */
public class HomeWorkClient {
    public static void main(String[] args) throws IOException {
//        接收用户输入,指定下载的文件名
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入下载的文件名:");
        String downloadFileName = scanner.next();
//        客户端连接服务器,准备发送
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
//        获取和Socket关联的输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(downloadFileName.getBytes());
//        设置写入结束标志
        socket.shutdownOutput();
//        读取服务端返回的文件(字节数据)
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] buf = StreamUtils.streamToByteArray(bis);
        String filePath = "E:\\Java_study\\" + downloadFileName + "1" + ".mp3";
//        得到一个输出流,准备将bytes写入到磁盘文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
        bos.write(buf);

        bos.close();
        bis.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端下载完毕退出。。。。。。。");
    }
}

工具类

package com.api;

import java.io.*;

/**
 * @author
 * @version 1.0
 * 关于流的读写方法
 */
public class StreamUtils {
    /**
     * 功能:将输入流转换成byte[],即可以把文件的内容读入到byte[]
     * @param is
     * @return
     * @throws IOException
     */
    public static byte[] streamToByteArray(InputStream is) throws IOException {
//        创建一个输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];//字节数组
        int len;
        while ((len = is.read(b)) != -1){//循环读取
            bos.write(b,0,len);//把读取的数据,写入bos
        }
        byte[] array = bos.toByteArray();//r然后将bos转成字节数组
        bos.close();
        return array;
    }

    /**
     * 功能:将InputStream 转成String
     * @param is
     * @return
     */
    public static String streamToString(InputStream is) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
        StringBuilder builder = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null){//当读取到空时,就结束
            builder.append(line + "\r\n");
        }
        return builder.toString();
    }
}

反射机制
万物皆对象

package com;

/**
 * @author
 * @version 1.0
 */
public class Cat {
    private String name = "招财猫";
    public void hi(){
        System.out.println("黑黑,澳毛" +name);
    }

    public void cry(){
        System.out.println("喵喵叫" + name);
    }
}

package com;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author
 * @version 1.0
 */
public class RefleationQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//        Cat cat = new Cat();
//        cat.hi();  调用cry方法,传统方式需要修改源码,但是反射机制不需要修改源码,
//        可以通过修改配置文件实现

//        1.使用Properties类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("E:\\Java_study\\src\\com\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();
        System.out.println("classfullpath= " + classfullpath);
        System.out.println("method= " + methodName);

//        2.创建对象,传统的方法行不通 =》 反射机制
//        new classfullpath();
//        3.使用反射机制解决
//        (1)加载类  返回一个Class类型的对象
        Class cls = Class.forName(classfullpath);
//        (2)通过cls 得到加载的类 com.Cat 的对象实例
        Object o = /*(Cat)*/cls.newInstance();//也可以不转
        System.out.println("o 的运行类型 = " + o.getClass());
//        (3) 通过 cls 得到加载的类  com.Cat 的对象的 methodName 的方法对象
//        即在反射中,可以将方法视为对象(万物皆对象)
        Method method1 = cls.getMethod(methodName);
//        (4)通过method1 调用方法:即通过方法对象来实现调用方法
        System.out.println("========================");
        method1.invoke(o);//传统方法 对象.方法(),反射机制 方法.invoke(对象)
    }
}

反射机制
Java Reflection
1.反射机制允许程序在执行期借助于Reflection
API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到
2.加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射
在这里插入图片描述
反射机制
Java反射机制可以完成
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时得到任意一个类所具有的成员变量和方法
4.在运行时调用任意一个对象的成员变量和方法
5.生成动态代理

反射机制
反射相关的主要类:
反射机制
反射相关的主要类:

  1. java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
  2. java.lang.reflect.Method:代表类的方法, Method对象表示某个类的方法
  3. java.lang.reflect.Field: 代表类的成员变量, Field对象表示某个类的成员变量
  4. java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
    这些类在java.lang.reflection
package com;

import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author
 * @version 1.0
 */
public class RefleationQuestion {
    public static void main(String[] args) throws Exception {
//        Cat cat = new Cat();
//        cat.hi();  调用cry方法,传统方式需要修改源码,但是反射机制不需要修改源码,
//        可以通过修改配置文件实现

//        1.使用Properties类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("E:\\Java_study\\src\\com\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();
        System.out.println("classfullpath= " + classfullpath);
        System.out.println("method= " + methodName);

//        2.创建对象,传统的方法行不通 =》 反射机制
//        new classfullpath();
//        3.使用反射机制解决
//        (1)加载类  返回一个Class类型的对象
        Class cls = Class.forName(classfullpath);
//        (2)通过cls 得到加载的类 com.Cat 的对象实例
        Object o = /*(Cat)*/cls.newInstance();//也可以不转
        System.out.println("o 的运行类型 = " + o.getClass());
//        (3) 通过 cls 得到加载的类  com.Cat 的对象的 methodName 的方法对象
//        即在反射中,可以将方法视为对象(万物皆对象)
        Method method1 = cls.getMethod(methodName);
//        (4)通过method1 调用方法:即通过方法对象来实现调用方法
        System.out.println("========================");
        method1.invoke(o);//传统方法 对象.方法(),反射机制 方法.invoke(对象)

//        java.lang.reflect.Field:代表类的成员变量,Field 对象表示某个类的成员变量
//        取得name字段
//        getField 不能得到私有的属性
        Field nameField = cls.getField("age");
        System.out.println(nameField.get(o));

//        java.lang.reflect.Constructor: 代表类的构造方法,Constructor对象表示构造器
        Constructor constructor = cls.getConstructor();//()中可以指定构造器参数类型,返回无参构造器
        System.out.println(constructor);

        Constructor constructor1 = cls.getConstructor(String.class);//String.class 为形参类别的Class
        System.out.println(constructor1);
    }
}

反射机制
·反射优点和缺点
1.优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
2.缺点:使用反射基本是解释执行,对执行速度有影响.

package com;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author
 * @version 1.0
 */
public class Reflection02 {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        m1();
        m2();
        m3();
    }

//    传统方法调用hi
    public static void m1(){
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000; i++) {
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("传统方法调用hi耗时为:" + (end - start));
    }

//    使用反射机制
public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class aClass = Class.forName("com.Cat");
    Object o = aClass.newInstance();
    Method hi = aClass.getMethod("hi");
    long start = System.currentTimeMillis();
    for (int i = 0; i < 900000; i++) {
        hi.invoke(o);
    }
    long end = System.currentTimeMillis();
    System.out.println("反射机制调用hi耗时为:" + (end - start));
}

//反射优化 + 关闭访问检查
    public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        hi.setAccessible(true);//在反射调用方法时,取消访问检测
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000; i++) {
            hi.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("优化后的反射调用时长:" + (end - start));
    }

}

在这里插入图片描述
Class类
●基本介绍:
1.Class也是类,因此也继承Object类
2. Class类对象不是new出来的,而是系统创建的
3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
4.每个类的实例都会记得自己是由哪个Class 实例所生成
5.通过Class对象可以完整地得到一个类的完整结构,通过一系列API
6. Class对象是存放在堆的
7.类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法代码,变量名,方法名,访问权限等等)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com;

/**
 * @author
 * @version 1.0
 */
public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException {
//        传统方法
        /* ClassLoader
         public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }
         */
//        Cat cat = new Cat();

//        反射方式,不注销就拿不到是因为上面 Cat cat = new Cat();已经加载; loadclass,类只加载一次
/*  ClassLoad类,任然通过 ClassLoader 类加载Cat 类的Class 对象
 public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }
 */
        Class cls = Class.forName("com.Cat");

        Class cls1 = Class.forName( "com.cat" );
//3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
        Class cls2= Class.forName( "com.cat" );
        System.out.println(cls1.hashCode());
        System.out.println(cls2.hashCode());

    }
}

在这里插入图片描述

package com;

import java.lang.reflect.Field;

/**
 * @author
 * @version 1.0
 */
public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String classfullpath = "com.Car";
//        获取到Car类对应的Class对象
//        <?>表示不确定的Java类型
        Class<?> aClass = Class.forName("com.Car");
//        输出aClass
        System.out.println(aClass);//显示aClass对象,是哪个类的Class对象,com.Car
        System.out.println(aClass.getClass());//运行类型
//        得到包名
        System.out.println(aClass.getPackage().getName());
//        得到全类名
        System.out.println(aClass.getName());
//        通过aClass创建对象实例
        Car o = (Car)aClass.newInstance();
        System.out.println(o);
//        通过反射获取属性
        Field brand = aClass.getField("brand");//无法获取私有属性
        System.out.println(brand.get(o));
//        设置属性值
        brand.set(o,"奔驰");
        System.out.println(brand.get(o));
//        遍历得到所有的属性
        Field[] fields = aClass.getFields();
        for(Field f: fields){
            System.out.println(f);
        }
    }
}

获取Class类对象

1.前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException,
实例: Class cls1 =Class.forName( “java.lang.Cat””);
应用场景:多用于配置文件,读取类全路径,加载类.
2.前提:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能
最高实例: Class cls2 = Cat.class;
应用场景:多用于参数传递,比如通过反射得到对应构造器对象.
在这里插入图片描述
3.前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象,实例:
Class clazz=对象.getClass0);
应用场景:通过创建好的对象,获取Class对象
.4、其他方式
ClassLoader cl =对象.getClass().getClassLoader();
Class clazz4 = cl.loadClass(“类的全类名”);
5、基本数据(int, char,boolean,float,double,byte,long,short)按如下方式得到Class类对象
Class cls =基本数据类型.class
6.基本数据类型对应的包装类,可以通过.type得到Class类对象
Class cls =包装类.TYPE

package com;

/**
 * @author
 * @version 1.0
 * 不同获取Class类对象的方式
 */
public class GetClass {
    public static void main(String[] args) throws ClassNotFoundException {
        //    1.forName
        String classfullpath = "com.Car";
        Class<?> cls1 = Class.forName(classfullpath);
        System.out.println(cls1);

//        2.类名.class,应用场景:用于参数传递
        Class cls2 = Car.class;
        System.out.println(cls2);

//        3.运行类型  对象.getClass(),已经知道有对象实例
        Car car = new Car();
        Class cls3 = car.getClass();
        System.out.println(cls3);
//       4.通过类加载器(4种)来获取类的Class对象
//        (1)先得到类加载器 car
        ClassLoader classLoader = car.getClass().getClassLoader();
//        (2)通过类加载器得到Class对象
        Class<?> cls4 = classLoader.loadClass(classfullpath);
        System.out.println(cls4);
//        cls1-4都是同一个class类
        System.out.println(cls1.hashCode());
        System.out.println(cls2.hashCode());
        System.out.println(cls3.hashCode());
        System.out.println(cls4.hashCode());

//        基本数据类型
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        System.out.println(integerClass);

//        基本数据类型的包装类
        Class<Integer> type = Integer.TYPE;
        Class<Character> type1 = Character.TYPE;
        System.out.println(type);

//        是同一个
        System.out.println(integerClass.hashCode());
        System.out.println(type.hashCode());
    }

}

在这里插入图片描述

package com;

import java.io.Serializable;

/**
 * @author
 * @version 1.0
 * 哪些类有class对象
 */
public class AllTypeClass {
    public static void main(String[] args) {
        Class<String> stringClass = String.class;//外部类
        Class<Serializable> serializableClass = Serializable.class;//接口
        Class<Integer[]> aClass = Integer[].class;//数组
        Class<float[][]> aClass1 = float[][].class;//二维数组
        Class<Deprecated> deprecatedClass = Deprecated.class;//注解
//        枚举
        Class<Thread.State> stateClass = Thread.State.class;
        Class<Long> longClass = long.class;//基本数据类型
        Class<Void> voidClass = void.class;//void数据类型
        Class<Class> classClass = Class.class;//Class类
    }
}

类加载
●基本说明
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
1.静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
2动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性

●类加载时机
1.当创建对象时(new)—静态加载
2.当子类被加载时,父类也加载–静态加载
3.调用类中的静态成员时–静态加载
4.通过反射===动态加载
Class.forName(“com.test.Cat”);
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

package com;

import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author
 * @version 1.0
 * 如何通过反射获取类的结构信息
 */
public class ReflectionUtils {
    public static void main(String[] args) {

    }

    //    第一组 方法 API
    @Test
    public void api_02() throws ClassNotFoundException {
//   得到Class对象
        Class<?> personCls = Class.forName("com.Person");
//        所有public修饰的属性(包括本类和父类)
//        获取本类所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println("本类中所有属性=" + field + "该属性的修饰符值= "
                    + field.getModifiers() + "该属性的类型= " + field.getType());
        }
    }



//    第一组 方法 API
    @Test
    public void api_01() throws ClassNotFoundException {
//   得到Class对象
        Class<?> personCls = Class.forName("com.Person");
//        全类名
        System.out.println(personCls.getName());
//        简单类名
        System.out.println(personCls.getSimpleName());
//        所有public修饰的属性(包括本类和父类)
        Field[] fields = personCls.getFields();
        for (Field field:fields){
            System.out.println("本类及父类的属性 = " + field.getName());
        }
//        获取本类所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field field:declaredFields){
            System.out.println("本类中所有属性=" + field);
        }
//        获取本类和父类的public修饰的方法
        Method[] methods = personCls.getMethods();
        for (Method method1 : methods){
            System.out.println("本类和父类的方法=" + method1.getName());
        }
//        获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method decl : declaredMethods){
            System.out.println("本类中所有方法= " + decl.getName());
        }
//    getConstructors:获取所有public修饰的构造器,包含本类以及父类的
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor constructor:constructors){
            System.out.println("本类及父类的构造器= " + constructor);
        }
//    getDeclaredConstructors:获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor constructor: declaredConstructors){
            System.out.println("本类所有的构造器= " + constructor.getName());
        }
//    getPackage : 以Package形式返回包信息
        System.out.println(personCls.getPackage());
//    getSuperClass:以Class形式返回父类信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println(superclass);
//    getInterfaces:以Class[]形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class in : interfaces){
            System.out.println("接口信息= " + in.getName());
        }
//    getAnnotations:以Annotation[]形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations){
            System.out.println("注解信息:" + annotation);
        }
    }
}

class A{
    public String hobby;

    public A() {
    }

    public A(String hobby) {
        this.hobby = hobby;
    }

    public void hi(){

    }
}

interface IA{}

interface IB{}

@Deprecated
class Person extends A implements IA,IB{
//    属性
    public String name;
    protected int age;
    String job;
    private double sal;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    private Person(String name,int age){

    }

    //    方法
    public void m1(){

    }
    protected void m2(){

    }

    void m3(){

    }
    private void m4(){

    }
}

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

package com;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author
 * @version 1.0
 */
public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//        现获取到User类的Class 对象
        Class<?> userClass = Class.forName("com.User");
//        通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
//        通过public 的有参构造器创建实例
        /*
         constructor 对象就是
         public User(String name){
                this.name = name;
         }
         */
//        先得到对应的构造器
        Constructor<?> constructor = userClass.getConstructor(String.class);
//       再创建实例,并传入实参
        Object lili = constructor.newInstance("lili");
        System.out.println("lili = " + lili);
//        通过public 的无参构造器创建实例
//        得到private的构造器对象
        Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
//        创建实例
        declaredConstructor.setAccessible(true);//爆破【暴力破解】,使用反射可以访问private构造器/私有方法、私有属性,反射面前,一切都是纸老虎
        Object zhangsan = declaredConstructor.newInstance(100, "zhangsan");
        System.out.println(zhangsan);


    }
}

class User{
    private int age = 10;
    private String name = "lili";

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    private User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
package com;

import java.lang.reflect.Field;

/**
 * @author
 * @version 1.0
 */
public class refection_ {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//     得到Student对应的Class对象
        Class<?> stuClass = Class.forName("com.Student");
//        创建对象
        Object o = stuClass.newInstance();//o 的运行类型就是Student
        System.out.println(o.getClass());//Student
//        使用反射得到age 属性对象
        Field age = stuClass.getField("age");
        age.set(o,88);
        System.out.println(o);
        System.out.println(age.get(o));//返回age属性的值

//        使用反射操作name属性
        Field name = stuClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o,"老安徽00");
        System.out.println(name.get(o));
        name.set(null,"lili");//因为name是static属性,因此 o 也可以写成null
        System.out.println(name.get(o));
        System.out.println(name.get(null));//写成null需要要求name是static的
    }
}

class Student{
    public int age;
    private static String name;

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
}

在这里插入图片描述

package com;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author
 * @version 1.0
 */
public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//   得到Boss类对应的Class对象
        Class<?> bossClass = Class.forName("com.Boss");
//        创建对象
        Object o = bossClass.newInstance();
//        调用public 的hi 方法
//        Method hi = bossClass.getMethod("hi",String.class);
        Method hi1 = bossClass.getDeclaredMethod("hi", String.class);
//        调用hi方法
        hi1.invoke(o,"理论");
//      调用 private static 方法
//        得到say 方法对象
        Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
//        方法是私有的,要进行爆破
        say.setAccessible(true);
       System.out.println(say.invoke(o,12,"hfej",'o'));
//      say方法是static的,可以调用方式
        System.out.println(say.invoke(null,1,"憨憨",'女'));
//     在反射中,如果方法有返回值,统一返回Object。但是他的运行类型和方法定义的返回类型值一样
        Object ii = say.invoke(null, 200, "fe", '男');
        System.out.println("ii 的运行类型= " + ii.getClass());//String
    }
}

class Boss{
    public int age;
    private static String name;

    public Boss(){
    }

    private static String say(int n, String s,char c){
        return n + " " + s + " " + c;
    }

    public void hi(String s){
        System.out.println("hi " + s);
    }
}
package com;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author
 * @version 1.0
 *
 */
public class HomeWork {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
//        得到PrivateTest对应的Class对象
        Class<PrivateTest> privateTestClass = PrivateTest.class;
//        创建对象实例
        PrivateTest privateTest = privateTestClass.newInstance();
//        得到name属性对象
        Field name = privateTestClass.getDeclaredField("name");
//        爆破
        name.setAccessible(true);
        name.set(privateTest,"fjej");
//        得到getName方法对象
        Method getName = privateTestClass.getMethod("getName");
//        因为是pubulic,直接调用
        Object invoke = getName.invoke(privateTest);
        System.out.println("name = " +invoke);
    }
}
class PrivateTest{
    private String name = "fekg";

    public PrivateTest() {
    }

    public PrivateTest(String name) {
        this.name = name;
    }

    public String getName(){
        return name;
    }
}

package com;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author
 * @version 1.0
 *
 */
public class HomeWork {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
        Class<?> fileCls = Class.forName("java.io.File");
//        得到构造器
        Constructor<?>[] declaredConstructors = fileCls.getDeclaredConstructors();;
        for (Constructor declCon : declaredConstructors){
            System.out.println(declCon);
        }
//        指定得到 public java.io.File(java.lang.String)
        Constructor<?> constructor = fileCls.getConstructor(String.class);
        String fileOPath = "E:\\Java_study\\mynew.txt";
        Object file = constructor.newInstance(fileOPath);//创建File对象
//        得到createNewFile 的方法对象
        Method createNewFile = fileCls.getMethod("createNewFile");
        createNewFile.invoke(file);
        System.out.println(file.getClass());
        System.out.println("创建文件成功 " + fileOPath);

    }
}

**

数据库mysql

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

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

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

create table t06(
	num1 float,
	num2 double,
	num3 decimal(30,20)
);
insert into t06 values(88.264124879721631211,98.264124879721631211,108.2645985254124879721631211);

select * from t06;

在这里插入图片描述
gbk编码是两个字节表示一个编码,所以要除以2.
在这里插入图片描述
Mysql常用数据类型
●字符串使用细节
1.细节
char(4)//这个4表示字符数(最大255),不是字节数,不管是中文还是字母都是放四个,按字符计算.
varchar(4)//这个4表示字符数,不管是字母还是中文都以定义好的表的编码来存放数据. gbk 2*4
不管是中文还是英文字母,都是最多存放4个,是按照字符来存放的.
char(4)和 varchar(4)这个4表示的是字符,而不是字节
2.细节2
char(4)是定长(固定的大小),就是说,即使你插入’aa’,也会占用分配的4个字符.
varchar(4)是变长,就是说,如果你插入了’aa’,实际占用空间大小并不是4个字符,而是按照实际占用空间来分配(varchar本身还需要占用1-3个字节来记录存放内容长度) L(实际占用的字节大小) + (1-3)个字节
3.细节3
什么时候使用char,什么时候使用varchar
1.如果数据是定长,推荐使用char,比如md5的密码,邮编,手机号,身份证号码等. char(32)
2.如果一个字段的长度是不确定,我们使用varchar,比如留言,文章
查询速度:char > varchar
在这里插入图片描述
#如果varchar不够用,可以考试使用mediumtext或者longtext,
#如果想简单点,可以使用直接使用text
在这里插入图片描述
create table t14(
birthday DATE,
job_time datetime,
login_time timestamp not null default current_timestamp on update current_timestamp
);
use dxl_db01;
select * from t14;
insert into t14 (birthday, job_time)
values (‘2011-11-11’,‘2022-11-11 10:12:15’)

use dxl_db01;
create table `emp`(
		id INT,
		`name` varchar(32),
		sex char(1),
		birthday date,
		entry_date datetime,
		job varchar(32),
		salary double,
		`resume` text)charset utf8 collate utf8_bin engine innodb;
)

--添加---
insert into `emp`
		values (100,'小样','男','2000-11-11','2020-11-23 4:5:6','写作',3000,
		'写出好的作品');
		
select * from `emp`;

在这里插入图片描述

use dxl_db01;
#修改表的操作练习
--员工表emp的上增加一个image列,varchar类型(要求在resume后面)。
alter table emp 
		add image varchar(32) not null default ''
		after resume
		
desc emp #显示表结构,可以查看表的所有列

#修改job列,使长度为60
alter table emp 
	modify job varchar(60) not null default ''
	
-- 	删除sex
alter table emp 
		drop sex
		
-- 		修改表名
rename table emp to employee

desc employee

-- 修改表的字符集为utf8
alter table employee character set utf8
-- 列名name修改为user_name

alter table employee change name user_name varchar(32) not null default ''

在这里插入图片描述
在这里插入图片描述
use dxl_db01;
create table goods(
id int,
goods_name varchar(10),
price double);
– 添加数据
insert into goods (id ,goods_name, price)
values (10,‘华为手机’,2000)

lnsert语句细节说明

1.插入的数据应与字段的数据类型相同。
比如把’abc’添加到int类型会错误
2.数据的长度应在列的规定范围内,例如:不能将一个长度为80的字符串加入到长度为40的列中。
3.在values中列出的数据位置必须与被加入的列的排列位置相对应。
4.字符和日期型数据应包含在单引号中。
5.列可以插入空值[前提是该字段允许为空],insert into table value(null)
6. insert into tab_name(列名…)values 0.0.(形式添加多条记录
7.如果是给表中的所有字段添加数据,可以不写前面的字段名称
8.默认值的使用,当不给某个字段值时,如果有默认值就会添加,否则报错
–如果某个列没有指定not null ,那么当添加数据时,没有给定值,则会默认给null–如果我们希望指定某个列的默认值,可以在创建表时指定
在这里插入图片描述
在这里插入图片描述

use dxl_db01;
-- 1.将所有员工薪水修改为5000元。[如果没有带where 条件,会修改所有的记录,因此要小心
update employee set salary = 5000

update employee 
	set salary = 3000
	where user_name  = '小样'
	
insert into employee 
	values(200,'老妖怪','1984-12-2','1548-2-6 10:12:1','垂腿的',6000,'给大王捶腿','d:\a.jpg');
	
update employee 
	set salary = salary + 1000
	where user_name  = '老妖怪'
	
-- 	可以修改多个列
update employee 
	set salary = salary + 1000,job = '出主意的'
	where user_name = '老妖怪'
	
select * from employee;

在这里插入图片描述

use dxl_db01;
-- 删除表中名称为‘老妖怪’的记录
delete from employee 
	where user_name = '老妖怪';


insert into employee 
	values(200,'老妖怪','1984-12-2','1548-2-6 10:12:1','垂腿的',6000,'给大王捶腿','d:\a.jpg');
	
-- 删除表中全部数据
-- Delete语句不能删除某一列的值(可使用update设为null或者''
update employee set job = '' where user_name = '老妖怪';

delete from employee 


select * from employee 

-- 删除这个表
drop table employee ;

use dxl_db01
create table student(
	id INT NOT NULL DEFAULT 1,
	NAME VARCHAR(20) NOT NULL DEFAULT '', 
	chinese FLOAT NOT NULL DEFAULT 0.0, 
	english FLOAT NOT NULL DEFAULT 0.0, 
	math FLOAT NOT NULL DEFAULT 0.0
);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(1,'优于',89,78,90);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(2,'张飞',67,98,56);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(3,'宋江',87,78,77);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(4,'关羽',88,98,90);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(5,'赵云',82,84,67);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(6,'欧阳锋',55,85,45);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(7,'黄蓉',75,65,30);
INSERT INTO student(id,NAME,chinese,english,math) VALUES(8,'韩信',45,65,99);
SELECT * FROM student;

select `name`,english from student ;

-- --过滤表中重复数据distinat
select distinct english from student ;

-- --要查询的记录,每个字段都相同,才会去重
select distinct `name`,english from student 

在这里插入图片描述

use dxl_db01
select `name`,(chinese + english + math) from student; 

select `name`,(chinese + english + math + 10) from student;

select `name`,(chinese+english+math+10) as total_score from student ;

select `name` as '名字' ,(chinese+english+math+10) as total_score 
   from student ;

在这里插入图片描述

use dxl_db01
select * from student
    where `name` = '赵云'
    
select * from  student 
	where english > 90
	
select * from  student 
	where (chinese+english+math) >200
	
select *from student 
	where math > 60 and id > 4
	
select * from student 
	where english > chinese
	
select * from student 
	where (chinese+english+math) > 200 and 
	math < chinese and `name` like '张%'
	
select * from student 
	where english >= 80 and english <= 90

-- 	between and 是闭区间
select * from student 
	where english between  80 and 90
	
select * from student 
	where math = 89 or math = 90 or math = 91
	
select * from student 
	where math in (89,90,91)
	
select * from student 
	where `name` like '韩%'
	
select * from student 
	where math>80 and chinese > 80

在这里插入图片描述

use dxl_db01

select * from student 
	order by math;
	
select * from student 
	order by math desc;
	
select `name`,(chinese + english +math) as total_socre from student
	order by total_socre desc ;
	
select * from student 
	where `name` like '韩%'
	order by math 
	
select `name`,(chinese + english + math) as total_score from student 
	where `name` like '韩%'
	order by total_score
	
select `name`,(chinese + english + math) as total_score from student 
	where `name` like '韩%'
	order by (chinese + english + math)

在这里插入图片描述
– count()和count(列)的|区别
–解释: count(
)返回满足条件的记录的行数
– count(列):统计满足条件的某列有多少个,但是会排除为null
在这里插入图片描述
对多列求和不能少了逗号
在这里插入图片描述
在这里插入图片描述

use dxl_db01

select count(*) from student  

select count(*) from student 
	where math >90

select count(*) from student 
	where (english+chinese+math) > 250
	
create table t15(
`name` varchar(15));

insert into t15 values ('tom');
insert into t15 values ('jack');
insert into t15 values ('mary');
insert into t15 values ('lili');
insert into t15 values (null);

select * from t15
select count(*) from t15; 

select count(`name`) from t15; 

select sum(math) from student  

select sum(math) as math_total_score, sum(english),sum(chinese) from student 

select sum(math + chinese+english) from student 

select sum(chinese)/count(*) from student  

select avg(math) from student  

select avg(math+chinese+english) from student

select max(math+english+chinese),min(math+english+chinese) from student;

在这里插入图片描述

CREATE TABLE dept( /*部门表*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, 
dname VARCHAR(20) NOT NULL DEFAULT "", 
loc VARCHAR(13) NOT NULL DEFAULT ""
);

INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK'), 
(20, 'RESEARCH', 'DALLAS'), 
(30, 'SALES', 'CHICAGO'), 
(40, 'OPERATIONS', 'BOSTON');
SELECT * FROM dept;

-- 员工表
CREATE TABLE emp
(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/
ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/
mgr MEDIUMINT UNSIGNED ,/*上级编号*/
hiredate DATE NOT NULL,/*入职时间*/
sal DECIMAL(7,2) NOT NULL,/*薪水*/
comm DECIMAL(7,2) ,/*红利 奖金*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
);

-- 添加测试数据
INSERT INTO emp
	VALUES(7369, 'SMITH', 'CLERK', 7902, '1990-12-17', 800.00,NULL , 20),
	(7499, 'ALLEN', 'SALESMAN', 7698, '1991-2-20', 1600.00, 300.00, 30), 
	(7521, 'WARD', 'SALESMAN', 7698, '1991-2-22', 1250.00, 500.00, 30),
	(7566, 'JONES', 'MANAGER', 7839, '1991-4-2', 2975.00,NULL,20),
	(7654, 'MARTIN', 'SALESMAN', 7698, '1991-9-28',1250.00,1400.00,30),
	(7698, 'BLAKE','MANAGER', 7839,'1991-5-1', 2850.00,NULL,30),
	(7782, 'CLARK','MANAGER', 7839, '1991-6-9',2450.00,NULL,10), 
	(7788, 'SCOTT','ANALYST',7566, '1997-4-19',3000.00,NULL,20), 
	(7839, 'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10), 
	(7844, 'TURNER', 'SALESMAN',7698, '1991-9-8', 1500.00, NULL,30), 
	(7900, 'JAMES','CLERK',7698, '1991-12-3',950.00,NULL,30), 
	(7902, 'FORD', 'ANALYST',7566,'1991-12-3',3000.00, NULL,20), 
	(7934,'MILLER','CLERK',7782,'1992-1-23', 1300.00, NULL,10);
SELECT * FROM emp; 

-- 工资级别
#工资级别表
CREATE TABLE salgrade
(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*工资级别*/
losal DECIMAL(17,2) NOT NULL, /* 该级别的最低工资 */
hisal DECIMAL(17,2) NOT NULL /* 该级别的最高工资*/
);
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);

SELECT * FROM salgrade;
SELECT * FROM dept;
SELECT * FROM emp;
use dxl_db01;

select * from emp;

-- 按部门分组
select avg(sal),max(sal),deptno 
		from emp group by deptno 
		
-- 每个部门每种岗位的平均工资和最低工资
select avg(sal),min(sal),deptno,job
	from emp group by deptno ,job 
	
select avg(sal),deptno
	from emp group by deptno 
		having avg(sal) < 2000; 
		
select avg(sal) as avg_sal,deptno
	from emp group by deptno 
		having avg_sal < 2000; 

在这里插入图片描述

use dxl_db01;
select charset(ename) from emp;

-- 将多列拼成一列
select concat(ename, 'job is',job) from emp 

select instr('hanshunping','ping') from dual 
-- dual 亚元表 系统表,可以作为测试表使用

-- 转成大写
select ucase(ename) from emp  

select lcase(ename) from emp  

select left(ename,2) from emp

select right(ename,2) from emp

-- 按字节返回长度
select length(ename) from emp 

select ename, replace(job,'MANAGER','经理') from emp

select strcmp('hsp','HpP') from dual 

-- 从ename的第一个位置开始取出2个字符
select substring(ename,1,2) from emp 

select ltrim('     教育') from dual 
select rtrim('教育     ') from dual
select trim('          教育          ')from dual


-- 首字母小写显示姓名

select concat(lcase(substring(ename,1,1) ),substring(ename,2))
		from emp
		
select concat(lcase(left(ename,1)),substring(ename,2))
	from emp

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/4177dce04abe4fc98bc4554011cc2004.png

select abs(10) from dual

select bin(10) from dual 

select ceiling(1.1) from dual

select conv(5,10,2) from dual

select floor(10.9) from dual 

select format(12.58795665,3) from dual 

select hex(1536) from dual

select least(12,85,1,-6) from dual

select mod(10,3) from dual

-- 想要固定随机数,加一个随机数种子
select rand(3) from dual 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
王实际开发中,我们也经常使用int来保存一个unix时间戳,然后使用from_unixtime(进行转换

select current_date() from dual 

select current_time() from dual 

select current_timestamp() from dual 

create table mes(
	id int,
	content varchar(30),
	send_time datetime
);

select * from mes

insert into mes 
	values(1,'南京新闻',current_timestamp());
	
insert into mes values(2,'成都新闻',now());
insert into mes values(3,'广州新闻',now());

select now() from dual; 

select id,content,date(send_time) 
	from mes
	
select *
	from mes
		where date_add(send_time,interval 10 minute) >= now()  
		
select *
	from mes
		where date_sub(now(),interval 10 minute) >= send_time 
		
-- 		相差多少天
select datediff('2011-11-11','1990-1-1') from dual 

select datediff(now(),'1996-06-30') from dual 

select datediff(date_add('1997-01-31 10:11:23',interval 80 year),now()) from dual 

select datediff('10:12:23','03:2:23')from dual 

select year(now()) from dual

select month (now()) from dual

select day (now()) from dual

select month ('2012-12-5')from dual

-- 1970-1-1到现在的秒数
select unix_timestamp() from dual 

select from_unixtime(1748654549,'%Y-%m-%d') from dual 
select from_unixtime(1748654549,'%Y-%m-%d  %H:%i:%s') from dual 

在这里插入图片描述

select user() from dual

select database() from dual

select MD5('hhs')from dual

select length(MD5('hhs'))from dual

create table dxl_user(
	id int,
	`name` varchar(32) not null default '',
	pwd char(32) not null default ''
	);

insert into dxl_user 
values(100,'玉玉',md5('yuyu'));

select * from dxl_user

select password('dxl') from dual 

select * from mysql.user

在这里插入图片描述

use dxl_db01;
select if (true,'北京','上海')from dual

select ifnull(null,'教育')from dual

select case 
	when true then 'jian'
	when false then 'tom' 
	else 'mary' end
	from dual
	
select ename,if(comm is null,0.0,comm) 
		from emp
	
select ename,ifnull(comm,0.0)
	from emp 
	
select ename, (select case
					when job = 'CLERK' then '职员'
					when job = 'MANAGER' then '经理'
					when job = 'SALESMAN' then '销售人员'
					else job end)
			from emp;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
select * from emp
order by empno
limit 每页显示的记录数 * (第几页-1),每页显示的记录数

use dxl_db01;
select * from emp
	where hiredate > '1992-01-01' 
	
select ename,sal from emp
	where ename like 'S%'
	
select ename,sal from emp
	where ename like '__O%'
	
select ename,sal from emp
	where mgr is null;
	
desc emp 

select * from emp
	order by sal 
	
select * from emp
		order by deptno asc,sal desc
		
select * from emp 
  limit 10
  
 select * from emp 
  order by empno 
  limit 0,3
  
 select * from emp
	 order by empno 
 	limit 3,3
--  公式
 	select * from emp
 		order by empno 
 		limit 每页显示的记录数 * (第几页-1),每页显示的记录数
 		
 select * from emp
  	order by empno 
  	limit 20,25
select count(*)  from emp
	group by  job 
	
select count(*),avg(sal),job
	from emp
	group by job
	
select count(*)
	from emp
	where comm is not null

select count(*),count(comm) 
	from emp
	
select count(*),count(if(comm is null,1,null))
	from emp
	
select count(*),count(*)-count(comm)
	from emp
	
select count(distinct mgr)
	from emp
	
select max(sal)-min(sal)  
   from emp

在这里插入图片描述
select deptno,avg(sal) as avg_sal
from emp
group by deptno
having avg_sal > 1000
order by avg_sal desc
limit 0,2
在这里插入图片描述
写出正确的过滤条件

select ename,sal,dname from emp,dept
	where emp.deptno = dept.deptno 

select ename,sal,dname,emp.deptno  from emp,dept
	where emp.deptno = dept.deptno and emp.deptno = 10 
	
select * from emp,salgrade 
	where sal between salgrade.losal and salgrade.hisal 

自连接:把一张表当做两张表来使用,要取别名 表名 表别名
列名不明确,可以指定列的别名 列名 as 列的别名

-- 自连接
use dxl_db01;
select worker.ename as '职员名', boss.ename as '上级名' 
	from emp as worker,emp as boss
	where worker.mgr = boss.empno; 

在这里插入图片描述

select deptno
	from emp
	where ename = 'SMITH'
	
select *
	from emp 
	where deptno =(
		select deptno
		from emp
		where ename = 'SMITH'
	)
	
select distinct job
	from emp
	where deptno = 10;
	
select ename ,job,sal,deptno  
	from emp
		where job in  (
		select distinct job
		from emp
		where deptno = 10
		) and deptno <> 10

子查询可以当做临时表使用

select goods_id,cat_id,goods_name,shop_price
	from ecs_goods;
	
select cat_id,max(shop_price)
	from ecs_goods
	group by cat_id
	
select goods_id,ecs_goods.cat_id,goods_name,shop_price
	from (	
	    select cat_id,max(shop_price) as max_price
		from ecs_goods
		group by cat_id
	)temp,ecs_goods
	where temp.cat_id = ecs_goods.cat_id 
	and temp.max_price = ecs_goods.shop_price

all和any

select ename,sal,deptno
	from emp
	where sal > all (
		select sal
			from emp
			where deptno = 30)
			
select ename,sal,deptno
	from emp
	where sal > (
		select max(sal)
			from emp
			where deptno = 30)		

select ename,sal,deptno
	from emp
	where sal > any (
		select sal
			from emp
			where deptno = 30)
			

select ename,sal,deptno
	from emp
	where sal >  (
		select min(sal)
			from emp
			where deptno = 30)

多列子查询

select deptno,job
	from emp
	where ename = 'SMITH'

select * from emp
	where (deptno,job) = (
		select deptno,job
		from emp
		where ename = 'ALLEN')and ename != 'ALLEN'
		
select * from student
	where (math,english,chinese) = (
		select math,english,chinese
		from student 
		where `name` = '宋江')
select deptno,avg(sal)
	from emp group by deptno 
	
select ename,sal,temp.avg_sal,emp.deptno 
	from emp,(
		select deptno,avg(sal) as avg_sal
		from emp group by deptno )temp
	where emp.deptno = temp.deptno and emp.sal > temp.avg_sal
	

select ename,sal,temp.max_sal,emp.deptno 
	from emp,(
		select deptno,max(sal) as max_sal
		from emp group by deptno )temp
	where emp.deptno = temp.deptno and emp.sal = temp.max_sal

-- --查询每个部门的信息(包括:部门名,编号,地址)和人员数量,我们一起完成。
-- --1.部门名,编号,地址来自dept表
-- -- 2.各个部门的人员数量-》构建一个临时表

select count(*),deptno
	from emp
	group by deptno 
	
select dname,dept.deptno ,loc,temp.numberman 
	from dept,(
		select count(*) as numberman,deptno
		from emp
		group by deptno 
	)temp
	where dept.deptno = temp.deptno 
	
--还有一种写法表.*表示将该表所有列都显示出来,可以简化sql语句
--在多表查询中,当多个表的列不重复时,才可以直接写列名

select dname,loc,temp.*
	from dept,(
		select count(*) as numberman,deptno
		from emp
		group by deptno 
	)temp
	where dept.deptno = temp.deptno 

表复制
自我复制数据(蠕虫复制)
有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据。

create table my_tab01
		(
		id int,
		`name` varchar(32),
		sal double,
		job varchar(32),
		deptno int
		);
-- 自我复制
	
insert into my_tab01 
	(id,`name`,sal,job,deptno)
	select empno,ename,sal,job,deptno from emp;
	
-- 自我复制
insert into my_tab01 
	select * from my_tab01 
	
select * from my_tab01;

-- 删除一张重复记录
create table my_tab02
	like emp;

insert into my_tab02
	select * from emp; 
	
-- 去重
-- 思路
-- (1)外创建一张临时表my_tmp ,该表的结构和 my _tab02一样
-- (2)把my_tmp 的记录通过distinct 关键字处理后把记录复制到my_tmp
-- (3)清除掉my _tab02记录
-- (4)把my _tmp―表的记录复制到my _tab02
-- (5) drop掉临时表my_tmp

create table my_tmp like my_tab02

insert into my_tmp 
	select distinct * from my_tab02;
	
delete from my_tab02;

insert into my_tab02
	select * from my_tmp;

drop table my_tmp ;

select * from my_tab02;

在这里插入图片描述
union all就是将两个查询结果合并,不会去重
在这里插入图片描述

select ename,sal,job from emp where sal >2500
union all 
select ename ,sal,job from emp where job = 'MANAGER'


select ename,sal,job from emp where sal >2500
union 
select ename ,sal,job from emp where job = 'MANAGER'

mysql表外连接
外连接
.1.左外连接(如果左侧的表完全显示我们就说是左外连接)
2.右外连接(如果右侧的表完全显示我们就说是右外连接)
在这里插入图片描述

select dname,ename,job
	from emp,dept
	where  emp.deptno = dept.deptno 
	order by dname
	
create table stu(
	id int,
	`name` varchar(32));
	
insert into stu values(1,'huh'),(2,'eff'),(3,'kity'),(4,'yueyue');

create table exam(
	id int,
	grade int);
	
insert into exam values(1,25),(2,89),(3,85);

	
insert into exam values(6,25);

-- 使用左连接(显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)

select `name`,stu.id,grade
	from stu,exam 
	where stu.id = exam.id
	

select `name`,stu.id,grade
	from stu left join exam
	on stu.id = exam.id
	
select `name`,stu.id,grade
	from stu right join exam
	on stu.id = exam.id
	
select dname ,ename,job
	from dept left join emp 
	on dept.deptno = emp.deptno 

绝大多数使用前面的连接

mysql约束
基本介绍
约束用于确保数据库的数据满足特定的商业规则。
在mysql中,约束包括: not null、unique,primary key,foreign key,和check五种.
在这里插入图片描述
在这里插入图片描述
在实际开发中,都需要有一个主键

create table t17(
	id int primary key,
	`name` varchar(32),
	email varchar(32));
	
-- 主键不可以重复
insert into t17 
	values(1,'jack','eekg@qq.com')
	
insert into t17 
	values(1,'jack','eekg@qq.com')
	
-- 	复合主键
create table t18(
	id int,
	`name` varchar(32),
	email varchar(32),
	primary key (id,`name`)
	);
	
insert into t18
	values(1,'jack','eekg@qq.com')
	
insert into t18
	values(1,'tom','eekg@qq.com')
insert into t18
	values(1,'tom','eekg@qq.com')
	
create table t19(
	id int,
	`name` varchar(32),
	email varchar(32),
	primary key (id)
	);
	
desc t19

在这里插入图片描述
在这里插入图片描述
unqiue使用细节
–如果没有指定not null ,则unique字段可以有多个null
–如果一个列(字段),是unique not null使用效果类似primary key
– 2.一张表可以有多个unique字段
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有外键指向主表不能删除,要先删除从表的指向数据,才能在删除主表的数据
在这里插入图片描述

create table my_class(
	id int primary key,
	`name` varchar(32) not null default '');
	
create table my_stu(
	id int primary key,
	`name` varchar(32) not null default '',
	class_id int,
	foreign key (class_id) references my_class(id))
	
insert into my_class 
	values(100,'java'),(200,'web');
	
insert into my_stu
	values (1,'tom',100),(2,'kax',200);

在这里插入图片描述

create table goods (
	goods_id int primary key,
	goods_name varchar(64) not null default '',
	unitprice decimal(10,2) not null default 0
		check(unitprice >= 1.0 and unitprice <= 9999.99),
	catefgory int not null default 0,
	provider varchar(64) not null default ''
		);
		
create table customer(
		customer_id char(8) primary key,
		`name` varchar(64) not null default '',
		address varchar(64) not null default '',
		email varchar(64) unique not null,
		sex enum('男','女') not null,
-- 		枚举类型
		card_Id char(18) unique
);

create table purchase(
	order_id int unsigned primary key,
	customer_id  char(8) not null default '',
	goods_id int not null default 0,
	nums int not null default 0,
	foreign key (customer_id) references customer(customer_id),
	foreign key (goods_id) references goods(goods_id)
);

desc purchase ;

在这里插入图片描述
自增长
●自增长使用细节
1.一般来说自增长是和primary key配合使用的
2自增长也可以单独使用[但是需要配合一个unique
3.自增长修饰的字段为整数型的(虽然小数也可以但是非常非常少这样使用)
4.自增长默认从1开始,你也可以通过如下命令修改alter
table表名auto_increment = 新的开始值;
5.如果你添加数据时,给自增长字段(列)指定的有值,则以指定的值为准
在这里插入图片描述

create table t24(
	id int primary key auto_increment,
	emil varchar(32) not null default ''
	); 
	
insert into t24
	values (null,'ajfe@qq.com');

mysql索引
说起提高数据库性能,索引是最物美价廉的东西了。不用加内存,不用改程序,不用调sql,查询速度就可能提高百倍干倍。
–使用索引来优化一下,体验索引的牛
–在没有创建索引前, emp.ibd文件大小是524m-- empno_index索引名称
– ONemp(empno):表示在 emp表的empno列创建索引

create index empno_index on emp(empno)

在这里插入图片描述
create index ename_index on emp(ename);
select *
from emp
where ename = ‘axJxCs’

mysql索引
索引的原理
没有索引为什么会慢?
●使用索引为什么会快?
索引的代价
磁盘占用
对dml(update delete insert)语句的效率影响
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

create table t25(
	id int,
	`name` varchar(32)
);


-- 查询表是否有索引
show indexes from t25;

-- 添加索引
-- 添加唯一索引
create unique index id_index on t25(id);

-- 普通索引
create index id_index on t25(id);

alter table t25 add primary key (id)

show index from t25;

-- 删除索引
drop index id_index on t25

-- 删除主键索引
alter table t25 drop primary key 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
mysql事务
·回退事务
在介绍回退事务前,先介绍一下保存点(savepoint).保存点是事务中的点.用于取消部分事务,当结束事务时(commit),会自动的删除该事务所定义的所有保存点.当执行回退事务时,通过指定保存点可以回退到指定的点,这里我们作图说明
·提交事务
使用commit语句可以提交事务.当执行了commit语句子后,会确认事务的变化、结束事务、删除保存点、释放锁,数据生效。当使用commit语句结束事务子后,其它会话将可以查看到事务变化后的新数据[所有的数据正式生效]

create table t27(
	id int,
	`name` varchar(32)
);

-- 开启事务
start transaction

-- 设置保存点
savepoint a

insert into t27 values(100,'tom');

savepoint b;

insert into t27 values(200,'jack');

-- 回退到b
rollback to b

select * from t27

rollback to a

-- 表示直接回退到事务开始的状态
rollback
commit 

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

-- 查看当前会话隔离级别
select @@tx_isolation;

-- 查看系统当前隔离级别
select @@global.tx_isolation;

-- 设置当前会话隔离级别
set session transaction isolation level read uncommitted 

-- 设置系统当前隔离级别
set global transaction isolation level [你设置的级别]

在这里插入图片描述
在这里插入图片描述
mysql表类型和存储引擎
●细节说明
我这里重点给大家介绍三种:MylSAM、InnoDB、MEMORY

  1. My!SAM不支持事务、也不支持外键,但其访问速度快,对事务完整性没有要求
  2. InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MylSAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
  3. MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦mysql服务关闭,表中的数据就会丢失掉,表的结构还在。
    在这里插入图片描述
show engines;

-- innodb 存储引擎,
-- 1.支持事务  2.支持外键   3.支持行级锁

drop table t27 

-- myisam 存储引擎
create table t27(
	id int,
	`name` varchar(32)
)engine myisam

-- 1.添加速度快   2.不支持外键和事务   3.支持表级锁
start transaction;
savepoint t1
insert into t27 values(1,'jack');
select * from t27

-- 不能回滚
rollback to t1

-- memory 存储引擎
-- 1.数据存储在内存中[关闭了mysql服务,数据丢失,但是表结构还在], 2.执行速度很快(没有IO读写)  3.默认支持索引(hash表)
create table t28(
	id int,
	`name` varchar(32)
)engine memory

insert into t28
		values(1,'tom'),(2,'jack'),(3,'hhh');
		
select * from t28

如何选择表的存储引擎
1.如果你的应用不需要事务,处理的只是基本的CRUD操作,那么MylSAM是不二选择.速度快
2.如果需要支持事务,选择lnnoDB。
3. Memory存储引擎就是将数据存储在内存中,由于没有磁盘I/O的等待,速度极快。但由于是内存存储引擎,所做的任何修改在服务器重启后都将消失。(经典用法用户的在线状态())
在这里插入图片描述
在这里插入图片描述
视图(view)
●基本概念
1.视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含列,其数据来自对应的真实表(基表)
2.视图和基表关系的示意图
在这里插入图片描述
视图(view)
●视图的基本使用

  1. create view视图名as select语句
  2. alter view视图名as select语句
  3. SHOW CREATE VIEW 视图名
  4. drop view视图名1,视图名2
-- 视图的使用
-- 创建视图
create 	view emp_view01
	as
	select empno,ename,job,deptno from emp;
	
-- 查看视图
desc emp_view01 

select * from emp_view01 ;

-- 查看创建视图的指令
show create view emp_view01 

-- 删除视图
drop view emp_view01  

在这里插入图片描述
视图中可以再使用视图,数据仍然来自基表

-- 视图的使用
-- 创建视图
create 	view emp_view01
	as
	select empno,ename,job,deptno from emp;
	

update emp_view01 
	set job = 'MANAGER'
	where empno = 7369
	
select * from emp

select * from emp_view01 

-- 修改基表,会影响到视图

update emp
	set job = 'SALESMAN'
	where empno = 7369
	
desc emp_view01 

create view emp_view02
	as
	select empno,ename from emp_view01 
	
select * from emp_view02 

在这里插入图片描述

create view emp_view03
	as
	select empno, ename, dname,grade
		from emp,dept,salgrade
		where emp.deptno = dept.deptno and 
		(sal between losal and hisal)
		
desc emp_view03;

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

desc dept 
desc emp

select dname 
	from dept
	
select ename,(sal + ifnull(comm,0) )*13 as "年收入"
	from emp 
	
select ename,sal
	from emp
	where sal < 1500 or sal > 2850
	
select ename,sal
	from emp
	where not (sal >= 1500 and sal <= 2850)
	
select ename,deptno 
	from emp
	where empno = 7566
	
select ename,job
	from emp
	where (deptno = 10 or deptno = 30) and sal>1500
	
select ename,job
	from emp
	where mgr is null 
	
select ename ,job ,hiredate 
	from emp
	where hiredate >= '1991-02-01'and hiredate <= '1991-05-01'
	order by hiredate 
	
select ename,sal,comm
	from emp
	order by sal desc
select * 
	from emp
	where deptno = 30
	
select ename,empno ,deptno ,job 
	from emp
	where job = 'CLERK'
	
select * from 
	emp
	where ifnull(comm,0) > sal 
	
select * from 
	emp 
	where ifnull(comm,0)>sal*0.6
	
select * from 
	emp
	where (deptno = 10 and job = 'MANAGER') or (deptno = 20 and job = 'CLERK')
	
select * from 
	emp
	where (deptno = 10 and job = 'MANAGER') 
	or (deptno = 20 and job = 'CLERK')
	or (job != 'MANAGER' and job != 'CLERK' and sal >= 2000)
	
select distinct job
	from emp
	where comm is not null 
	
	
select distinct *
	from emp
	where comm is null or ifnull(comm,0) < 100 
	
select last_day('2011-11-11')

-- ------9.找出各月倒数第3天受雇的所有员工.
--- last day(日期),~可以返回该日期所在月份的最后一天
-- last_day(日期)-2得到日期所有月份的倒数第3天

select *
	from emp
	where last_day(hiredate) - 2 == hiredate 
	
select *
	from emp
	where date_add(hiredate,interval 12 year) 
	
select concat(lcase(substring(ename,1,1)),substring(ename,2)) 
	from emp
	
select * 
	from emp
	where length(ename) = 5
select *
	from emp
	where ename not like '%R%'
	
select left(ename,3)
	from emp
	
select replace (ename,'A','a')
	from emp

	
select ename,hiredate
	from emp
	where date_add(hiredate,interval 10 year) <= now()  
	
select *
	from emp
	order by ename 
	
select ename,hiredate
	from emp
	order by hiredate 
	
select ename,job,sal
	from emp
	order by job desc,sal

select ename,concat(year(hiredate),'-', month(hiredate)) 
	from emp
	order by month(hiredate),year(hiredate)
	
select floor(sal/30),sal/30
	from emp;
	
select *
	from emp
	where month(hiredate) = 2

select *
	from emp
	where ename like '%A%'

select ename,floor(datediff(now(),hiredate)/365) as "工作年" ,
	floor(datediff(now(),hiredate)%365 / 31) as "工作月",
	datediff(now(),hiredate)%31 as "工作天数"
	from emp;
select count(*) as c,deptno
	from emp
	group by deptno
	having c > 1
	
select *
	from emp 
	where sal >(
		select sal
			from emp
			where ename = 'SMITH'
	)
	
select worker.ename as '员工名', worker.hiredate as '员工入职时间',
	leader.ename as '上级名',leader.hiredate as '上级入职时间'
 	from emp worker , emp leader
	where worker.hiredate  > leader.hiredate
	and worker.mgr  = leader.empno;

select dname,emp.*
	from dept left join emp on dept.deptno = emp.deptno 
	
select dname,emp.*
	from dept
	left join emp on dept.deptno = emp.deptno 
	
select ename,dname
	from emp,dept
	where job = 'CLERK' and emp.deptno = dept.deptno 
	
	
select min(sal) as min_sal,job
	from emp
	group by job
	having min_sal > 1500
	
select ename,dname
	from emp,dept
	where emp.deptno = dept.deptno  and dname = 'SALES'
	
select *
	from emp
		where sal > (
			select avg(sal)
				from emp
		)
	
select * 
	from emp
	where job = (
		select job
		 from emp
		  where ename = 'SCOTT'	)
		  
select ename,sal
	from emp
	where sal > (
		select max(sal)
		from emp
		where deptno = 30
	)
	
select count(*) as '部门员工数量',deptno,avg(sal) as '部门平均工资',
		format(avg(datediff(now(),hiredate)/365),2) as '平均服务期限(年)' 
		from emp
		group by deptno 
		
select count(*) as c,deptno
	from emp
	group by deptno 
	
select dept.*,tmp.c
	from dept,(
		select count(*) as c,deptno
		from emp
		group by deptno )tmp
	where dept.deptno = tmp.deptno
	
select min(sal) ,job 
	from emp
	group by job 
	
select min(sal),job
	from emp
	where job = 'MANAGER'
	
select ename, (sal + ifnull(comm,0))*12 year_sal
		from emp
		order by year_sal
create table department(
	departmentid varchar(32) primary key,
	deptname varchar(32) unique not null
);

create table `class`(
		classid int primary key,
		`subject` varchar(32) not null default '',
		deptname varchar(32),
		enrolltime int not null default 2000,
		num int not null default 0,
		foreign key (deptname) references department(deptname)
);

create table student_d(
	studentid int primary key,
	`name` varchar(32) not null default '',
	age int not null default 0,
	classid int,
	foreign key (classid) references `class`(classid)
);

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值