JDBC基礎
JDBC的全稱是Java Database Connectivity,即數據庫連接,它是一種可以執行SQL語句的JavaAPI。程序可通過JDBC API連接到關係數據庫,並使用結構化查詢語言(SQL,數據庫標準的查詢語言)來完成對數據庫的查詢、更新。
JDBC簡介
通過使用JDBC,就可以使用同一種API訪問不同的數據庫系統。
JDBC驅動示意圖
正是通過JDBC驅動的轉換,才使得使用相同JDBC API編寫的程序,在不同的數據庫系統上運行良好。Sun提供的JDBC可以完成以下三個基本工作。
- 與數據庫建立連接
- 執行SQL語句
- 獲得SQL語句的執行結果
通過JDBC的這三個功能,應用程序就可以使用JDBC來操作數據庫系統了
JDBC驅動程序
數據庫驅動程序是JDBC程序和數據庫之間的轉換層,數據庫驅動程序負責將JDBC調用映射成特定的數據庫調用。
JDBC訪問示意圖
ODBC的全稱是Open Database Connectivity,即開放數據庫連接。ODBC和JDBC很像,嚴格地說,應該說JDBC模仿了ODBC的設計。ODBC也允許應用程序通過一組通用的API訪問不同的數據庫管理系統,從而使得基於ODBC的應用程序可以在不同的數據庫之間切換。同樣,ODBC也需要各數據庫廠商提供相應的驅動程序,而ODBC則負責管理這些驅動程序。
SQL語法
SQL語句是對所有關係數據庫都通用的命令語句,而JDBC API則是執行SQL語句的工具,JDBC允許對不同的平臺、不同的數據庫採用相同的編程接口來執行SQL語句。
關係數據庫基本概念和MySQL基本命令
嚴格來說,數據庫僅僅是存放用戶數據的地方。當用戶訪問、操作數據庫中的數據時,就需要數據庫管理系統的幫助。數據庫管理系統的全稱是Database Management System,簡稱DBMS。我們常常會把數據庫和數據庫管理系統籠統地稱爲數據庫,通常所說的數據庫既包括存儲用戶數據的部分,也包括管理數據庫的管理系統。
MySQL數據庫的一個實例(Server Instance)可以同時包含多個數據庫,MySQL使用如下命令來查看當前實例下包含多少個數據庫
SHOW DATABASES;
刪除指定數據庫
DROP DATABASE 數據庫名;
創建新的數據庫,其中IF NOT EXISTS是可選的,如果加上則代表數據庫不存在時纔會創建
CREATE DATABASE [IF NOT EXISTS] 數據庫名;
建立了數據庫之後,如果想操作該數據庫,則需要進入該數據庫
進入指定數據庫命令
use 數據庫名;
查詢該數據庫下包含多少個數據表
SHOW TABLES;
查看指定數據表的表結構
DESC 表名;
連接遠程主機的MySQL服務命令
mysql -p 密碼 -u 用戶名 -h 主機名
執行上面命令時可以省略-p後面的密碼,執行該命令後系統會提示輸入密碼
MySQL數據庫通常支持如下兩種存儲機制
- MyISAM:這是MySQL早期默認的存儲機制,對事務支持不夠好
- InnoDB:InnoDB提供事務安全的存儲機制。InnoDB通過建立行級鎖來保證事務完整性,並以Oracle風格的共享鎖來處理select語句。系統默認啓動InnoDB存儲機制
SQL語句基礎
SQL的全稱是Structured Query Language,也就是結構化查詢語言。SQL是操作和檢索關係數據庫的標準語言,標準的SQL語句可用於操作任何關係數據庫。
使用SQL語句可以完成如下任務
- 在數據庫中檢索信息
- 對數據庫的信息進行更新
- 改變數據庫的結構
- 更改系統的安全設置
- 增加用戶對數據庫或表的許可權限
在上面的5個任務中,一般程序員可以管理前3個任務,後面2個任務通常由DBA來完成。
標準的SQL語句通常可分爲如下幾種類型
- 查詢語句:主要由
select
關鍵字完成,查詢語句是SQL語句中最複雜、功能最豐富的語句 - DML(Data Manipulation Language,數據操作語言)語句:主要由
inset
、update
和delete
三個關鍵字完成 - DDL(Data Definition Language,數據定義語言)語句:主要由
create
、alter
、drop
和truncate
四個關鍵字完成 - DCL(Data Control Language,數據控制語言)語句:主要由
grant
和revoke
兩個關鍵字完成 - 事務控制語句:主要由
commit
、rollback
和savepoint
三個關鍵字完成
DDL語句
DDL語句是操作數據庫對象的語句,包括創建(create)、刪除(drop)和修改(alter)數據庫對象
常見的數據庫對象
建表語句示例
create table test(
# 整型通常用int
test_id int,
# 小數點數
test_price decimal,
# 普通長度文本,使用default指定默認值
test_name varchar(255) default 'xxx',
# 大文本類型
test_desc text,
# 圖片
test_img blob,
test_date datetime
);
建表時需要指定每列的數據類型,不同數據庫所支持的列類型不同,這需要查閱不同數據庫的相關文檔。
MySQL支持的列類型
使用子查詢建表語句,可以在建表的同時插入數據
# 創建haha數據表,該數據表和user_inf完全相同,數據也完全相同
create table haha
as
select * from user_inf;
當數據表創建成功後,MySQL使用information_schema數據庫裏的TABLES表來保存該數據庫實例中的所有數據表,可以通過查詢TABLES表來獲取該數據庫的表信息
修改表結構的語法
修改表結構使用alter table,修改表結構包括增加列定義、修改列定義、刪除列、重命名列等操作。
增加列定義語法
# 爲hehe數據表增加一個hehe_id字段,該字段的類型爲int
# 如果只是增加一列,則可以省略圓括號
alter table hehe
add hehe_id int;
# 爲hehe數據表增加aaa、bbb字段,兩個字段的類型都爲varchar(255)
alter table hehe
add(
aaa varchar(255) default 'xxx',
bbb varchar(255)
);
修改列定義語法
# 將hehe表的hehe_id列修改成varchar(255)類型
alter table hehe
modify hehe_id varchar(255);
# 將hehe表的bbb列修改成int類型
alter table hehe
modify bbb int;
刪除列定義語法
# 刪除hehe表中的aaa字段
alter table hehe
drop aaa;
重命名數據表的語法
# 將hehe數據表重命名爲wawa
alter table hehe
rename to wawa;
完全改變列定義
# 將wawa數據表的bbb字段重命名爲ddd
alter table wawa
change bbb ddd int;
對比change和modify連個選項,不難發現:change選項比modify選項多了一個列名,因爲change選項可以改變列名,所以它需要兩個列名。一般而言,如果不需要改變列名,使用alter table的modify選項即可,只有當需要修改列名時纔會使用change選項。
刪除表的語法
# 刪除數據表
drop table wawa;
刪除表的效果如下
- 表結構被刪除,表對象不再存在
- 表裏的所有數據也被刪除
- 該表所有相關的索引、約束也被刪除
truncate表
對於大部分數據庫而言,truncate都被當成DDL處理,truncate被稱爲截斷某個表,它的作用是刪除該表裏的全部數據,但保留表結構。相對於DML裏的delete命令而言,truncate的速度要快得多,而且truncate不像delete可以刪除指定的記錄,truncate只能一次性刪除整個表的全部記錄。
truncate 表名;
數據庫約束
約束是在表上強制執行的數據校驗規則,約束主要用於保證數據庫裏數據的完整性。除此之外,當表中數據存在相互依賴性時,可以保護相關的數據不被刪除。
大部分數據庫支持下面5種完整性約束
- NOT NULL:非空約束,指定某列不能爲空
- UNIQUE:唯一約束,指定某列或者幾列組合不能重複
- PRIMARY KEY:主鍵,指定該列的值可以唯一地標識該條記錄
- FOREIGN KEY:外鍵,指定該行記錄從屬於主表中的一條記錄,主要用於保證參照完整性
- CHECK:檢查,指定一個布爾表達式,用於指定對應列的值必須滿足該表達式
雖然大部分數據庫都支持上面5種約束,但MySQL不支持CHECK約束,雖然MySQL的SQL語句也可以使用CHECK約束,但這個CHECK約束不會有任何作用。
雖然約束的作用只是用於保證數據表裏數據的完整性,但約束也是數據庫對象,並被存儲在系統表中,也擁有自己的名字。根據約束對數據列的限制,約束分爲如下兩類
- 單列約束:每個約束只約束一列
- 多列約束:每個約束可以約束多個數據列
爲數據表指定約束有如下兩個時機
- 在建表的同時爲相應的數據列指定約束
- 建表後創建,以修改表的方式來增加約束
MySQL使用information_schema數據庫裏的TABLE_CONSTRAINTS表來保存該數據庫實例中所有的約束信息
NOT NULL約束
建表時爲指定列指定非空約束,只要在列定義後增加not null即可
create table hehe(
# 建立了非空約束,這意味着hehe_id不可以爲null
hehe_id int not null,
# MySQL的非空約束不能指定名字
hehe_name varchar(255) default 'xyz' not null,
# 下面列可以爲空,默認就是可以爲空
hehe_gender varchar(2) null
);
也可以在使用alter table修改表時增加或刪除非空約束
# 增加非空約束
alter table hehe
modify hehe_gender varchar(2) not null;
# 取消非空約束
alter table hehe
modify hehe_name varchar(255) null;
# 取消非空約束,並指定默認值
alter table hehe
modify hehe_name varchar(255) default 'abc' null;
UNIQUE約束
唯一約束用於保證指定列或指定列組合不允許出現重複值。雖然唯一約束的列不可以出現重複值,但可以出現多個null值(因爲在數據庫中null不等於null)。
同一個表內可建多個唯一約束,唯一約束也可由多列組合而成。當爲某列創建唯一約束時,MySQL會爲該列相應地創建唯一索引。如果不給唯一約束起名,該唯一約束默認與列名相同。
使用列級約束語法建立唯一約束非常簡單,只要簡單地在列定義後增加unique關鍵字即可。
# 建表時創建唯一約束,使用列級約束語法建立約束
create table unique_test(
# 建立了非空約束,這意味着test_id不可以爲null
test_id int not null,
# unique就是唯一約束,使用列級約束語法建立唯一約束
test_name varchar(255) unique
);
如果需要爲多列組合建立唯一約束,或者想自行指定約束名,則需要使用表級約束語法。
# 建表時創建唯一約束,使用表級約束語法建立約束
create table unique_test2(
# 建立了非空約束,這意味着test_id不可以爲空
test_id int not null,
test_name varchar(255),
test_pass varchar(255),
# 使用表級約束語法建立唯一約束
unique(test_name),
# 使用表級約束語法建立唯一約束,而且指定約束名
constraint test2_uk unique(test_pass)
);
我們還可以爲多列組合建立唯一約束
# 建表時創建唯一約束,使用表級約束語法建立約束
create table unique_test3(
# 建立了非空約束,這意味着test_id不可以爲空
test_id int not null,
test_name varchar(20),
test_pass varchar(50),
# 使用表級約束語法建立唯一約束,指定兩列組合唯一
constraint test3_uk unique(test_name,test_pass)
);
也可以在修改表結構時使用add關鍵字來增加唯一約束
# 增加唯一約束
alter table unique_test3
add unique(test_name,test_pass);
對於大部分數據庫而言,刪除約束都是在alter table語句後使用drop constraint 約束名
語法來完成的,但MySQL並不使用這種方式,而是使用drop index 約束名
的方式來刪除約束
# 刪除unique_test3表上的test3_uk唯一約束
alter table unique_test3
drop index test3_uk;
PRIMARY KEY約束
主鍵約束相當於非空約束和唯一約束,即主鍵約束的列既不允許出現重複值,也不允許出現null值;如果對多列組合建立主鍵約束,則多列裏包含的每一列都不能爲空,但只要求這些列組合不能重複。
每一個表中最多允許有一個主鍵,但這個主鍵約束可由多個數據列組合而成,主鍵是表中能唯一確定一行記錄的字段或字段組合。
當創建主鍵約束時,MySQL在主鍵約束所在列或列組合上建立對應的唯一索引。
建表時創建主鍵約束,使用列級約束語法
create table primary_test(
# 建立了主鍵約束
test_id int primary key,
test_name varchar(255)
);
建表時創建主鍵約束,使用表級約束語法
create table primary_test2(
test_id int not null,
test_name varchar(255),
test_pass varchar(255),
# 指定主鍵約束名爲test2_pk,對大部分數據庫有效,但對MySQL無效
# MySQL數據庫中該主鍵約束名依然是PRIMARY
constraint test2_pk primary key(test_id)
);
建表時創建主鍵約束,以多列建立組合主鍵,只能使用表級約束語法
create table primary_tese3(
test_name varchar(255),
test_pass varchar(255),
# 建立多列組合的主鍵約束
primary key(test_name,test_pass)
);
刪除指定表的主鍵約束
# 刪除主鍵約束
alter table primary_test3
drop primary key;
很多數據庫對主鍵列都支持一種自增長的特性,如果某個數據列的類型是整型,而且該列作爲主鍵列,則可指定該列具有自增長功能。
create table primary_test4(
# 建立主鍵約束,使用自增長
test_id int auto_increment primary key,
test_name varchar(255),
test_pass varchar(255)
);
FOREIGN KEY 約束
外鍵約束主要用於保證一個或兩個數據表之間的參照完整性,外鍵是構建於一個表的兩個字段或者兩個表的兩個字段之間的關係。外鍵確保了相關的兩個字段的參照關係:子(從)表外鍵列的值必須在主表被參照列的值範圍之內,或者爲空(也可以通過非空約束來約束外鍵列不允許爲空)。
當主表的記錄被從表記錄參照時,主表記錄不允許被刪除,必須先把從表裏參照該記錄的所有記錄全部刪除後,纔可以刪除主表的該記錄。還有一種方式,刪除主表記錄時級聯刪除從表中所有參照該記錄的從表記錄。
從表外鍵參照的只能是主表主鍵列或者唯一鍵列,這樣纔可保證從表記錄可以準確定位到被參照的主表記錄。同一個表內可以擁有多個外鍵。
建立外鍵約束時,MySQL也會爲該列建立索引。
建立外鍵約束同樣可以採用列級約束語法和表級約束語法。如果僅對單獨的數據列建立外鍵約束,則使用列級約束語法即可;如果需要對多列組合創建外鍵約束,或者需要爲外鍵約束指定名字,則必須使用表級約束語法。
採用列級約束語法建立外鍵約束直接使用references關鍵字,references指定該列參照哪個主表,以及參照主表的哪一列。
# 爲了保證從表參照的主表存在,通常應該先建主表
create table teacher_table1(
# auto_increment:代表數據庫的自動編號策略,通常用作數據表的邏輯主鍵
teacher_id int auto_increment,
teacher_name varchar(255),
primary key(teacher_id)
);
create table student_table1(
# 爲本表建立主鍵約束
student_id int auto_increment primary key,
student_name varchar(255),
# 指定java_teacher參照到teacher_table1的teacher_id列
java_teacher int references teacher_table1(teacher_id)
);
注意,雖然MySQL支持使用列級約束語法來建立外鍵約束,但這種列級約束語法建立的外鍵約束不會生效,MySQL提供這種列級約束語法僅僅是爲了和標準的SQL保持良好的兼容性。因此,如果要使MySQL中的外鍵約束生效,則應使用表級約束語法。
# 爲了保證從表參照的主表存在,通常應該先建主表
create table teacher_table(
teacher_id int auto_increment,
teacher_name varchar(255),
primary key(teacher_id)
);
create table student_table(
student_id int auto_increment primary key,
student_name varchar(255),
# 指定java_teacher參照到teacher_table的teacher_id列
java_teacher int,
foreign key(java_teacher) references teacher_table(teacher_id)
);
如果使用表級約束語法,則需要使用foreign key
來指定本表的外鍵列,並使用references
來指定參照哪個主表,以及參照到主表的哪個數據列。使用表級約束語法可以爲外鍵約束指定約束名,如果創建外鍵約束時沒有指定約束名,則MySQL會爲該外鍵約束命名爲table_name_ibfk_n,其中table_name是從表的表名,而n是從1開始的整數。
# 爲了保證從表參照的主表存在,通常應該先建主表
create table teacher_table2(
teacher_id int auto_increment,
teacher_name varchar(255),
primary key(teacher_id)
);
create table student_table2(
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher int,
# 使用表級約束語法建立外鍵約束
# 指定外鍵約束的約束名爲student_teacher_fk
constraint student_teacher_fk
foreign key(java_teacher) references teacher_table(teacher_id)
);
如果需要建立多列組合的外鍵約束,則必須使用表級約束語法
# 爲了保證從表參照的主表存在,通常應該先建主表
create table teacher_table3(
teacher_name varchar(50),
teacher_pass varchar(50),
# 以兩列建立組合主鍵
primary key(teacher_name, teacher_pass)
);
create table student_table3(
# 爲本表建立主鍵約束
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher_name varchar(50),
java_teacher_pass varchar(50),
# 使用表級約束語法建立外鍵約束,指定兩列的聯合外鍵
foreign key(java_teacher_name, java_teacher_pass) references teacher_table3(teacher_name, teacher_pass)
);
刪除外鍵約束
# 刪除student_table3表上名爲student_table3_ibfk_1的外鍵約束
alter table student_table3
drop foreign key student_table3_ibfk_1;
增加外鍵約束通常使用add foreign key命令
# 修改student_table3數據表,增加外鍵約束
alter table student_table3
add foreign key(java_teacher_name, java_teacher_pass) references teacher_table3(teacher_name, teacher_pass);
外鍵約束不僅可以參照其他表,而且可以參照自身,這種參照自身的情況通常被稱爲自關聯。
# 使用表級約束語法建立外鍵約束鍵,且直接參照自身
create table foreign_test(
foreign_id int auto_increment primary key,
foreign_name varchar(255),
# 使用該表的refer_id參照到本表的foreign_id列
refer_id int,
foreign key(refer_id) references foreign_test(foreign_id)
);
如果想定義當刪除主表記錄時,從表記錄也會隨之刪除,則需要在建立外鍵約束後添加on delete cascade
或添加on delete set null
,第一種是刪除主表記錄時,把參照該主表記錄的從表記錄全部級聯刪除;第二種是指定當刪除主表記錄時,把參照該主表記錄的從表記錄的外鍵設爲null。
create table teacher_table4(
teacher_id int auto_increment,
teacher_name varchar(255),
primary key(teacher_id)
);
create table student_table4(
student_id int auto_increment primary key,
student_name varchar(255),
java_teacher int,
foreign key(java_teacher) references teacher_table4(teacher_id)
on delete cascade # 也可用on delete set null
);
CHECK約束
create table check_test(
emp_id int auto_increment,
emp_name varchar(255),
emp_salary decimal,
primary key(emp_id),
# 建立CHECK約束
check(emp_salary>0)
);
雖然上面的SQL語句建立的check_test表中有CHECK約束,CHECK約束要求emp_salary大於0,但這個要求實際上並不會起作用。
索引
索引是存放在模式(schema)中的一個數據庫對象,雖然索引總是從屬於數據表,但它和數據表一樣屬於數據庫對象。創建索引的唯一作用就是加速對錶的查詢,索引通過使用快速路徑訪問方法來快速定位數據,從而減少了磁盤的I/O。
索引作爲數據庫對象,在數據字典中獨立存在,但不能獨立存在,必須屬於某個表。
MySQL使用information_schema數據庫裏的STATISTICS表來保存該數據庫實例中的所有索引信息
創建索引有兩種方式
- 自動:當在表上定義主鍵約束、唯一約束和外鍵約束時,系統會爲該數據列自動創建對應的索引
- 手動:用戶可以通過create index語句來創建索引
對單個列創建索引
create index emp_last_name_idx
on employees(last_name);
對多列建立索引
# 下面語句爲employees的first_name和last_name兩列同時建立索引
create index emp_last_name_idx2
on employees(first_name, last_name);
刪除索引
drop index 索引名 on 表名
有些數據庫刪除索引時無須指定表名,因爲它們要求建立索引時每個索引都有唯一的名字,例如Oracle就採用這種策略。但MySQL只要求同一個表內的索引不能同名,所以刪除索引時必須指定表名。
索引的好處是可以加速查詢。但索引也有如下兩個壞處
- 與書的目錄類似,當數據表中的記錄被添加、刪除、修改時,數據庫系統需要維護索引,因此有一定的系統開銷
- 存儲索引信息需要一定的磁盤空間
視圖
視圖看上去非常像一個數據表,但它不是數據表,因爲它並不能存儲數據。視圖只是一個或多個數據表中數據的邏輯顯示。
使用視圖有如下幾個好處
- 可以限制對數據的訪問
- 可以是複雜的查詢變得簡單
- 提供了數據的獨立性
- 提供了對相同數據的不同顯示
因爲視圖只是數據表中數據的邏輯顯示,也就是一個查詢結果,所以創建視圖就是建立視圖名和查詢語句的關聯
create or replace view 視圖名
as
subquery
通過建立視圖的語法規則不難看出,所謂視圖的本質,其實就是一條被命名的SQL查詢語句。
一旦建立了視圖以後,使用該視圖與使用數據表就沒有什麼區別了,但通常只是查詢視圖數據,不會修改視圖裏的數據,因爲視圖本身沒有存儲數據。
爲了強制不允許改變視圖的數據,MySQL允許在創建視圖時使用with check option子句,使用該子句創建的視圖不允許修改
create or replace view view_test
as
select teacher_name from teacher_table
# 指定不允許修改該視圖的數據
with check option;
刪除視圖
drop view 視圖名
DML語句用法
DML語句由insert into、update和delete from 3個命令組成。
insert into語句
insert into 表名(列名...) values(值...);
如果省略列名則默認插入所有列的值
update語句
update table_name
set column1=value1[,column2=value2]...
[where condition];
delete from語句
delete from語句用於刪除指定數據表的記錄。使用delete from語句刪除時不需要指定列名,因爲總是整行地刪除。
delete from table_name
[where condition];
單表查詢
單表查詢的select語句的語法格式如下
select column1,column2...
from 數據源
[where condition];
select後的不僅可以是數據列,還可以是表達式,還可以是變量、常量等。
# 數據列實際上可當成一個變量
select teacher_id + 5
from teacher_table;
# 查詢出teacher_table表中teacher_id * 3大於4的記錄
from teacher_table
where teacher_id * 3 > 4;
# 數據列實際上可當成一個變量
select 3*5, 20
from teacher_table;
# 選擇出teacher_name和'xx'字符串連接後的結果
select concat(teacher_name, 'xx')
from teacher_table;
MySQL提供了一種擴展語法,允許select語句後沒有from子句
select 4 + 5;
distinct
# 去除重複行
select distinct student_name,java_teacher
from student_table;
使用distinct去除重複行時,distinct緊跟select關鍵字。它的作用是去除後面字段組合的重複值,而不管對應記錄在數據庫裏是否重複。例如,(1, ‘a’, ‘b’)和(2, ‘a’, ‘b’)兩條記錄在數據庫裏是不重複的,但如果僅選擇後面兩列,則distinct會認爲兩條記錄重複。
SQL中判斷兩個值是否相等的比較運算符是單等號,判斷不相等的運算符是
<>
;SQL中的賦值運算符不是等號,而是冒號等號:=
。
SQL語句中可以使用兩個通配符:下劃線(_)和百分號(%),其中下劃線可以代表一個任意的字符,百分號可以代表任意多個字符。
查詢出所有學生中名字以“孫”開頭的學生
select * from student_table
where student_name like '孫%';
查詢出名字爲兩個字符的所有學生
select * from student_table
# 下面使用兩個下劃線代表兩個字符
where student_name like '__';
在某些特殊的情況下,查詢的條件裏需要使用下劃線或百分號,不希望SQL把下劃線和百分號當成通配符使用,這就需要使用轉義字符,MySQL用反斜線(\)作爲轉義字符
# 選出所有名字以下劃線開頭的學生
select * from student_table
where student_name like '\_%';
判斷是否爲空用 is null
select * from student_table
where student_name is null;
如果需要按多列排序,則每列的asc、desc必須單獨設定。如果指定了多個排序列,則第一個排序列是首要排序列,只有當第一列中存在多個相同的值時,第二個排序列纔會起作用。如下SQL語句先按java_teacher列的降序排列,當java_teacher列的值相同時按student_name列的升序排列。
select * from student_table
order by java_teacher desc,student_name asc;
數據庫函數
下面直接通過一些例子來介紹MySQL單行函數的用法
# 選出teacher_table表中teacher_name列的字符長度
select char_length(teacher_name)
from teacher_table;
# 計算teacher_name列的字符長度的sin值
select sin(char_length(teacher_name))
from teacher_table;
# 計算1.57的sin值,約等於1
select sin(1.57);
# 爲指定日期添加一定的時間
# 在這種用法下interval是關鍵字,需要一個數值,還需要一個單位
select DATE_ADD('1998-01-02', interval 2 MONTH);
# 這種用法更簡單,單位是日
select ADDDATE('1998-01-02', 60);
# 獲取當前日期
select CURDATE();
# 獲取當前時間
select CURTIME();
# 下面的MD5是MD5加密函數
select MD5('test');
MySQL提供瞭如下幾個處理null的函數
如果expr1爲null,則返回expr2,否則返回expr1
IFNULL(expr1,expr2)
如果expr1和expr2相等,則返回null,否則返回expr1
NULLIF(expr1,expr2)
類似於三目運算符,如果expr1爲true,則返回expr2,否則返回expr3
`IF`(expr1,expr2,expr3)
判斷expr是否爲null,如果爲null則返回true,否則返回false
ISNULL(expr)
MySQL還提供了一個case函數,該函數是一個流程控制函數。case函數有兩個用法,case函數第一個用法的語法格式如下
case value
when compare_value1 then result1
when compare_value2 then result2
...
else result
end
# 如果java_teacher爲1,則返回‘Java老師’,爲2返回‘Ruby老師’,否則返回‘其他老師’
select student_name, case java_teacher
when 1 then 'Java老師'
when 2 then 'Ruby老師'
else '其他老師'
end
from student_table;
case函數第二個用法的語法格式如下
case
when condition1 then result1
when condition2 then result2
...
else result
end
在第二個用法中,condition1、condition2都是返回一個boolean值的條件表達式,因此這種用法更加靈活。
# id小於3的爲初級班,3~6的爲中級班,其他的爲高級版
select student_name,case
when student_id <= 3 then '初級班'
when student_id <= 6 then '中級班'
else '高級班'
end
from student_table;
雖然我們介紹了MySQL常用函數的簡單用法,但通常不推薦在Java程序中使用特定數據庫的函數,因爲這將導致程序代碼與特定數據庫耦合;如果需要把該程序移植到其他數據庫系統上時,可能需要打開源程序,重新修改SQL語句。
分組和組函數
組函數也就是多行函數,組函數將一組記錄作爲整體計算,沒組記錄返回一個結果,而不是每條記錄返回一個結果。常用的組函數有如下5個
計算多行expr的平均值,其中,expr可以是變量、常量或數據列,但其數據類型必須是數值型。還可以在變量、列前使用distinct或all關鍵字,如果使用distinct,則表明不計算重複值;all用和不用的效果完全一樣,表明需要計算重複值。
AVG([DISTINCT] expr)
計算多行expr的總條數,其中,expr可以是變量、常量或數據列,其數據類型可以是任意類型;用星號(*)表示統計該表內的記錄行數;distinct表示不計算重複值
COUNT(DISTINCT expr,[expr...])
計算多行expr的最大值,其中expr可以是變量、常量或數據列,其數據類型可以是任意類型
MAX(expr)
計算多行expr的最小值,其中expr可以是變量、常量或數據列,其數據類型可以是任意類型
MIN(expr)
計算多行expr的總和,其中,expr可以是變量、常量或數據列,但其數據類型必須是數值型;distinct表示不計算重複值
SUM([DISTINCT] expr)
# 計算student_table表中的記錄條數
select count(*)
from student_table;
# 計算java_teacher列總共有多少個值
select count(distinct java_teacher)
from student_table;
# 統計所有student_id的總和
select sum(student_id)
from student_table;
# 計算的結果是20 * 記錄的行數
select sum(20)
from student_table;
# 選出student_table表中student_id最大的值
select max(student_id)
from student_table;
# 選出teacher_table表中teacher_id最小的值
select min(teacher_id)
from teacher_table;
# 因爲sum裏的expr是常量34,所以每行的值都相同
# 使用distinct強制不計算重複值,所以下面計算結果爲34
select sum(distinct 34)
from student_table;
# 使用count統計記錄行數時,null不會被計算在內
select count(student_name)
from student_table;
對於可能出現null的列,可以使用ifnull函數來處理該列
# 計算java_teacher列所有記錄的平均值
select avg(ifnull(java_teacher, 0))
from student_table;
在默認情況下,組函數會把所有記錄當成一組,爲了對記錄進行顯式分組,可以在select語句後使用group by子句,group by子句後通常跟一個或多個列名,表明查詢結果根據一列或多列進行分組,當一列或多列組合的值完全相同時,系統會把這些記錄當成一組。
# count(*)將會對沒組得到一個結果
select count(*)
from student_table
# 將java_teacher列值相同的記錄當成一組
group by java_teacher;
如果對多列進行分組,則要求多列的值完全相同纔會被當成一組。
select count(*)
from student_table
# 當java_teacher、student_name兩列的值完全相同時纔會被當成一組
group by java_teacher,student_name;
使用having子句對組進行過濾
select *
from student_table
group by java_teacher
# 對組進行過濾
having count(*) > 2;