mysql - 入門知識總結

常見的數據庫

關係型數據庫java

  • MySQL (如下內容所有基於 mysql )mysql

  • Oracle面試

  • Sql serverredis

非關係型數據庫sql

  • mongoDB數據庫

  • redisapi

操做數據庫的命令

  • 建立庫
create database 庫名[character set 碼錶 collate 字符校對集]
  • 刪除庫
drop database 庫名
  • 顯示全部庫
show databases
  • 修改數據庫碼錶
alter database 庫名 character set 碼錶(utf8) collate 字符校對集(utf8_bin);
  • 使用數據庫
use 庫名
  • 查看當前使用的庫
select database();
  • 顯示建立庫語句
show create database 庫名;

操做表的命令

  • 建立表
create table t_user(
      id int,
      name varchar(20),
      sal double(4,3),
      birthday datetime,
      hiredate timestamp
    );
  • 查看錶的結構數據庫設計

    desc t_user;
  • 刪除表函數

    drop table t_user;
  • 修改表url

    alter table t_user add photo blob;
  • 修改列的類型

    alter table 表名 modify 列名 類型;
  • 修改列的名稱

    alter table 表名 change 舊列名 新列名 數據類型;
  • 刪除某列

    alter table 表名 drop 列名;
  • 修改表名

    rename table t_user to t_employee;

操做數據的命令

  • 插入數據
insert into 表名(字段1,2) values(數據...)
  • 更新數據
update 表 set ... where 條件
  • 刪除數據
delete from 表 [條件]

    truncate

面試題:

DELETE 和 TRUNCATE 有什麼區別?

相同點: 

    這兩種都是刪除表中的記錄.      

不一樣點:
   
    1. delete 是逐行標記刪除. TRUNCATE 是將整張表包括表結構都移除,而後將表從新建立.
    
    2. delete DML語句。 TRUNCATE DDL語句。
    
    3. delete 刪除的記錄能夠被恢復,TRUNCATE 不能回覆。
    
    4. delete 不釋放空間,TRUNCATE 釋放空間.
    
    5. TRUNCATE  會提交事務. (還沒學)

mysql 中的數據類型

數字型

  • 整形
TINYINT     1字節   byte   -128~127
    SAMLLINT     2字節   short  -32768~32767
    MEDIUMINT    3字節    
    INT       4字節   int   32bit  2^32
    BIGINT      8字節   long  64bit  2^64
    
    ----------------------------------
    int(10) 和 int(3) 的區別
    括號中的數字只是客戶端顯示時顯示幾位, 不會影響存儲容量
    若是設置 int(10) 當填入1時   默認前面會補充9個0    最種結果就是0000000001(前提設置zeorfill)
  • 浮點型
FLOAT       單精度4字節  float
    DOUBLE   8字節    double
    DECIMAL   沒有精度損失
    
    ----------------------------------
    float 默認只保存6位(除去小數點),若是超過6位,則四捨五入,因此float存儲的數據是不精確的,只是近似值
    DOUBLE和DECIMAL區別?
          DOUBLE類型在運算時會有精度損失
          DECIMAL就是解決精度缺失問題
          單純想表示小數屬性時,使用double
          須要頻繁參與運算的小數,使用

字符串類型

注意:字符串類型要使用單引號包裹

  • 短字符串類型
CHAR/VARCHAR(最大長度225字節)
    
    ---------------------------------------
    區別:
        char定長字符串,varchar表示變長字符串
        同時指定長度10,當存儲abc
        char='abc
        varchar='abc'
    
    結論:
        開發中varchar用得最多,char 只表示固定長度的枚舉中使用。
  • 長字符串類型(流類型)
TEXT/CLOB  保存文本(字符流)->當要保存的內容超過255字節
    BLOB  保存字節-開發中不用
     
    --------------------------------------    
    區別:
        text:只能存儲字符數據
        BLOB:能夠存儲字符和多媒體信息

日期和時間類型

date 只記錄日期
    time 只記錄時間
    year 只記錄年
    datetime 有記錄日期  又記錄時間(不傳值爲null)
    timestamp  同上(不傳值,爲當前時間)

查詢語句

語法

SELECT selection_list /*要查詢的列名稱*/
  FROM table_list /*要查詢的表名稱*/
  WHERE condition /*行條件*/
  GROUP BY grouping_columns /*對結果分組*/
  HAVING condition /*分組後的行條件*/
  ORDER BY sorting_columns /*對結果排序*/
  LIMIT offset_start, row_count /*結果限定*/

聚合函數

聚合函數是用來作縱向運算的函數

  • MAX():計算指定列的最大值,若是指定列是字符串類型,那麼使用字符串排序運算;
  • MIN():計算指定列的最小值,若是指定列是字符串類型,那麼使用字符串排序運算;
  • SUM():計算指定列的數值和,若是指定列類型不是數值類型,那麼計算結果爲0;
  • AVG():計算指定列的平均值,若是指定列類型不是數值類型,那麼計算結果爲0;

分組查詢

當須要分組查詢時須要使用GROUP BY子句.

例如查詢每一個部門的工資和,這說明要使用部門來分組。

1>查詢每一個部門的部門編號和每一個部門的工資和:
 
	select deptno,sum(sal) from emp group by deptno;
     
 2>查詢每一個部門的部門編號以及每一個部門的人數:

     select deptno,count(ename) from emp group by deptno;

 3>查詢每一個部門的部門編號以及每一個部門工資大於1500的人數:

      select deptno,count(ename) from emp where sal>1500 group by deptno ;

HAVING 子句

4>查詢工資總和大於9000的部門編號以及工資和:

      select deptno,sum(sal) from emp group by deptno having sum(sal)>9000;

分頁

LIMIT(MySQL方言) LIMIT用來限定查詢結果的起始行,以及總行數。

1>查詢5行記錄,起始行從0開始
    select * from emp limit 0,5;
    
2> 查詢10行記錄,起始行從3開始
    select * from emp limit 3,10;
    
3>若是一頁記錄爲5條,但願查看第3頁記錄應該怎麼查呢?

    第一頁記錄起始行爲0,一共查詢5行;
      	select * from emp limit 0,5;
      	
    第二頁記錄起始行爲5,一共查詢5行;
        select * from emp limit 5,5;
        
    第三頁記錄起始行爲10,一共查詢5行;
        select * from emp limit 10,5;

多表查詢

多表查詢的步驟

  • 1.肯定查詢那些表
  • 2.肯定查詢哪些字段
  • 3.肯定鏈接條件

交叉鏈接查詢(產生笛卡爾積)

查詢員工表和部門表的信息
SELECT t_emp.emp_name,t_dep.dep_name FROM t_emp, t_dep
這種寫法不會達到咱們的目的, 因爲沒有足夠的鏈接條件會產生笛卡爾積

內鏈接查詢

隱式內鏈接

select * from A,B where 條件;

顯示內鏈接

select * from A inner join B on 條件;(inner join ...  on可省略)

左外鏈接

左表的數據所有顯示, 右表的數據當知足鏈接條件的時候,就顯示知足條件的數據 可是若是不知足鏈接條件, 則顯示NULL

右外鏈接

跟左外鏈接相反

自鏈接

只是一種技巧, 本身跟本身鏈接而已

子查詢

當一個查詢是另外一個查詢的條件

聯合查詢

union 和 union all

手寫SQL順序

select <select_list>
from <table_name>
<join_type> join <join_table> on <join_condition>
where <where_condition>
group by <group_by_list>
having <having_condition>
order by <order_by_condition>
limit <limt_number>

MySql執行順序

from <left table>
on <on_condition>
<join_type> join <join_table>
where <where_condition>
group by <group_by_list>
<sum()avg()等聚合函數>
having <having_condition>
select <select_list>
distinct
order by <order_by_condition>
limit <limit_number>

MySql執行順序理解

第一步:加載from子句的前兩個表計算笛卡爾積,生成虛擬表vt1;

第二步:篩選關聯表符合on表達式的數據,保留主表,生成虛擬表vt2;

第三步:若是使用的是外鏈接,執行on的時候,會將主表中不符合on條件的數據也加載進來,作爲外部行

第四步:若是from子句中的表數量大於2,則重複第一步到第三步,直至全部的表都加載完畢,更新vt3;

第五步:執行where表達式,篩選掉不符合條件的數據生成vt4;

第六步:執行group by子句。group by 子句執行事後,會對子句組合成惟一值而且對每一個惟一值只包含一行,生成vt5,。一旦執行group by,後面的全部步驟只能獲得vt5中的列(group by的子句包含的列)和聚合函數。

第七步:執行聚合函數,生成vt6;

第八步:執行having表達式,篩選vt6中的數據。having是惟一一個在分組後的條件篩選,生成vt7;

第九步:從vt7中篩選列,生成vt8;

第十步:執行distinct,對vt8去重,生成vt9。其實執行過group by後就不必再去執行distinct,由於分組後,每組只會有一條數據,而且每條數據都不相同。

第十一步:對vt9進行排序,此處返回的不是一個虛擬表,而是一個遊標,記錄了數據的排序順序,此處可使用別名;

第十二步:執行limit語句,將結果返回給客戶端

其餘

on 和 where 的區別?

簡單地說,當有外關聯表時,on主要是針對外關聯表進行篩選,主表保留,當沒有關聯表時,兩者做用相同。

例如在左外連時,首先執行on,篩選掉外連表中不符合on表達式的數據,而where的篩選是對主表的篩選。

表與表之間的關係

一對多

在開發中,關係中的一方稱之爲主表或者一表,關係中的多方稱之爲多表或者從表, 爲了表示一對多的關係,通常會在多表的一方添加一個字段,字段名稱自定義(建議:主表的名稱_id) 字段類型通常和主表的主鍵的類型保持一致,咱們稱這個字段爲外鍵

注意

在多表的一方添加外鍵約束(不是必須的,也能夠經過java程序來控制)格式

alter table 多表名稱 add foreign key(外鍵名稱) references 主表名稱(主鍵名稱)

多對多

在開發中,通常引入一箇中間表,在中間表中存放另外兩張表的主鍵.這樣就能夠將多對多的關係拆分兩個一對多的關係 爲了保證數據的有效性和完整性,在中間表上添加兩個外鍵約束(不是必須的,也能夠經過java程序來控制)

約束

  • 默認值約束 建表時, 在數據類型後面添加 DEFAULT '默認值'

  • 非空約束 建表時, 在數據類型後面添加 NOT NULL

  • 惟一約束 建表時, 在數據類型後面添加 UNIQUE

  • 主鍵約束(惟一 + 非空) 建表時, 在數據類型後面添加 PRIMARY KEY

  • 自增加約束 建表時, 在數據類型後面添加 AUTO_INCREMENT

  • 外鍵約束 CONSTRAINT 外鍵名稱 FOREIGN KEY(外鍵字段) REFERENCES 表名(關聯表id)

數據庫設計的三大範式

  • 第一範式: 要求表的每一個字段必須是 獨立 且 不可分割 的單元

  • 第二範式: 要求表的 除主鍵以外 的字段都和 主鍵 有依賴關係 一張表只能表達一個意思, 例如不在呢

  • 第三範式: 在第二範式的基礎上, 要求表中除主鍵以外的字段都與主鍵有直接決定的依賴關係 其餘字段只能由主鍵決定

JDBC

JDBC就是由java提供的一套訪問數據庫的統一api,切換庫時十分方便.

url格式 大協議:自協議://ip:port/庫名?參數鍵=參數值

url = jdbc:mysql://localhost:3306/day05?useUnicode=true&characterEncoding=utf8

url = jdbc:mysql:///day05?useUnicode=true&characterEncoding=utf8 //鏈接本機默認端口號

  • 註冊驅動的方式1:
DriverManager.registerDriver(new Driver());
    Connection connection = DriverManager.getConnection("jdbc:mysql:///blog", "root", "root");
  • 註冊驅動的方式二:
Class.forName("com.mysql.jdbc.Driver");
    Connection connection = DriverManager.getConnection("jdbc:mysql:///blog", "root", "root");

JDBC中幾個重要的API

java.sql.DriverManager
 java.sql.Connection
 java.sql.Statement
 java.sql.ResultSet
 
這裏注意區分 java.sql.Driver 和 com.mysql.jdbc.Driver

 [@Test](https://my.oschina.net/azibug)
 public void test_Conn_1() throws Exception {

      Driver driver  = new Driver();
      Properties prop = new Properties();
      prop.put("user", "root");
      prop.put("password", "root");
      Connection connect = driver.connect("jdbc:mysql://localhost:3306/blog", prop);
      System.out.println(connect);

 }

使用Statement實現數據庫的增刪改查

//1.先獲取Statement
 Statement statement = connection.createStatement();
 //2.調用statement的crud方法     
 statement.update(sql);

注意:

使用statement時,咱們須要傳入參數從而拼寫很長的sql語句,這個時候咱們就引入了PreparedStatement, 咱們可使用 ? 佔位符去替換那些參數,經過PreparedStatement的API傳入參數

sql注入攻擊

登陸功能,實現邏輯以下:

數據庫中存放用戶名密碼, 在表單上讓用戶輸入用戶名和密碼

  1. 經過以下語句判斷用戶名密碼是否一致:

    SELECT * FROM t_user WHERE NAME = 'tom' AND PASSWORD='1234';

  2. 若是如上查詢返回告終果,那麼說明用戶名密碼正確.登陸成功!

  3. 如上實現登陸的方式 很容易sql注入

用戶在填寫用戶名時 填入以下:  xxx' OR 1=1 --
    SELECT * FROM t_user WHERE NAME = '' AND PASSWORD='1234';

分析sql注入的緣由?

將用戶填寫的用戶名直接拼裝到sql中.至關於變相讓用戶參與到了sql語句的書寫

解決sql注入問題

演示使用PrepareStatement對象,解決sql注入問題

public void fun2() throws Exception{
      String name ="xxx' OR 1=1 -- ";
      String password ="1234";
     
      //1 得到鏈接
      Connection conn= JDBCUtils.getConnection();
      //2 拼裝sql語句
      String sql = "SELECT * FROM t_user  WHERE NAME=? AND   PASSWORD=?";
      //3 得到PrepareStatement
      PreparedStatement ps = conn.prepareStatement(sql);
      //4 設置參數到ps對象中
      ps.setString(1, name);
      ps.setString(2, password);
      //5 運送參數,執行sql並拿到結果
      ResultSet rs =      ps.executeQuery();
      //5 根據結果判斷是否登陸成功
      if(rs.next()){
           System.out.println("登陸成功!");
      }else{
           System.out.println("登陸失敗!");
      }
      //6關閉資源
      JDBCUtils.close(conn, ps, rs);
}
相關文章
相關標籤/搜索