MySQL數據庫與JDBC編程(一)

JDBC基礎

JDBC的全稱是Java Database Connectivity,即數據庫連接,它是一種可以執行SQL語句的JavaAPI。程序可通過JDBC API連接到關係數據庫,並使用結構化查詢語言(SQL,數據庫標準的查詢語言)來完成對數據庫的查詢、更新。

JDBC簡介

通過使用JDBC,就可以使用同一種API訪問不同的數據庫系統。
JDBC驅動示意圖
在這裏插入圖片描述
正是通過JDBC驅動的轉換,才使得使用相同JDBC API編寫的程序,在不同的數據庫系統上運行良好。Sun提供的JDBC可以完成以下三個基本工作。

  1. 與數據庫建立連接
  2. 執行SQL語句
  3. 獲得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數據庫通常支持如下兩種存儲機制
  1. MyISAM:這是MySQL早期默認的存儲機制,對事務支持不夠好
  2. InnoDB:InnoDB提供事務安全的存儲機制。InnoDB通過建立行級鎖來保證事務完整性,並以Oracle風格的共享鎖來處理select語句。系統默認啓動InnoDB存儲機制

SQL語句基礎

SQL的全稱是Structured Query Language,也就是結構化查詢語言。SQL是操作和檢索關係數據庫的標準語言,標準的SQL語句可用於操作任何關係數據庫。

使用SQL語句可以完成如下任務

  1. 在數據庫中檢索信息
  2. 對數據庫的信息進行更新
  3. 改變數據庫的結構
  4. 更改系統的安全設置
  5. 增加用戶對數據庫或表的許可權限

在上面的5個任務中,一般程序員可以管理前3個任務,後面2個任務通常由DBA來完成。

標準的SQL語句通常可分爲如下幾種類型

  • 查詢語句:主要由select關鍵字完成,查詢語句是SQL語句中最複雜、功能最豐富的語句
  • DML(Data Manipulation Language,數據操作語言)語句:主要由insetupdatedelete三個關鍵字完成
  • DDL(Data Definition Language,數據定義語言)語句:主要由createalterdroptruncate四個關鍵字完成
  • DCL(Data Control Language,數據控制語言)語句:主要由grantrevoke兩個關鍵字完成
  • 事務控制語句:主要由commitrollbacksavepoint三個關鍵字完成

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種完整性約束

  1. NOT NULL:非空約束,指定某列不能爲空
  2. UNIQUE:唯一約束,指定某列或者幾列組合不能重複
  3. PRIMARY KEY:主鍵,指定該列的值可以唯一地標識該條記錄
  4. FOREIGN KEY:外鍵,指定該行記錄從屬於主表中的一條記錄,主要用於保證參照完整性
  5. CHECK:檢查,指定一個布爾表達式,用於指定對應列的值必須滿足該表達式

雖然大部分數據庫都支持上面5種約束,但MySQL不支持CHECK約束,雖然MySQL的SQL語句也可以使用CHECK約束,但這個CHECK約束不會有任何作用。

雖然約束的作用只是用於保證數據表裏數據的完整性,但約束也是數據庫對象,並被存儲在系統表中,也擁有自己的名字。根據約束對數據列的限制,約束分爲如下兩類

  1. 單列約束:每個約束只約束一列
  2. 多列約束:每個約束可以約束多個數據列

爲數據表指定約束有如下兩個時機

  1. 在建表的同時爲相應的數據列指定約束
  2. 建表後創建,以修改表的方式來增加約束

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表來保存該數據庫實例中的所有索引信息

創建索引有兩種方式
  1. 自動:當在表上定義主鍵約束、唯一約束和外鍵約束時,系統會爲該數據列自動創建對應的索引
  2. 手動:用戶可以通過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只要求同一個表內的索引不能同名,所以刪除索引時必須指定表名。

索引的好處是可以加速查詢。但索引也有如下兩個壞處

  1. 與書的目錄類似,當數據表中的記錄被添加、刪除、修改時,數據庫系統需要維護索引,因此有一定的系統開銷
  2. 存儲索引信息需要一定的磁盤空間

視圖

視圖看上去非常像一個數據表,但它不是數據表,因爲它並不能存儲數據。視圖只是一個或多個數據表中數據的邏輯顯示。
使用視圖有如下幾個好處

  • 可以限制對數據的訪問
  • 可以是複雜的查詢變得簡單
  • 提供了數據的獨立性
  • 提供了對相同數據的不同顯示

因爲視圖只是數據表中數據的邏輯顯示,也就是一個查詢結果,所以創建視圖就是建立視圖名和查詢語句的關聯

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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章