MySQL的学习笔记

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

数据库操作常用命令:

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方法,其他所以上层数据源皆延展自此接口。

<think>嗯……用户想要查找MySQL学习笔记,而且之前已经提供了三个引用片段作为参考。让我先理解一下用户的需求和上下文。 从用户的问题历史来看,ta似乎正在系统性地学习MySQL,特别是索引、事务隔离级别这些进阶内容。三个引用片段分别涉及多列索引的使用限制(引用1)、索引优化的重要性(引用2)和事务隔离级别的分类(引用3),这些都是MySQL的核心知识点。 用户明确说“我想查找MySQL学习笔记”,但没说具体方向。考虑到ta之前关注的索引和隔离级别,笔记应该覆盖这些深度内容,同时包含基础语法以便复习。可能需要整理成系统化的知识框架。 引用1提到多列索引的字段顺序很重要——这个必须强调,因为跳过第一个字段会使索引失效。引用2指出数据清洗要在update前完成,还提到B-Tree索引的结构原理,这些都应该整合进笔记。引用3关于事务隔离级别的描述很专业,但“未提交读/提交读/可重复读/可串行化”的对比需要更清晰的表格呈现。 用户没有指定笔记形式,但学习笔记最好结构化。我打算分成七部分:基础架构、数据类型、索引(重点展开)、事务、锁机制、优化技巧、备份恢复。其中索引部分要突出引用1的字段顺序限制和引用2的B-Tree原理;事务部分详解引用3的隔离级别。 需要警惕一个细节:引用3提到“可重复读使用MVCC+X锁实现”,但MySQL的InnoDB在可重复读级别下默认用MVCC避免幻读,实际只在写操作加锁。这点要修正说明,避免误导用户。 对了,用户可能还需要对比不同存储引擎(比如InnoDB和MyISAM的事务支持差异),但引用内容没涉及。为免信息过载,先聚焦已有引用关联的知识点,结尾用开放性问题引导用户提出细化需求比较稳妥。 </think>以下是一份系统的MySQL学习笔记整理,涵盖核心概念与实践要点,结合了您提供的引用内容: --- ### **一、MySQL基础架构** 1. **逻辑架构** - 连接层:客户端连接管理、认证 - 服务层:查询解析、优化、缓存(8.0+移除查询缓存) - 存储引擎层:InnoDB(默认)、MyISAM等 --- ### **二、数据类型与表设计** 1. **常见数据类型** - 整型:`INT`、`BIGINT`(注意无符号范围) - 字符型:`VARCHAR`(变长)、`CHAR`(定长) - 时间型:`DATETIME`(精确到秒)、`TIMESTAMP`(时区敏感) 2. **设计原则** - 主键推荐自增整型(避免页分裂[^1]) - 避免`NULL`字段(增加索引复杂度) --- ### **三、索引机制(核心重点)** 1. **索引类型** - **B-Tree索引**(默认结构): - 数据有序存储,支持范围查询 - 适用场景:`=, >, <, BETWEEN, LIKE 'prefix%'`[^2] - 哈希索引:仅精确匹配(Memory引擎) - 全文索引:`FULLTEXT`(文本搜索) 2. **多列索引(联合索引)规则** - 最多支持16个字段 - **最左前缀原则**: ```sql /* 索引 (a,b,c) */ WHERE a=1 AND b=2 -- ✅ 使用索引 WHERE b=2 AND c=3 -- ❌ 无法使用索引(缺少a)[^1] ``` 3. **索引失效场景** - 对索引列进行运算(`WHERE id+1=10`) - 类型转换(字符串列用数字查询) - `LIKE '%suffix'`(前导通配符) --- ### **四、事务与隔离级别** | 隔离级别 | 脏读 | 不可重复读 | 幻读 | 实现机制 | |------------------|------|------------|------|-----------------------------| | 读未提交 (RU) | ✅ | ✅ | ✅ | 无锁 | | 读已提交 (RC) | ❌ | ✅ | ✅ | MVCC(无X锁)[^3] | | 可重复读 (RR) | ❌ | ❌ | ⚠️ | **MVCC+间隙锁**(防幻读) | | 串行化 (Serializable) | ❌ | ❌ | ❌ | 全表锁 | > **说明**: > - InnoDB在RR级别通过**间隙锁**解决幻读问题[^3] > - MVCC通过事务ID和Undo Log实现快照读 --- ### **五、锁机制** 1. **锁类型** - 行级锁:`Record Lock`(单行)、`Gap Lock`(间隙)、`Next-Key Lock`(行+间隙) - 表级锁:`ALTER TABLE`时自动加锁 2. **死锁处理** - 检测机制:等待图(wait-for graph) - 解决策略:回滚代价最小的事务 --- ### **六、性能优化** 1. **SQL优化原则** - 避免`SELECT *`,用覆盖索引 - 数据清洗在应用层完成(如`UPPER()`处理[^2]) - 批量操作代替循环单条处理 2. **Explain工具** - 关注`type`(访问类型):`const > ref > range > index > ALL` - `Extra`字段:`Using index`(覆盖索引)、`Using filesort`(需优化) --- ### **七、备份与恢复** - **逻辑备份**:`mysqldump --single-transaction`(不影响事务) - **物理备份**:Percona XtraBackup(热备份) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DefinedBySaint

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

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

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

打赏作者

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

抵扣说明:

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

余额充值