MySQL的学习笔记

本文详细介绍了数据库的常用操作,包括查看数据库、切换数据库、创建表、数据插入、更新和删除,以及查询方法。此外,还涉及了事务处理、索引、用户管理和数据库备份。在数据库设计中强调了规范化原则,并讨论了JDBC操作数据库的基本步骤,同时提到了防止SQL注入的方法和数据库连接池的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库操作常用命令:

SHOW DATABASES; --查看所有数据库

USE 数据库名;--切换数据库

SHOW TABLES;--查看所有表

DESCRIBE 表名;--显示表的信息

CREATE DATABASE 名字; --创建数据库

SHOW CREATE 表名; --显示该表被创建时的查询语句

ALTER TABLE 表名 旧名 RENAME AS 新名,

                                 ADD 新字段 类型,

                                 MODIFY 字段 新类型,

                                 CHANGE 旧字段名 新字段名

                                 DROP 字段

建表eg:

CREATE TABLE `NewTable`(
`name` VARCHAR(10) NOT NULL COMMENT 'Student',                                                              `id` INT(10) DEFAULT 0 NOT NULL COMMENT 'ID',
`birthday` DATETIME NULL COMMENT 'Birthday',
`address` VARCHAR(100) NULL COMMENT 'Location',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4


数据操作:

FOREIGN KEY (`本表字段`) REFERENCES `外表`(`字段`) --表级约束,也是物理外键,由于强壮的级联性不建议使用,因为数据库体现为单纯的存储数据,应避免繁杂的其他程序功能;

插入:

INSERT INTO `表名`(要添加的字段 --可以为空,即为默认全部属性) 

VALUES (元组1), (元组2), ... --每个元组对象需一一对应上行的字段,自增字段可忽略;

更新:

UPDATE `表名` SET `字段1` = xxx, `字段2`= xxx,  `字段3` = xxx... 

WHERE `字段` =、<>、>、<、BETWEEN a AND b --闭区间;未指定则SET所有行

删除:

DELETE FROM `表名` WHERE 行级条件;-- 逐条删除各元组,表结构保存,自增保存

TRUNCATE `表名` -- 摧毁表结构然后重建,自增归零


数据查询:

单表查询:

SELECT [DISTINCT(去重)] 字段1,字段2,...  AS 别名 FROM 表名 

模糊查询:

WHERE 字段 LIKE ‘_%’、BETWEEN x AND y、IN (值1,值2,...)、IS NULL(= '' 应该也行)

联表查询:

一般仅为WHERE条件下的满足:SELECT 别名1.字段1, 别名2.字段2,...

                                                      FROM 表1 别名1, 表2 别名2,...

                                                      WHERE 连接谓词 AND 其他限定条件

若想以基本表所有元组作为查询结果:SELECT ...

                                                              FROM 主体表 LEFT OUTER JOIN 查询表 

                                                              ON 连接条件;

自连接:一般是几层递归查询采用:单标两别名后自身连接;

!多表查询多以双表查询开始逐一累加查询

分页和排序:  ORDER BY  字段 默认ASC(升序)/DESC(降序)

                        LIMIT 起始页(以0开始),每页尺寸(每页数据条数)

                        eg:LIMIT 0,5 --最开始的五条数据

子查询与嵌套查询:连接运算优化比子查询完善

相关子查询(父子查询间存在元组变量的传递)过程:按序生成元组变量由子查询WHERE条件确定子查询元组后执行子查询返回结果给父查询后生成当下元组变量的最终结果;

!别名也作为元组变量,即代表某一元组来匹配where条件;

!EXISTS子查询SELECT一般是*,而且多为相关子查询(子查询WHERE需存在与子表连接的条件,接受传递下来的元组变量),并且多数时候可以替换IN,比较运算以及ANY、ALL等子查询,且更加高效,由于不用返回结果表;


常用函数:SELECT CEILING();   SELECT CHAR_LENGTH();返回字符串长度

                  SELECT FLOOR();  SELECT CONCAT();拼接字符串

                  SELECT ABS(); SELECT LOWER();SELECT UPPER();

                  SELECT RAND();0~1随机数  SELECT REVERSE();反转

                  SELECT CURRENT_DATE();

聚集函数:COUNT(*); COUNT(1); 由于内部SQL优化两者差异不大;

                  AVG(); SUM(); MAX(); MIN();   ...

                  GROUP BY 字段; HAVING 条件(筛选GROUP BY后的符合条件元组)

!WHERE不能加聚集函数因为其先于GROUP BY,无法作用于整个基本表;

!MD5('密码');返回加密后的暗文,校验,传递皆使用此暗文;                


事务并发导致的问题:

脏读:某端读到了另一端回滚前的数据;

幻读:一个事务内读到了新插入的元组结果;

不可重复读:由于他端修改操作导致当前端多次读结果不一致;

事务执行:(InnoDB支持事务)

开始前要SET AUTOCOMMIT = OFF, 结尾再开启回来;

START TRANSACTION 

... ...

COMMIT; -- 手动提交

ROLLBAKE; -- 手动撤销


索引

分类:

B+树

散列索引

顺序文件索引

... ...

CREATE [UNIQUE] [CLUSTER] INDEX 索引名

ON 表名(列名) 次序;

-- UNIQUE  表明数据值唯一,不可重复

SHOW INDEX -- 显示索引

EXPLAIN 分析查询效率


用户管理 

      (实际就是在对存在于本地数据库的用户表CRUD):

        创建用户:CREATE USER 用户名 IDENTIFIED BY 密码;

        修改密码:...

        赋予权限:GRANT ALL PRIVILEGES(权限名) ON 库.表 TO 用户名

        显示权限:SHOW GRANTS FOR 用户名        

        撤销权限:REVOKE (权限名) ON 库.表 FROM 用户名


数据库备份

命令行(mysql登录状态下)

导出: mysqldump -h 主机地址 -u 用户名 -p 密码 库名 表名 > D:/... ... -- 备份位置

导入:source 直接拖曳文件过来?/ 备份文件地址


数据库设计

注意事项:

1 - 一般的表项都有id这一字段,作为主键;

2 - 评论表可加入上级id产生自连接;

3 - 订阅数为中间表(关系一个用户和另一个用户的表)的统计;

4 - 标识实体关系图(ER图)

数据库CRUD异常:

插入异常:主码未标定无法插入;

删除异常:删个别主码字段导致整个元组数据的丢失;

修改复杂:修改一个需要接连修改从属字段;

规范化:逐步分离数据依赖中不合适的部分,即概念的逐步概括单一化;

2NF:一个表只能完全围绕主码(主码组),即只能完全形容一种实体;

3NF:在2NF基础上,不可以存在传递依赖,即非主码组不能被依赖,或称为不可再拆出一个主键表,ps:还是保证每张表只能完全形容一种主体;

与性能的关系:范式越高,表的分解度就越高,导致查询性能变差,在考虑用户性能体验时,结合商业化需求往往会存在反范式设计;


JDBC

First jdbc procedure

//note that there are several exception needed to be thrown;

//1. load the driver

Class.forName("com.mysql.jdbc.driver");//it's static code inside the driver class

//2. connection with relevant info

String url = "jdbc:mysql://localhost:3360/nameOfDatabase?useUnicode = true&characterEncoding=utf8&useSSL=true";

String username = "root";
String password = "666666";


Connection connection = DriverManager.getConnection(url,username,password);


//2.return statement object



Statement statement = connection.createStatement;


//3.CRUD using statement

ResultSet resultSet = statement.executeQuery("SELECT * FROM TABLE");
//this result set has all result from select statement and it's a form of linked list; 
//only for select statement, and it's a cursor actually(.next(); .previous();)...

int num = statement.executeUpdate("DELETE ID FROM TABLE WHERE AGE < 10");
//update statement will return a int which means the rows affected;



while(resultSet.next())
{
    resultSet.getObject(Column index: 1);
    resultSet.getObject(Column label: "id");
    ...

}

//4.shut down connection

resultSet.close();
statement.close();
connection.close();




.properties文件为一些相关变量和配置参数,目的为从程序中的变量改变独立出来;

两种配置文件读取方式,!注意Properties的建立接收应在static块里;

1.反射取得类加载器


Properties properties = new Properties();

// 使用ClassLoader加载properties配置文件生成对应的输入流
InputStream in = jdbc.class.getClassLoader().getResourceAsStream("config/config.properties"); //相对路径

// 使用properties对象加载输入流
properties.load(in);

//获取key对应的value值,properties变量格式为键值对
properties.getProperty(String key);



2.输入流

Properties properties = new Properties();

// 使用InPutStream流读取properties文件
BufferedReader bufferedReader = new BufferedReader(new FileReader("E:/config.properties"));
//绝对路径

properties.load(bufferedReader);

// 获取key对应的value值
properties.getProperty(String key);

工具类的概念:

相对于首个JDBC程序,一个jdbc工具类的建立可以简化连接建立释放等固定操作;

public class utils
{
    private static String driver;
    private static String username;
    private static String password;
    private static String url;


   static {
       //1. loading the properties file
       Properties config = new Properties();
       InputStream in = FirstJDBC.class.getClassLoader().getResourceAsStream("jdbc.properties");

       try {
           config.load(in);

           url = config.getProperty("url");
           username = config.getProperty("username");
           password = config.getProperty("password");
           driver = config.getProperty("driver");

           //1. load the Driver
           Class.forName(driver);



       } catch (Exception e) {
           e.printStackTrace();
       }
   }

   public static Connection connect() throws SQLException {
       //2. Connect the database

       return DriverManager.getConnection(url,username,password);
   }


   public static void close(Statement statement,ResultSet resultSet, Connection connection)

       //4. 释放连接
   {
       if(resultSet != null)
       {
           try {
               resultSet.close();
           } catch (SQLException throwables) {
               throwables.printStackTrace();
           }
       }

       if(statement != null)
       {
           try {
               statement.close();
           } catch (Exception throwables) {
               throwables.printStackTrace();
           }
       }

       if(connection != null)
       {
           try {
               connection.close();
           } catch (Exception throwables) {
               throwables.printStackTrace();
           }
       }

   }
}

SQl注入问题

可通过字符串输入破坏SQL查询逻辑结构致使数据泄露,例如拼接or true条件;

PreparedStatement对象:对参数全部实行字符化处理并且忽略转义字符;

public static void login(String username,String password)//模拟登录注入
    {
        try {
            ResultSet result = null;
            Connection connect = utils.connect(); //常规调用

            PreparedStatement statement = connect.prepareStatement("select * from users where name = ? and password = ?");//变量设置占位符‘?’
    

            statement.setString(1,username); //对每个占位符按顺序设置字符或者其他类型
            statement.setString(2,password);

            if(!statement.executeQuery().next())
                System.out.println("Failed");
            else
            {
                result = statement.executeQuery();
                while(result.next())
                    System.out.println(result.getString(1));
            }
            
            utils.close(statement,result,connect);



        } catch (SQLException e) {
            e.printStackTrace();
        }
        

    }

数据库连接池:

DBCP(DataBase connection pool)数据库连接池是 apache 上的一个Java连接池项目,通过连接池预先同数据库建立一些连接放在内存中,应用程序需要建立数据库连接时直接到从接池中申请一个连接使用,用完后由连接池回收该连接,从而达到连接复用,减少资源消耗的目的。

//DBCP2数据源的工具类实现

public class DBCP_utils
{
       static BasicDataSource dataSource = null;


    static {
        //1. loading the properties file
        Properties config = new Properties();
//配置文档为DBCP专用的内置参数设置
        InputStream in = DBCP_utils.class.getClassLoader().getResourceAsStream("DBCP/DBCP_config.properties");

        try {
            
            //连接配置文件到properties对象
            config.load(in);

            //通过配置文件读取信息源初始参数并返回数据源对象;
            dataSource = BasicDataSourceFactory.createDataSource(config);

        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }

    public static Connection connect() throws Exception {
        //2. Connect the database
        return dataSource.getConnection();
    }


    public static void close(PreparedStatement statement,Connection connection)
    {


        if(statement != null)
        {
            try {
                statement.close();
            } catch (Exception throwables) {
                throwables.printStackTrace();
            }
        }

        if(connection != null)
        {
            try {
                connection.close();
            } catch (Exception throwables) {
                throwables.printStackTrace();
            }
        }

    }
}

!DataSource为函数式接口唯一getConnection方法,其他所以上层数据源皆延展自此接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DefinedBySaint

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值