A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

#day 02-高级SQL, JDBC, SQL注入            
##高级SQL
*    排序格式:
    * 升序: `SELECT 列名1, 列名2 FROM 表名 ORDER BY 列名 (ASC默认 可不写);`
    * 降序:: `SELECT 列名1, 列名2 FROM 表名 ORDER BY 列名 DESC;`
    * 使用WHERE条件: `SELECT 列名1, 列名2 FROM 表名 WHERE 条件 ORDER BY 列名 ASC;`
*    注意: `WHERE`在前, `ORDER BY`在后, 否则报错
* 扩展:
    * 排序可以按照多列, 如先按a列降序, 如果a列中有相同的值, 则按b列降序
        * `SELECT * FROM table ORDER BY a DESC, b DESC;`   

##聚合函数
*    作用:
    *    对一列的值进行计算, 然后返回一个值.
    *    格式: `SELECT 函数(列) FROM 表名 ...;`
* `COUNT(列名)`: 计算指定列的记录行数.
    * 注意: 不会计算NULL值
* `SUM(列名)`: 计算指定列的数值总和
    * 如果数据类型不是数值, 则结果为: 0
* `MAX(列名)`: 获取指定列的数值中的最大值
* `MIN(列名)`: 获取指定列的数值中的最小值
* `AVG(列名)`: 计算指定列的数值中的平均值
    * 如果数据类型不是数值, 则结果为: 0

## 分组查询

* 分组查询
    * `GROUP BY 列名 HAVING 条件`, 是`SELECT`的子句, 用于将查询出的结果归类分组显示
    * 格式:
        * `SELECT 列1, 列2 FROM 表名 [WHERE 条件] GROUP BY 列名 HAVING 条件;`
            * `HAVING`关键字的作用: 对查询结果进行分组显示后, 再次按条件过滤

*    最终 sql语句
    *    `SELECT 列1,列2 FROM 表名 WHERE条件 GROUP BY 列名 HAVING 条件 ORDER BY 列名 DESC/ASC;`

* 注意:
    * 分组查询中能使用的列名
        * `HAVING`条件中的列名: 必须是`SELECT`条件或`GROUP BY`条件中使用过的列名
        * `GROUP BY`后的列名: 可以使用表的所有字段
    * 聚合函数与分组的使用效果
        * 使用聚合函数后再进行分组, 才相当于汇总统计
            * `SELECT zname, SUM(zmoney) FROM zhangwu GROUP BY zname;`
        * 不使用聚合函数的分组, 只有第一条记录的值
            * `SELECT zname, zmoney FROM zhangwu GROUP BY zname;`
    * `HAVING``WHERE`的区别
        * 过滤时机不同
            * WHERE是在分组前对结果进行过滤
            * HAVING是在分组后对结果进行再次过滤
        * 是否可跟随聚合函数不同
            * WHERE后不可使用聚合函数
            * HAVING后可以使用聚合函数
        * 条件可用字段不同
            * HAVING条件中的字段必须是SELECT条件或GROUP BY条件中使用过的字段
            * WHERE条件中可以使用表的所有字段

##JDBC
*    JDBC就是一套API 可以通过Java代码来使用JDBC,提供了一套接口,
*    通过多态的方式调用数据库驱动中实现类的方法,对数据库进行操作
*    准备步骤

##1 注册驱动
*    告知JVM使用的是哪一个数据库驱动
*    `Class.forName("com.mysql.jdbc.Driver");`

##2 获得连接
*    使用JDBC中的类完成对MySQL数据库的连接
*    `Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybase","root","123456");`
*    获取Connection接口的实现类, 实现类是jar包中实现的

##3 获得语句执行平台(不建议使用)
*    通过连接对象获得对SQL语句的执行者对象   
*    `Statement cst = con.createStatement();`
*    获取Statement对象, 该对象用于将SQL语句发送到数据库

##3.1 使用PreparedStatement接口预编译SQL语句, 避免SQL注入
```
String sql = "UPDATE sort SET sname = ?,sprice = ? WHERE sid = ?";`用问号占位
PreparedStatement ps = con.prepareStatement(sql);`
ps.setObject(1, "汽车美容")   第几个问号 + 内容
ps.setObject(2, 34566);
ps.setObject(3, 2);
ps.executeUpdate();
```
##4 执行sql语句(执行INSERT语句, 获取结果集, 释放资源)
*    `int rows = cst.executeUpdate(delete from sort where sname ='汽车用品');
*    执行SQL语句, 仅限于INSERT, DELETE, UPDATE, 返回生效的行数

##5 处理结果
*    执行SELECT语句, 获取结果集, 从结果集中获取数据   
*    `ResultSet rs = cst.executeQuery("SELECT * FROM sort");`

```
//执行sql语句
        String sql= "select * from sort";
        PreparedStatement ps = con.prepareStatement(sql);
        //通过ps对象的方法执行查询语句
        ResultSet resultSet = ps.executeQuery();
        //遍历
        while(resultSet.next()){
            String string = resultSet.getString("sid")+"\t"
            +resultSet.getString("sname")+"\t"
            +resultSet.getString("sprice")+"\t"
            +resultSet.getString("sdesc");
            System.out.println(string);
        }
```


## Statement类 && ResultSet接口 方法
```
*Statement类
    ResultSet executeQuery(String sql): 执行SELECT查询, 返回查询结果到ResultSet对象中.
*ResultSet接口
    boolean next()`: 将结果集的指针向下移动一行, 并返回是否还有下一条记录
       注意: 没有调用该方法之前, ResultSet的光标在第一条记录之前, 只有调用一次next方法后, 指针才指向第一条记录
    int getInt(int column): 获取第column列的int类型的数据
    int getInt(String columnName): 获取指定列名的int类型的数据
    String getString(int column): 获取第column列的String类型数据
    String getString(String columnName): 获取指定列名的String类型的数据
    Object getObject(String columnName): 获取指定列名的任何类型数据
    void close()`: 释放结果集资源
```
##6 释放资源
*    一堆close();

##sql注入攻击
*    SQL语句使用字符串拼接方式
*    使用Statement执行的语句
*    密码'1'or'1=1'(后面恒成立 true)
    *    `SELECT * FROM user WHERE username = '随便怎么写' AND password = '1' OR '1=1'`;

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马