數據庫知識總結
一、數據庫服務器設置
1,查看數據庫服務器編碼
show variables like 'character%';
2,設置數據庫服務器編碼
set character_set_server = utf8; //默認的內部操作字符集
set character_set_client = gbk; //客戶端來源數據使用的字符集
set character_set_results = gbk; //查詢結果字符集
set character_set_connection = utf8; //連接層字符集
set character_set_database = utf8; //當前選中數據庫的默認字符集
set character_set_system = utf8; //系統元數據(字段名等)字符集
注意:
character_set_client 指的是客戶端來源數據所用的編碼
dos窗口輸入中文使用的是gbk,所以應當指定set character_set_client = gbk;
指定其他碼表會造成亂碼(解碼錯誤),從而出現向數據庫插記錄時,字段長度超出限制
的錯誤。
同時,由於插入數據用的是gbk,將數據查詢結果顯示出來的時候,也要使用gbk
故 set character_set_results = gbk; 否則會亂碼,依舊是解碼錯誤。
· 不能直接在dos窗口中設置,因為這樣的設置是臨時的,下次進去就失效了
應該在my.ini 中修改 default-character-set=gbk (第57行),再重啟服務器。
3,查看數據庫服務器校對規則
show variables like 'collation%';
4,設置數據庫服務器校對規則
set collation_connection = utf8_general_ci; //指定連接層校對規則
set collation_database = utf8_general_ci; //指定數據庫校對規則
set collation_server = utf8_general_ci; //指定服務端校對規則
---------------------------------------------------------------------------
二、針對數據庫database的SQL操作 (CRUD, create delete update read)
1,創建(create)
# 創建數據庫 employee (使用默認的字符集和校對規則)
create database employee;
# 創建一個使用utf-8字符集的數據庫 employee
create database employee character set utf8;
# 創建一個使用utf-8字符集,並且校對規則為 utf8_general_ci 的數據庫 employee
create database employee character set utf8 collate utf8_general_ci;
2,刪除(drop)
# 刪除數據庫 employee
drop database if exists employee;
3,修改(alter)
# 修改數據庫 employee的字符集為 gbk
alter database employee character set gbk;
# 修改數據庫 employee的校對規則為 utf8_bin;
alter database employee collate utf8_bin;
4,查詢(show)
# 查看當前服務器中所有的數據庫
show databases;
# 查看數據庫 employee的定義信息
show create database employee;
5,數據庫備份(備份的是數據,而不是數據庫)
# 數據庫備份(將數據導出,需要退出mysql命令)
mysqldump -uroot -proot employee > H:\sql\employee.sql
# 恢復數據庫
use employee;
source H:\sql\employee.sql //執行該文件中的每條語句
-------------------------------------------------------------------
mysql常用的數據類型
數值類型 說明
BIT(M) bit 位類型,M指定位數,不指定默認1,范圍1-64
TINYINT byte 帶符號的范圍-128 -> 127, 不帶符號的范圍 0 -> 255
SMALLINT short
INT int
BIGINT long
FLOAT float
DOUBLE double
BOOL boolean 使用0 和 1 表示真假
文本,二進制類型
CHAR(size) 固定長度字符串,不足就填空格
VARCHAR(size) 變長字符串,最常用
BLOB 二進制數據
LONGBLOB 二進制數據
TEXT 大文本
日期類型
DATE 日期類型(yyyy-MM-dd等)
DATETIME
TIMEStamp 時間戳(自動記錄insert,update操作時間)
-------------------------------------------------------------------
三、針對數據庫表 table的 SQL操作
1,創建(create)
# 創建一張名稱為 emp_1的表
create table emp_1
(
id int,
name varchar(20),
gender varchar(6),
birthday date,
entry_date date,
job varchar(20),
salary float,
resume text
);
# 創建一張名為 emp_2的表,並指定數據庫引擎為 MYISAM,
create table emp_2
(
id int,
name varchar(20),
gender varchar(6),
birthday date,
entry_date date,
job varchar(20),
salary float,
resume text
) ENGINE=MYISAM ;
# 創建一張名為 emp_3的表,並指定數據庫字符集為 gbk,
create table emp_3
(
id int,
name varchar(20),
gender varchar(6),
birthday date,
entry_date date,
job varchar(20),
salary float,
resume text
) charset=gbk ;
2,刪除(drop)
# 刪除 emp_1表
drop table if exists emp_1;
3,修改(alter)
# 增加 email列
alter table emp_1 add email varchar(30);
# 修改 email列為 varchar(40)
alter table emp_1 modify email varchar(40);
# 刪除 gender列
alter table emp_1 drop gender;
# 修改表名為 employee_1
rename table emp_1 to employee_1;
# 修改表的字符集為 gbk
alter table emp_1 character set gbk;
# 將列名由birthday改為 birth (類型也可以同時修改)
alter table emp_1 change birthday birth varchar(20);
4,查詢(show)
# 查看該數據庫下的所有表
show tables;
# 查看 emp_1表的定義信息 (創建語句)
show create table emp_1;
# 查看 emp_1表的結構 (列名,類型,主鍵,約束等信息)
desc emp_1;
---------------------------------------------------------------------
四、針對數據庫記錄的SQL操作
以下表為例
+------+--------+---------+---------+------+
| id | name | chinese | english | math |
+------+--------+---------+---------+------+
| 1 | 張小明 | 89 | 78 | 90 |
| 2 | 李進 | 67 | 53 | 95 |
| 3 | 王五 | 87 | 78 | 77 |
| 4 | 李一 | 88 | 98 | 92 |
| 5 | 李四 | 82 | 84 | 67 |
| 6 | 張三 | 55 | 85 | 45 |
| 7 | 黃蓉 | 75 | 65 | 30 |
+------+--------+---------+---------+-------+
1,增加(insert)
# 向 student表中插入一條記錄
insert into student(id,name,chinese,english,math) values(7,'黃蓉',75,65,30);
2,刪除(delete)
# 刪除student 表中全部記錄
delete from student;
# 刪除student 表中語文分數大於80的學生記錄(使用where子句)
delete from student where chinese > 80;
# 刪除student 表中語文成績是 55分,75分,和67分的學生記錄
delete from student where chinese in(55,75,67);
3,修改(update)
# 將student 表中名叫張三的人改成張小三
update student set name = '張小三' where name = '張三';
# 將student表中所有人的數學分數修改為 90分
update student set math = 90;
# 將student 表中名叫張三的學生數學成績修改為 100分
update student set math = 100 where name = '張三';
# 將student 表中 id為 1 的學生,語文和英語都改成 80分
update student set chinese = 80, english = 80 where id = 1;
# 將student 表中名為張三的學生,語文成績在原來的基礎上加 10 分
update student set chinese = chinese + 10 where name = '張三';
4,查看(select)
# 查看student 表中的所有記錄(所有列名都顯示)
select * from student;
# 查看student 表中的所有學生的姓名和語文成績
select name, chinese from student;
# 查詢student表中所有出現的數學成績 (過濾表中重復信息)
select distinct math from student;
# 統計每個學生的總分
select name, chinese+math+english as count from student;
# 在student 表中使用別名來表示總分
select *, chinese+math+english sum from student;
# 查詢姓名為張三的學生成績
select * from student where name = '張三';
# 查詢英語成績大於90 分的學生信息
select * from student where english > 90;
# 查詢總分大於250 分的學生
select *, chinese+math+english from student where chinese+math+english > 250;
# 查詢英語成績在90 - 100分之間的學生
select * from student where english between 90 and 100;
# 查詢語文成績為88 和 87 的學生信息
select * from student where chinese in(88,87);
# 查詢所有姓李的學生
select * from student where name like '李%';
# 查詢所有姓張的,而且姓名是三個字的學生
select * from student where name like '張__';
# 查詢所有英語大於90,語文大於85的學生
select * from student where chinese > 85 and english >90;
# 按語文成績從高到低排序
select * from student order by chinese desc;
# 按總成績從低到高排序
select *, chinese+math+english as sum from student order by chinese+math+english;
# 統計一個班有多少名學生
select count(*) from student;
# 統計英語成績大於80的人有多少個
select count(*) from student where english > 80;
# 統計總分大於250分的人數
select count(*) from student where chinese+math+english > 250;
# 統計一個班的數學總成績
select sum(math) from student;
# 統計一個班各科總成績
select sum(chinese), sum(math), sum(english) from student;
# 統計一個班級語文、英語、數學的成績總和
select sum(chinese+math+english) from student;
# 統計一個班級語文成績平均分
select sum(chinese)/count(chinese) from student;
# 查詢語文分數最高
select max(chinese) from student;
# 查詢英語分數最低
select min(english) from student;
# 查詢語文平均分
select avg(chinese) from student;
------------------------------------------------------------------------------
限定查詢
1,where
單個條件時,可以使用 not進行反選
多個條件時,可以使用 and 和 or 來作為查詢條件
可以使用in(x,y,z)來限定值是某個,而不是某一區間
select * from student where name = '張三';
select * from student where math > 70 and english > 80;
select * from student where chinese > 70 or math > 80;
select * from student where not english < 60;
select * from student where chinese in(87,88,89);
2,between ... and ...
在某一區間內查找, 包括左右端點
select * from student where english between 80 and 98;
select * from student where english > 80 and english < 98;
3, is null 或者 is not null
判斷為null
select * from student where english is null;
select * from student where english is not null;
4, in操作符
指定查詢范圍
select * from student where chinese in(87,88,89);
5,like操作符
用於模糊查詢
"_":匹配任意的一個字符;
"%":匹配任意多個字符,可以是0個、1個或多個;
各種數據類型都可以使用LIKE子句進行模糊匹配
在使用like 子句的時候如果不設置任何的查詢關鍵字,則表示查詢全部:
show variables like 'character%';
select * from student where name like '%%'; //查詢全部學生
select * from student where english like '9%';
--------------------------------------------------------------------
排序
1,order by [asc|desc ]
asc 升序排列,默認是asc
desc 降序排列
select * from student order by chinese;
-------------------------------------------------------------------
表的約束
在創建表時,同時為字段增加約束,可以對將來插入的數據做一些限定
1,唯一約束 unique
該字段是唯一的,不允許重復
2,非空約束 not null
3,主鍵約束 primary key
主鍵必須有唯一約束,非空約束
·每張表都應該有個主鍵,方便我們通過主主鍵找到記錄(通常是id字段)
·主鍵可以定義為自動增長, 注意主鍵類型必須是int
·如果表中有字段值重復或者為空的情況,無法添加主鍵
create table aaa
(
id int primary key auto_increment,
name varchar(20)
);
//沒有設置主鍵時,通過修改表結構來增加主鍵
alter table table_name add primary key(id);
//刪除主鍵
alter table table_name drop primary key;
//創建聯合主鍵
create table bbb
(
firstname varchar(20),
lastname varchar(20),
primary key(firstname, lastname)
);
4, 外鍵約束
一張表的某一列的數據需要參照另外一張表的某一列
·如員工表的部門編號是按照部門表的編號來制定的
# 部門表
create table dept
(
deptno int primary key,
dname varchar(30)
);
insert into dept (deptno, dname) values (1, '人事部');
insert into dept (deptno, dname) values (2, '市場部');
# 員工表
create table emp
(
id int primary key auto_increment,
ename varchar(30),
deptno int,
constraint deptno_FK foreign key(deptno) references dept(deptno)
);
insert into emp (ename, deptno) values ('張三',1);
insert into emp (ename, deptno) values ('李四',1);
insert into emp (ename, deptno) values ('王五',2);
insert into emp (ename, deptno) values ('趙六',3);
--> ERROR 1452 (23000): Cannot add or update a child row: a foreign key
constraint fails (`test_sql`.`emp`, CONSTRAINT `deptno_FK` FOREIGN KEY
(`deptno`) REFERENCES `dept` (`deptno`))
//為aaa表添加外鍵,引用bbb表中的id字段
create table aaa
(
id int primary key auto_increment,
name varchar(20)
);
create table bbb
(
id int primary key auto_increment,
name varchar(20),
aaa_id int
# constraint aaa_id_FK foreign key(aaa_id) references aaa(id)
);
# 為 bbb表添加引用 aaa表 id字段的外鍵
alter table bbb add constraint aaa_id_FK foreign key(aaa_id) references aaa(id);
# 刪除外鍵
//先刪除外鍵名,再刪外鍵字段(mysql官方提供)
alter table bbb drop foreign key aaa_id_FK;
alter table bbb drop aaa_id;
------------------------------------------------------------------------
如何根據java對象去設計表
1,每個javabean 對應一張表
2,表之間的關聯關系
一對一
分清主從關系,外鍵放在從的一方
一對多
外鍵放在多的一方
多對多
建立中間表以描述關系
中間表需要兩列,作為聯合主鍵,同時又是外鍵分別參照兩張表的主鍵
-------------------------------------------------------------------
oracle常用函數
1,字符串函數
upper(str) 將輸入的字符串變為大寫返回
lower(str) 小寫
initcap(str) 首字母大寫
length(str) 字符串長度
substr(列名,開始點,結束點) 字符串截取
replace(列名,原始值,替換值) 字符串替換
2,數學函數
round() 四舍五入
trunc() 截取小數
mod() 取模
3,日期函數
months_between(日期1,日期2) 求出兩個日期之間的月數:
add_months(日期,月數) 求出若干月之后的日期
last_day(日期) 求出指定日期的最后一天
next_day(日期,星期X) 求出下一個指定星期的日期
4, 轉換函數
to_char() 將日期或數字變為字符串顯示
to_date() 將字符串變為日期型數據
to_number() 將字符串變數字型數據
5, 通用函數
nvl() 處理null的數據
decode() 多值處理函數
----------------------------------------------------------------------
JDBC (Java Database Connectivity)
1,實現JDBC程序
(1) 創建數據庫,表及記錄
(2) 導入數據庫驅動 mysql-connector-java-5.1.7-bin.jar
(3) 編寫java程序
---------------------------------------------------------------------
事務
1,什么是事務
所謂事務,就是針對數據庫的一組操作(多條sql)
位於同一個事務的操作具備同步的特點,也就是要么都成功,要么都失敗
2,事務的作用
在實際中,我們的很多操作都是需要由多條sql來共同完成的,例如,A賬戶給B賬戶轉賬
就會對應兩條sql
update account set money=money-100 where name=‘a’;
update account set money=money+100 where name=‘b’;
假設第一條sql成功了,而第二條sql失敗了,這樣就會導致a賬戶損失了100元,而b賬戶
並未得到100元
如果將兩條sql放在一個sql中,當第二條語句失敗時,第一條sql語句也同樣不會生效,
這樣a賬戶就不會有任何的損失
3. 事務的實現原理
默認情況下,我們向數據庫發送的sql語句是會被自動提交的,開啟事務就是相當於關閉
自動提交功能,改為手動提交,我們只需要將提交事務的操作放在最后一個操作,這樣一來,
如果在提交事務之前出現異常,由於沒有執行提交操作,事務中未提交的操作就會被回滾掉
4,事務相關SQL (在dos命令行窗口執行)
開啟事務 start transaction;
事務提交 commit;
事務回滾 rollback;
注意:
如果開了一個事務, 又敲了一次 start transaction,前一個事務會自動提交
5、在程序中使用 jdbc 開啟事務
在使用 jdbc 操作數據庫時,需要使用 Connection 對象對事務進行管理
// 開啟事務
Connection.setAutoCommit(false); //設置自動提交為false
// 回滾事務
Connection.rollback();
//提交事務
Connection.commit();
在 jdbc 程序中我們還可以設置回滾點, 讓事務回顧到指定的回滾點,而不是自動回滾所有未提交的操作
需要將程序中的異常捕獲,在catch語句塊中回滾事務,在finally中提交事務
注意 , 將 Commit 操作放在 finally 中是為了保證提交未回滾的事務操作
6. 事務的特性
事務有四大特性,一般來講,判斷一個數據庫是否支持事務,就看數據庫是否支持這四個特性
原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要么都發生,要么都不發生。
一致性(Consistency)
事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態。
隔離性(Isolation)
事務的隔離性是多個用戶並發訪問數據庫時,數據庫為每一個用戶開啟的事務,不能被
其他事務的操作數據所干擾,多個並發事務之間要相互隔離。
持久性(Durability)
持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使
數據庫發生故障也不應該對其有任何影響。
7. 事務的隔離級別
1)多線程開啟事務
由於數據庫是多線程並發訪問的,所以很容易出現多個線程同時開啟事務的情況
多線程開事務容易引起 贓讀、不可重復讀、幻讀 的情況發生
贓讀:dirty read
臟讀就是指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交
到數據庫中,這時,另外一個事務也訪問這個數據,然后使用了這個數據。
不可重復讀:non-repeatable read
是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問
該同一數據。那么,在第一個事務中的兩次讀數據之間,由於第二個事務的修改,那么第一
個事務兩次讀到的的數據可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是
不一樣的,因此稱為是不可重復讀。
幻讀:phantom read 又名虛讀
是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了
修改,這種修改涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種
修改是向表中插入一行新數據。那么,以后就會發生操作第一個事務的用戶發現表中還有
沒有修改的數據行,就好象發生了幻覺一樣。
幻讀只是在理論上會發生的一種情況,而現實操作中並不是一定會發生
2)設置事務的隔離級別
為了避免多線程開事務引發的問題,我們需要將事務進行隔離
事務有四種隔離級別,不同的隔離級別可以防止不同的錯誤發生
serializable:可串行化,能避免臟讀、不可重復讀、幻讀情況的發生
repeatable read:可重讀,能避免臟讀、不可重復讀情況的發生
read committed:讀取提交的內容,可避免臟讀情況發生
read uncommitted:讀取未提交的內容最低級別,避免不了任何情況
在數據庫服務器中進行設置:
設置事務隔離級別
set transaction isolation level
查詢當前事務隔離級別
select @@tx_isolation
查詢看到的都是快照
位於事務中的多次查詢,如果隔離級別設置為repeatable read,那么多次查詢讀的
就是一個快照(快照不更新)
----------------------------------------------------------------------------
數據庫連接池
1,什么是連接池
連接池就是數據庫連接對象的一個緩沖池
使用數據庫連接池可以極大地提高系統的性能
2. 實現數據庫連接池
jdbc針對數據庫連接池也定義的接口java.sql.DataSource,所有的數據庫連接池實現
都要實現該接口
該接口中定義了兩個重載的方法
Connection getConnection()
Connection getConnection(String username, String password)
數據庫連接池實現思路
1) 定義一個類實現java.sql.DataSource接口
2) 定義一個集合用於保存Connection對象,由於頻繁地增刪操作,用LinkedList比較好
3) 實現getConnection方法,在方法中取出LinkedList集合中的一個連接對象返回
注意:
返回的Connection對象不是從集合中獲得,而是刪除
用戶用完Connection,會調用close方法釋放資源,此時要保證連接換回連接池,而不是關閉連接
重寫close方法是難點,解決方案: 裝飾設計模式、動態代理
