關係型數據庫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 會提交事務. (還沒學)
數字型
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 /*結果限定*/
聚合函數
聚合函數是用來作縱向運算的函數
分組查詢
當須要分組查詢時須要使用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;
多表查詢的步驟
交叉鏈接查詢(產生笛卡爾積)
查詢員工表和部門表的信息 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
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>
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>
第一步:加載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就是由java提供的一套訪問數據庫的統一api,切換庫時十分方便.
url格式 大協議:自協議://ip:port/庫名?參數鍵=參數值
url = jdbc:mysql://localhost:3306/day05?useUnicode=true&characterEncoding=utf8
url = jdbc:mysql:///day05?useUnicode=true&characterEncoding=utf8 //鏈接本機默認端口號
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注入攻擊
登陸功能,實現邏輯以下:
數據庫中存放用戶名密碼, 在表單上讓用戶輸入用戶名和密碼
經過以下語句判斷用戶名密碼是否一致:
SELECT * FROM t_user WHERE NAME = 'tom' AND PASSWORD='1234';
若是如上查詢返回告終果,那麼說明用戶名密碼正確.登陸成功!
如上實現登陸的方式 很容易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); }