SQL語法 MySQL數據庫

SQL語句是對全部關係數據庫都通用的命令語法,而JDBC API只是執行SQL語句的工具,JDBC容許對不一樣的平臺、不一樣的數據庫採用相同的編程接口來執行SQL語句java

關係數據庫基本概念和MySQL基本命令

數據庫僅僅是存放用戶數據的地方。當用戶訪問、操做數據庫中的數據時,就須要數據庫管理系統的幫助。數據庫管理系統的全稱是Database Management System,簡稱DBMS。把數據庫和數據庫管理系統籠統地稱爲數據庫,一般所說的數據庫既包括存儲用戶數據的部分,也包括管理數據庫的管理系統mysql

DBMS是全部數據的知識庫,它負責管理數據的存儲、安全、一致性、併發、恢復和訪問等操做。DBMS有一個數據字典(也稱爲系統表),用於存儲它擁有的每一個事務的相關信息,例如名字、結構、位置和類型,這種關於數據的數據也稱爲元數據程序員

在數據庫的發展歷史中,按時間順序主要出現了以下幾種類型的數據庫系統:sql

  • 網狀型數據庫數據庫

  • 層次型數據庫編程

  • 關係數據庫安全

  • 面向對象數據庫併發

MySQL數據庫的一個實例能夠同時包含多個數據庫,MySQL使用以下命令來查看當前實例下包含多少數據庫函數

show databases;

建立新的數據庫工具

create database [IF NOT EXISTS] 數據庫名;

刪除指定數據庫

delete database 數據庫名;

進入指定數據庫

use 數據庫名;

查詢該數據庫下包含多少個數據表

show tables;

查看指定數據表的表結構

desc 代表;

MySQL數據庫一般支持以下兩種存儲機制:

  • MyISAM:這是MySQL早期默認的存儲機制,對事務支持不夠好

  • InnoDB:InnoDB提供事務安全的存儲機制。InnoDB存儲機制,若是不想使用InnoDB表,則可使用skip-innodb選項

  • ENGINE = MyISAM —— 強制使用MyISAM

  • ENGINE = InnoDB —— 強制使用InnoDB

SQL語句基礎

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

使用SQL語句,程序員和數據庫管理員(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)、刪除(delete)、修改(alter)數據庫對象

數據庫裏的幾種常見的數據庫對象

clipboard.png

建立表的語法

create table [模式名.] 表名
(
    # 能夠定義有多個列定義
    columnName1 datatype [default expr] ,
    ...
)

每一個列定義之間以英文逗號(,)隔開,最後一個列定義不須要使用英文逗號,而是直接以括號結束
列名放在前面,列類型放在後面。若是要指定列的默認值,則使用default關鍵字,而不是使用等號(=)
clipboard.png

使用子查詢建表語句,能夠在建表的同時插入數據。子查詢建表的語法

create table [模式名.]表名 [column[, cloumn...]]
as subquery;
#建立premium_info數據表,該數據表和user_info徹底相同,數據也徹底相同
create table premium_info
as
select * from user_info;

修改表結構語法

修改表結構使用alter table,修改表結構包括增長列定義、修改列定義、刪除列、重命名列等操做。SQL語句中的字符串值很多用雙引號引發,而是用單引號引發的

alter table 表名
add
(
    #能夠有多個列定義
    column_name1 datatype [default expr] ,
    ...
)

若是隻是新增一列,則能夠省略圓括號,僅在add後緊跟一個列定義便可

# 爲premium_info數據表增長一個pre_id字段,該字段的類型爲int;
alter table premium_info
add pre_id int;
# 爲premium_info數據表增長增長name、duration字段,兩個字段的類型都爲varchar(255)
alter table premium_info
add
(
name varchar(255) default 'Jimmy',
duration varchar(255)
)

修改列定義的語法

alter table 表名
modify column_name datatype [default expr] [first|after col_name];

first或者after col_name指定須要將目標修改到指定位置,該修改語句每次只能修改一個列定義

#將premium_info數據表的pre_id列修改爲varchar(255)類型
alter table premium_info
modify pre_id varchar(255);
#將premium_info的duration列修改爲int類型
alter table premium_info
modify duration int;

若是須要讓MySQL支持一次修改多個列定義,則能夠在alter table後使用多個modify命令

刪除列的語法

alter table 表名
drop column_name
# 刪除premium_info表中的name字段
alter talbe premium_info
drop name;

從數據庫中刪除列定義一般老是能夠成功,刪除列定義時將從每行中刪除該列的數據,並釋放該列在數據塊中佔用的空間。因此刪除大表中的字段時須要比較長的時間,由於還須要回收空間

MySQL的兩種特殊語法:重命名數據表和徹底改變列定義

重命名數據表的語法

alter table 表名
rename to 新表名

alter table premium_info
rename to premium;

change選項的語法

alter table 表名
change old_column_name new_column_name type [default expr] [first|after col_name];
alter table premium_info
change duration time int;

刪除表的語法

drop table 表名;
# 刪除數據表
drop table premium_info;

刪除數據表的效果以下

  • 表結構被刪除,表對象再也不存在

  • 表裏的全部數據也被刪除

  • 該表全部相關的索引、約束也被刪除

truncate表的語法

truncate被稱爲「截斷」某個表——做用是刪除該表裏的所有數據,但保留表結構。相對於DML裏的delete命令而言,truncate的速度要快得多,並且truncate不像delete能夠刪除指定的記錄,truncate只能一次性刪除整個表的所有記錄。truncate命令的語法:

truncate 表名

數據庫約束

約束是表上強制執行的數據校驗規則,約束主要用於保證數據庫裏數據的完整性。除此以外,當表中數據存在相互依賴性時,能夠保護相關的數據不被刪除

5種完整性約束
大部分數據庫支持下面五類完整性約束;

  • NOT NULL:非空約束,指定某列不能爲空

  • UNIQUE:惟一約束,指定某列或者幾列組合不能重複

  • PRIMARY KEY:主鍵,指定該列的值能夠惟一地標識該條記錄

  • FOREIGN KEY:外鍵,指定該行記錄從屬於主表的一條記錄,主要用於保證參照完整性

  • CHECK:檢查,指定一個布爾型表達式,用於指定對應列的值必須知足該表達式

MySQL不支持CHECK約束

根據約束對數據列的限制,能夠分爲以下兩類:

  • 單行約束:每一個約束只約束一列

  • 多行約束:每一個約束約束多個數據列

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

  • 在建表的同時爲相應的數據列指定約束

  • 建表後建立,以修改表的方式來增長約束

NOT NULL約束

非空約束用於確保指定列不容許爲空,非空約束是比較特殊的約束,只能做爲列級使用

SQL中的NULL值特徵:

  • 全部的數據類型的值均可覺得null,包括int、float、boolean等數據類型

  • 與java相似的是,空字符串不等於null,0也不等於null

建表示指定非空約束:

create table null_test
(
    # 創建了非空約束,這意味着user_id不能夠爲null
    user_id int not null,
    # MySQL的非空約束不能指定名字
    user_name varchar(255) default 'lin' not null,
    # 下面列能夠爲空,默認就是能夠爲空
    user_location varchar(255) null
)

也能夠在使用alter table修改表時增長或者刪除非空約束:

# 增長非空約束
alter table null_test
modify user_location varchar(255) not null;
# 取消非空約束
alter table null_test
modify user_name varchar(255) null;
# 取消非空約束,並指定默認值
alter table null_test
modify user_location varchar(255) default 'Nantes' null;

UNIQUE約束

惟一性約束用於保證指定列或指定列的組合不容許出現重複值,但能夠出現多個null值(由於在數據庫中null不等於null)

惟一約束既可使用列級約束語法創建,也可使用表級約束的語法創建。若是須要爲多列建組合約束,或者須要爲惟一約束指定約束名,則只能用表級約束語法

當創建惟一約束時,MySQL在惟一約束所在列或列組合上創建對應的惟一索引。若是不給惟一約束起碼,該惟一約束默認與列名相同

使用列級約束語法來創建惟一約束很是簡單,只要簡單的在列定義後增長unique關鍵字便可

test_name varchar(255) unique

若是須要爲多列組合創建惟一約束,或者想自行指定約束名,則須要使用表級約束語法,表級約束語法以下:

[constraint 約束名] 約束定義
# 建表時建立惟一約束,使用表級的約束語法建約束
create table unique_test2
(
    # 創建了非空約束,着意味着test_id不能夠爲null
    test_id int not null,
    test_name varchar(255),
    test_pass varchar(255),
    # 使用表及約束語法建惟一約束
    unique (test_name),
    # 使用表級約束語法建惟一約束,並且指定約束名
    constraint test_uk unique(test_pass)}
);

上面建表語句爲test_name、test_pass分別創建惟一約束,這意味着兩列不能爲空,除此以外還能夠爲這兩列組合創建惟一約束

# 建表時建立惟一約束,使用表級約束語法建約束
create table unique_test3
(
    # 創建了非空約束,着意味着test_id不能夠爲NULL
    test_id int not null,
    test_name varchar(255),
    test_pass varchar(255),
    # 使用表級約束語法建惟一約束,指定兩列組合不能爲空
    constraint test3_uk unique(test_name, test_pass)
);

unique_test2要求test_name、test_pass都不能出現重複值,而unique_test3只要求test_name、test_pass兩列值的組合不能重複

能夠修改表結構增長惟一約束

# 添加惟一約束
alter table unique_test3
add unique(test_name, test_pass);

能夠在修改表時使用modify關鍵字,爲單列採用列級約束語來增長惟一約束

# 爲null_test表的user_name列增長惟一約束
alter table null_test
modify user_name varchar(255) unique;

對於大多數數據庫而言,刪除約束都是在alter table語句後使用drop constraint約束名的語法刪除約束,但MySQL並不使用這種方式,而是使用drop index、約束名的方式來刪除約束

# 刪除unique_test3表上的test3_uk
alter table unique_test3
drop index test3_uk;

PRIMARY KEY約束

主鍵約束至關於非空約束和惟一約束,即主鍵約束的列既不容許出現重複值,也不容許出現null值;若是對多列組合創建主鍵約束,則多列裏包含的每一列都不能爲空,但只要求這些列組合不能重複

每一個表中最多容許一個主鍵,但這個主鍵約束可由多個數據列組合而成。主鍵是表中能惟一肯定一行記錄的字段或字段組合

創建主鍵約束時既可使用列級約束語,也可以使用表級約束語。如須要對多個字段創建組合主鍵約束時,則只能使用表級約束語法。使用表級約束語法來創建約束時,能夠爲該約束指定約束名。MySql老是將全部主鍵約束命名爲PRIMARY

創建主鍵約束使用primary key

建表時建立主鍵約束,使用的是列級約束語法:

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_test3
(
    test_name varchar(255),
    test_pass varchar(255),
    # 使用表級約束創建多列組合主鍵約束
    primary key(test_name, test_pass)
);

若是須要刪除指定表的主鍵約束,則在alter table語句後使用drop primary_key字句便可

#刪除主鍵約束
alter table primary_test3
drop primary key;

若是須要爲指定表增長主鍵約束,便可經過modify修改列定義來增長主鍵約束,這將採用列級約束語法增長主鍵約束
也可經過add來增長主鍵約束,這將採用表級約束語法來增長主鍵約束

# 使用列級約束語法增長主鍵約束
alter table_primary_test3
modify test_name varchar(255) primary key;
#使用表級約束語法增長主鍵約束
alter table primary_test3
add primary key(test_name,test_pass);

MySQL只用auto_increment來設置自增加

create table primary_test4
(
    # 創建主鍵約束,使用自增加
    test_id int auto_increment primary key,
    test_name varchar(255),
    test_pass varchar(255)
);

FOREIGN KEY約束

外鍵約束主要保證一個或兩個數據表之間的參照完整性,外鍵是構建於一個表的兩個字段或者兩個表的兩個字段之間的參照關係。外鍵確保了相關的兩個字段的參照關係:子(從)表外鍵列的值必須在主表被參照列的值範圍以內,或者爲空。

當主表的記錄被從表的記錄參照時,主表記錄不容許被刪除,必須先把從表裏參照該記錄的全部記錄所有刪除後,才能能夠刪除主表

從表外鍵參照的只能是主表主鍵列或者惟一鍵列,這樣纔可保證從表記錄能夠準肯定位到被參照的主表記錄。同一個表內能夠擁有多個外鍵

外鍵約束一般用於定義兩個實體之間的一對多,一對一的關聯關係。對於一對多的關聯關係,一般在多的一端增長外鍵列。對於一對一的關聯關係,則能夠選擇任意一方增長外鍵列,增長外鍵列的表被稱爲從表。對於多對多的關聯關係,則須要額外增長一個鏈接表來記錄他們的關聯關係。

創建外鍵約束一樣能夠採用列級約束語法和表級約束語法。若是僅對單獨的數據列創建外鍵約束,則可使用列級約束語法便可;若是須要對多列組合建立外鍵約束,或者須要爲外鍵指定名字,則必須使用表級約束語

採用列級約束語法創建外鍵約束直接使用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_table的teacher_id列
java_teacher int references teacher_table1(teacher_id)
);

但值得指出的是,雖然mysql支持使用列級約束語法來創建外鍵約束,但這種列級約束語法創建的外鍵約束不會生效,mysql提供這種列級約束語法僅僅是爲了和標準的SQL保持良好的兼容性,若是要使用mysql中的外鍵約束生效,則應該使用表級約束語法

#爲了保證從表參照的的主表存在,一般應該先建主表
create table teacher_table
(
    #auto_increment:表明數據庫的自動編碼策略,一般用做數據表的邏輯主鍵
    teacher_id int auto_increment,
    teacher_name varchar(255),
    primary key(teacher_id)
);

create table student_table
(
    student_id int auto_increment primary key,
    studnet_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開始的整數

若是須要顯式指定外鍵約束的名字,則可使用constraint來指定名字

create table teacher_table2
(
    #auto_increment:表明數據庫的自動編碼策略,一般用做數據表的邏輯主鍵
    teacher_id int auto_increment,
    teacher_name varchar(255),
    primary key(teacher_id)
);

create table student_table2
(
    student_id int auto_increment primary key,
    studnet_name varchar(255),
    # 指定java_teacher參照到teacher_table的teacher_id列
    java_teacher int,
    # 使用表級約束語法創建外鍵約束,指定外鍵約束的約束名爲student_teacher_fk
    constraint student_teacher_fk foreign key(java_teacher) 
    references teacher_table(teacher_id)
);

若是須要創建多列組合的外鍵約束,則必須使用表級約束語法

create table teacher_table
(
    teacher_name varchar(255),
    teacher_pass varchar(255),
    # 以兩列創建組合主鍵
    primary key(teacher_name, teacher_pass)
);

create table student_table
(
    # 爲本表創建主鍵約束
    student_id int auto_increment primary key,
    student_name varchar(255),
    java_teacher_name varchar(255),
    java_teacher_pass varchar(255),
    # 使用表級約束語法創建外鍵約束,指定兩列的聯合外鍵
    foreign key(java_teacher_name, java_teacher_pass)
    references teacher_table(teacher_name, teacher_pass)
);

刪除外鍵約束的語法也很簡單,在alter table後增長"drop foreign key 約束名"字句便可

# 刪除student_table3表上名爲student_talbe_ibkf_1的外鍵約束
alter table student_table
drop foreign key student_table_ibkf_1;

增長外鍵約束一般使用add foreign key命令,以下

# 修改student_table的數據表,增長外鍵約束
alter table student_table
add foreign key(java_teacher_name, java_teacher_pass)
references teacher_table(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_table
(
    teacher_id int auto_increment,
    teacher_name varchar(255),
    primary key(teacher_id)
);

create table studnet_table
(
    # 爲本表創建主鍵約束
    student_id int auto_increment primary key,
    studnet_name varchar(255),
    java_teacher int,
    # 使用表級約束語法創建外鍵約束,定義級聯刪除
    foreign key(java_teacher) references teacher_table(teacher_id)
    on delete cascade 
    # 也可使用on delete set null
);

CHECK約束

創建CHECK約束的語法很簡單,只要在建表的列定義後增長check便可

create table check_test
(
    emp_id int auto_increment,
    emp_name varchar(255),
    emp_salary decimal,
    # 建立CHECK約束
    check(emp_salary>0)
);

索引

索引是存放在模式(scheme)中的一個數據庫對象,雖然索引老是從屬於數據表,但它也和數據表同樣屬於數據庫對象。建立索引的惟一做用就是加速對錶的查詢,索引經過使用快速訪問方法來快速定位數據,從而減小磁盤的I/O

索引做爲數據庫對象,在數據字典裏獨立存放,但不能獨立存在,必須屬於某個表

建立索引有兩種方式

  • 自動:當在表上定義主鍵約束、惟一約束和外鍵約束時,系統會爲該數據列自動建立對應的索引

  • 手動:用戶能夠經過create index...語句來建立索引

刪除索引也有兩種方式

  • 自動:數據表被刪除時,該表上的索引自動被刪除

  • 手動:用戶能夠經過drop index...語句來刪除指定數據表上的指定索引

建立索引的語法格式以下:

create index index_name
on table_name (column[,column]...);

下面的索引將會提升對employees表基於last_name字段的查詢速度

create index emp_last_name_index
on employees(last_name);

同時對多列創建索引如

# 下面語句爲employees的first_name和last_name兩列同時創建索引
create index emp_last_name_index
on employees(first_name, last_name);

MySQL中刪除索引須要指定表,採用以下語法格式

drop index 索引名 on 表名

以下SQL語句刪除了employees表中的emp_last_name_idx的索引

drop index emp_last_index on employees;

索引的好處是加速查詢,但索引也有以下壞處:

  • 與書的目錄類似,當數據表中的記錄被添加、刪除、修改時,數據庫系統須要維護索引,所以有必定的系統開銷

  • 存儲索引信息須要必定的磁盤空間

視圖

視圖看上去很是像一個數據表,但它不是數據表,由於他並不能存儲數據,視圖只是一個或多個數據表中數據的邏輯顯示

使用試圖的優勢:

  • 能夠限制對數據的訪問

  • 可使複雜的查詢變的簡單

  • 提供了數據的獨立性

  • 提供了對相同數據的不一樣顯示

由於視圖只是數據表中數據的邏輯顯示--也就是一個查詢結果,因此建立視圖就是創建視圖名和查詢語句的關聯。以下:

create or replace view 視圖名
as
subquery

從上面的語法能夠看出,建立、修改視圖均可使用上面語法。上面語法的含義是,若是該視圖不存在,則建立視圖;若是指定的視圖名的視圖已經存在,則使用新視圖替換原有的視圖。後面的subquery就是一個查詢語句,這個查詢能夠很是複雜。

一旦創建了視圖之後,使用該視圖語使用數據表就沒有上面區別了,但一般只是查詢視圖數據,不會修改視圖裏的數據,由於視圖自己就沒有存儲數據

create or replace view view_test
as
select teacher_name, teacher_pass from teacher_table;

大部分時候,咱們不推薦直接改變視圖的數據,由於視圖並不存儲數據,它只是至關於一條命名的查詢語句而已。爲了強制不容許改變視圖的數據,MySQL容許在建立視圖時使用with check option字句,使用該字句建立視圖不容許修改以下:

create or replace view view_test
as
select teacher_name form teacher_table
# 指定不容許修改視圖的數據
with check option;

刪除視圖使用以下語句:

drop view 視圖名

以下SQL語句刪除了前面剛剛建立的視圖名

drop view view_test;

DML語句的語法

與DDL操做數據庫對象不一樣,DML主要操做數據表裏的數據,使用DML能夠完成如下3中任務:

  • 插入新數據

  • 修改已有的數據

  • 刪除不須要的數據

DML語句由insert into、update、和delete from 3個命令組成。

insert into語句

insert into用於向數據表中插入數據。對於標準的SQL語句而言,每次只能插入一條記錄。insert into語法格式以下:

insert into table_name [(column[,column..])]
values(value,[,vlaue...]);

執行插入操做時,表名後能夠用括號列出全部須要插入值的列名,而value後用括號列出對應須要插入的值。
例如:

insert into teacher_table2 value ('Vincent');

若是不想在表後用括號列出全部列,則須要爲全部列指定值;若是某列的值不能肯定,則爲該列分配一個null值

insert into teacher_table2 
# 使用null代替主鍵列的值
values(null, 'Pigeau');

然而此時,Pigeau記錄的主鍵列的值是2,而不是SQL語句插入的null,由於該主鍵列是自增加,系統會自動爲該列分配值

根據外鍵約束規則:外鍵列裏的值必須是被參照列裏已有的值,因此向從表中插入記錄以前,一般應該先向主表中插入記錄,不然從表記錄的外鍵列只能爲null。現向從表student_table2中插入記錄

insert into student_table2
# 當向外鍵列裏插值時,外鍵列的值必須是被參照列裏已有的值
values (null, 'Mars', 2);

在一些特殊的狀況下,咱們可使用帶子查詢的插入語句,帶子查詢的插入語句能夠一次插入多條記錄

insert into student_table2(student_name)
# 使用子查詢的值來插入
select teacher_name from teacher_table2;

MySQL容許在values後使用多個括號包含多條記錄,表示多條記錄的多個括號之間以英文逗號(,)隔開

insert into teacher_table2
# 同時插入多個值
values (null, 'Paris'),
(null, 'Nantes');

update語句

update語句用於修改數據表的記錄,每次能夠修改多條記錄,經過使用where子句限定修改哪些記錄。沒有where子句則意味着where表達式的值老是true,即該表的全部記錄都會被修改,update語句的語法格式以下:

update teacher_table 
set column1 = value1[,column=value2]...
[WHERE condition];

使用update不只能夠一次修改多條記錄,也能夠一次修改多列。修改多列都是經過在set關鍵字後使用column1=value1,column2=value2...來實現的,修改多列的值之間以英文逗號(,)隔開

update teacher_table2 
set teacher_name = '王';

也能夠經過添加where條件來指定只修改特定記錄,以下

update teacher_table
set teacher_name = '林'
where teacher_id > 1;

delete from語句

delete from語句用於刪除指定數據表的記錄。使用delete from語句刪除時不須要指定列名,由於老是整行地刪除。使用delete from語句能夠一次刪除多行,刪除哪些行採用where字句限定,只刪除知足where條件的記錄。沒有where字句限定將會把表裏的所有記錄刪除

delete from語句的語法格式以下:

delete from table_name
[WHERE condition];

以下SQL語句將會把student_table2表中的所有記錄所有刪除:

delete from studnet_table2;

也可使用where條件來限定只刪除指定記錄,以下SQL語句所示:

delete form teacher_table2 
where teacher_id > 2;

當主表記錄被從表記錄參照時,主表記錄不能被刪除,只有先將從表中參照主表記錄的全部記錄所有刪除後,纔可刪除主表記錄。還有一種狀況,定義外鍵約束時定義了主表記錄和從表記錄之間的聯級刪除on delete cascade,或者使用on delete null用於指定當主表記錄被刪除時,從表中參照該記錄的從表記錄把外鍵列的值設爲null

單表查詢

select語句的功能就是查詢數據。select語句也是SQL語句中功能最豐富的語句,select語句不只能夠執行單表查詢,並且能夠執行多表鏈接查詢,還能夠進行子查詢,select語句用於從一個或多個數據表中選出特定行、特定列的交集

select語句最簡單的功能如圖所示
clipboard.png

單表查詢的select語句的語法以下:

select colimn1 colimn2 ... 
form 數據源 
[WHERE condition]

上面的語法格式中的數據源能夠是表、視圖等。從上面的語法格式中能夠看出,select後的列表用於選擇哪些列,where條件用於肯定選擇哪些行,只有知足where條件的記錄纔會被選擇出來;若是沒有where條件,則默認選出全部行。若是想選擇全部列,則可以使用星號(*)表明全部列

下面的SQL語句將會選擇出teacher_table表中的全部行、全部列的數據。

select * 
from teacher_table;

若是增長where條件,則只選擇符合where條件的記錄,以下SQL語句將選擇出student_table表中java_teacher值大於3的記錄student_name列的值

select student_name 
from student_table 
where java_teacher > 3;

當使用select語句進行查詢時,還能夠在select語句中使用算術運算符(+、-、*、/),從而造成算術表達式:使用算術表達式的規則以下

  • 對數值型數據列、變量、常量可使用算術運算符(+、-、*、/) 建立表達式

  • 對日期型數據列、變量、常量可使用部分算術運算符(+、-、)建立表達式,兩個日期之間能夠進行減法運算,日期和數值之間能夠進行加、減運算

  • 運算符不只能夠在列和常量、變量之間進行運算,也能夠在兩列之間進行運算

下面的select語句中使用了算術運算符

# 數據列實際上可當成一個變量
select teacher_id + 5 
from teacher_table;
# 查詢出teacher_table表中teacher_id * 3 大於4的記錄
select * 
from teacher_table 
where teacher_id * 3 > 4;

須要指出的是,select後的不只能夠是數據列,也能夠是表達式,還能夠是變量、常量等

# 數據列實際上可當成一個變量
select 3*5, 20 
from teacher_table;

SQL語言中算術符的優先級與java語言的運算符優先級徹底相同,MySQL使用concat函數來進行字符串鏈接運算。

# 選擇出teacher_name和'xx'字符串鏈接後的結果
select concat(teacher_name, 'xx') 
form teacher_table;

對於MySQL而言,若是在算術表達式中使用null,將會致使整個算術表達式的返回值爲null;若是在字符串鏈接運算符中出現null,將會致使鏈接後的結果也是null

select concat(teacher_name, null) 
from teacher_table;

若是不但願直接使用列名做爲列標題,則能夠爲數據列或表達式起一個別名,爲數據列或表達式起別名時,別名緊跟數據列,中間以空格隔開,或者使用as關鍵字隔開

select teacher_id + 5 as MY_ID 
from teacher_table;

若是列別名中使用特殊字符(例如空格),或者須要強制大小寫敏感,均可以經過爲別名添加雙引號來實現

# 能夠爲選出的列起別名,別名中包括單引號字符,因此把別名用雙引號引發來
select teacher_id + 5 as "MY'id"
from teacher_table;

若是須要選擇多列,併爲多列起別名,則多列與列之間以逗號隔開,但列和列名之間以空格隔開

select teacher_id + 5 MY_ID, teacher_name 老師名
from teacher_table;

不只能夠爲列或表達式起別名,也能夠爲表起別名,爲表起別名的語法和爲列或表達式起別名的語法徹底同樣

select teacher_id + 5 MY_ID, teacher_name 老師名
# 爲teacher_table起別名t
from teacher_table t;

列名能夠當成變量處理,因此運算符也能夠在多列之間進行運算

select teacher_id + 5 MY_ID, concat(teacher_name, teacher_id) teacher_name
from teacher_table
where teacher_id * 2 > 3;

select默認會把全部符合條件的記錄所有選出來,即便兩行記錄徹底同樣。若是想去除重複行,則可使用distinct關鍵字從查詢結果中清除重複行,比較下面兩條SQL語句的執行結果:

# 選出全部記錄,包括重複行
select student_name, java_teacher 
from student_table;

# 去除重複行
select distinct student_name, java_teacher 
from student_table;

注:使用distinct去除重複行時,distinct緊跟select關鍵字,它的做用是去除後面字段組合的重複值,而無論對應對應記錄在數據庫是否重複

前面已經看到了where字句的做用:能夠控制只選擇指定的行。由於where字句裏包含的是一個條件表達式,因此可使用>、>=、<、<=、=和<>等基本的比較運算符。SQL中的比較運算符不只能夠比較數值之間的大小,也能夠比較字符串、日期之間的大小

SQL判斷兩個值是否相等的比較運算符是單等號=,判斷不等的運算符是<>;SQL中的賦值運算符不是等號,而是冒號等號(:=)

SQL支持的特殊比較運算符

運算符 含義
expr1 between expr2 and expr3 要求expr1 >= expr2 而且 expr2 <= expr3
expr1 in(expr2,expr3,expr4,...) 要求expr1等於後面括號裏任意一個表達式的值
like 字符串匹配,like後的字符串支持通配符
is null 要求指定值等於null

下面的SQL語句選出student_id大於等於2,且小於等於4的全部記錄.

select * 
from student_table 
where student_id between 2 and 4;

# 選出java_teacher小於等於2,student_id大於等於2的全部記錄
select * 
from student_table 
where 2 between java_teacher and student_id;

使用in比較運算時,必須在in後的括號裏列出一個或多個值,它要求指定列必須與in括號裏任意一個值相等

# 選出student_id、java_teacher列的值爲2或4的全部記錄
select * 
from student_table 
where student_id in(2,4);

與之相似的是,in括號裏的值既能夠是常量,也能夠是變量或者列名

# 選出student_id、java_teacher列的值爲2的全部記錄
select * 
from student_table 
where 2 in(student_id,java_teacher);

like運算符主要用於進行模糊查詢,例如,若要查詢名字以「孫」開頭的全部記錄,這就須要用到迷糊查詢,在模糊查詢中須要使用like關鍵字。SQL語句中可使用兩個通配符:下劃線(_)和百分號(%),其中下劃線能夠表明一個任意的字符,百分號能夠表明任意多個字符。以下SQL語句將查詢出全部學生中名字以"孫"開頭的學生

select * 
from student_table
where student_name like '孫%';

下面的SQL語句將查出名字爲兩個字符的全部學生

select * 
from student_table
# 下面使用兩個下劃線表明來個字符
where student_name like '__';

在某些特殊狀況下,查詢的條件裏須要使用下劃線或百分號,不但願SQL把下劃線和百分號當成通配符使用,這就須要使用轉義字符,MySQL使用反斜線(/)做爲轉義字符

# 選出全部名字如下劃線開頭的學生
select 8
from student_table
where student_name like '\_%';

is null 用於判斷某些值是否爲空,判斷是否爲空不能用=null來判斷,由於SQL中null=null返回null。以下SQL語句將選擇出student_table表中student_name爲null的全部記錄

select * 
from student_table
where student_name is null;

若是where字句後面有多個條件須要組合,SQL提供了and和or邏輯運算符來組合2個條件,並提供了not來對邏輯表達式求否,以下SQL語句將選出學生名字爲2個字符,且student_id 大於3的全部記錄。

select * 
from student_table
where student_name like '__' and studnent_id > 3;

下面的SQL語句將選出student_table表中姓名不如下劃線開頭的全部記錄。

select * 
from student_table
# 使用not對where條件取否
where not student_name like '/_%';

SQL中比較運算符、邏輯運算符的優先級
clipboard.png

order by語句

執行查詢後的結果默認按插入順序排序;若是須要在查詢結果按某列值的大小進行排序,則可使用order by字句

ORDER BY 語句用於根據指定的列對結果集進行排序。ORDER BY 語句默認按照升序對記錄進行排序。若是您但願按照降序對記錄進行排序,可使用 DESC 關鍵字

order by字句的語法以下:

order by column_name1 [desc], column_name...

進行排序時默認按升序排序排列,若是強制按降序排序,則須要在列後使用desc關鍵字(與之對應的是asc關鍵字,用不用該關鍵字的效果徹底同樣,由於默認是按升序排列)。上面語法中設定排序列時可採用列名、序列名和列別名。以下SQL語句選出student_table表中的全部記錄,選出後按java_teacher列的升序排列、

select * 
from student_table
order by java_teacher;

若是須要按多列排序,則每列的asc、desc必須單獨設定。若是指定了多個排序列,則第一個排序列是首要排序列,只有當第一列中存在多個相同值時,第二個排序纔會起做用。若是SQL語句先按java_teacher列的降序排序,當java_teacher列的值相同按student_name列的升序排列

select * 
from student_table
order by java_teacher desc, student_name;

數據庫函數

每一個數據庫都會在標準的SQL基礎上擴展一些函數,這些函數用於進行數據處理或複雜計算,他們一般對一組數據進行計算,獲得最終須要的輸出結果。函數通常都會有一個或者多個輸入,這些輸入被稱爲函數的參數,函數內部會對這些參數進行判斷和計算,最終只有一個值做爲返回值。函數能夠出如今SQL語句中的各個位置,比較經常使用的位置是select以後的where子句中

根據函數對多行數據的處理方式,函數被分爲單行函數和多行函數,單行函數對每行輸入值單獨計算,每行獲得一個計算結果返回給用戶;多行函數對多行輸入值總體計算,最後只會獲得一個結果
clipboard.png

SQL中的函數和java語言中的方法有點類似,但SQL中的函數是獨立的程序單元,也就是說,調用函數時無需使用任何類、對象做爲調用者,而是直接執行函數。以下:

function_name(arg1,arg2...)

多行函數也稱爲彙集函數、分組函數,主要用於完成一些統計功能,在大部分數據庫中基本相同。但不一樣數據庫中的單行函數差異很是大,MySQL中的單行函數具備以下特徵

  • 單行函數的參數能夠是變量、常數或數據列。單行函數能夠接收多個參數,但只返回一個值

  • 單行函數會對每行單獨起做用,每行(可能包括多個參數)返回一個結果

  • 使用單行函數能夠改變參數的數據類型。單行函數支持嵌套使用,即內層函數的返回值是外層函數的參數

MySQL的單行函數分類如圖所示
clipboard.png

MySQ數據庫的數據類型大體分爲數值型、字符型、和日期時間型。因此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;

# 爲指定日期添加必定的時間,在這種用法下interval是關鍵字,須要一個數值還有一個單位
select DATE_ADD('1998-01-02', interval 2 MONTH);

# 獲取當前日期
select CURDATE();

# 獲取當前時間
select curtime();

# 下面的MD5是MD5加密函數
select MD5('testing');

MySQL提供了以下幾個處理null的函數

  • ifnull(expr1, expr2):若是expr1爲null,則返回expr2,不然返回expr1

  • nullif(expr1, expr2):若是expr1和expr2相等,則返回null,不然返回expr1

  • if(expr1, expr2, expr3):有點相似於?:三目運算符,若是expr1爲true,不等於0,且不等於null,則返回expr2,不然返回expr3

  • isnull(expr1):判斷expr1是否爲null,若是爲null則返回true,不然返回false

# 若是student_name列爲null,則返回'沒有名字'
select ifnull(student_name, '沒有名字')
from student_table;

# 若是CTO_name列爲'吳局',則返回null
select nullif(CTO_name, '吳局')
from CTO_table;

# 若是student_name列爲null,則返回'沒有名字',不然返回'有名字'
select if(isnull(student_name), '沒有名字', '有名字')
from student_table;

case函數

case函數,流程控制函數。case函數有兩個用法

case函數第一個用法的語法

case value
when compare_value1 then result1
when compare_value2 then result2
...
else result
end

case函數用value和後面的compare_value一、compare_value二、...依次進行比較,若是value和指定的compare_value1相等,則返回對應的result1,不然返回else後的result

# 若是java_teacher爲1,則返回'Java老師',爲2返回'Spring老師',不然返回'其餘老師'
select student_name, case java_teacher
when 1 then 'Java老師'
when 2 then 'Spring老師'
else '其餘老師'
end
from student_table;

case函數第二個用法的語法

case
when condition1 then result1
when condition2 then result2
...
else result
end

condition返回boolean值的條件表達式

# id小於3的爲初級工程師,3~6爲中級工程師,其餘爲高級工程師
select employees_name, case
when employees_id <= 3 then '初級工程師'
when employees_id <= 6 then '中級工程師'
else '高級工程師'
end
from employees_table;

分組和組函數

組函數也就是前面提到的多行函數,組函數是將一組做爲總體計算,每組記錄返回一個結果,而不是每條記錄返回一個結果

  • avg([distinct|all]expr):計算多行expr平均值,其中expr能夠是變量、常量或者數據列,但其數據類型必須是數值型。使用distinct代表不計算重複值;all代表須要計算重複值

  • count({*|[distinct|all] expr}):計算多行expr的總條數,其中expr能夠是變量、常量或者數據列,但其數據類型必須是數值型。用星號(*)表示統計該表內的記錄行數

  • max(expr):計算多行expr的最大值

  • min(expr):計算多行expr的最小值

  • sum([distanct|all]expr):計算多行expr的總和

# 計算student_table表中的記錄條數
select count(*)

# 計算java_teacher列總共有多少個值
select count(distinct java_teacher)

# 統計全部student_id 的總和
select sum(student_id)

# 計算的結果是20 * 記錄的行數
select sum(20)

# 選出student_table表中student_id最大的值
select max(student_id)

# 選出student_table表中student_id最小的值
select min(student_id)

# 由於sum裏的expr是常量23,因此每行的值都相同
# 使用distinct強制不計算重複值,因此下面計算結果爲23
select sum(distinct 23)

# 使用count統計記錄行數,null不會被計算在內
select count(student_name)

# 對於可能出現null的列,可使用ifnull函數來處理該列
# 計算java_teacher列全部記錄的平均值
select avg(ifnull(java_teacher, 0))

from student_table;

# distinct和*不可同時使用

group by語句

組函數會把全部記錄當成一組,爲了對記錄進行顯式分組,能夠在select語句後使用group by子句後一般跟一個或多個列名,代表查詢結果根據一列或多列進行分組——當一列或多列組合的值徹底相同時,系統會把這些記錄當成一組

SQL GROUP BY 語法

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
# count(*)將會對每組獲得一個結果
select count(*)
from student_table
# 將java_teacher列值相同的記錄當成一組
group by java_teacher;

若是對多列進行分組,則要求多列的值徹底相同纔會被當成一組

# count(*)將會對每組獲得一個結果
select count(*)
from student_table
# 將java_teacher、student_name兩列的值徹底相同時纔會被當成一組
group by java_teacher, student_name;

having語句

若是須要對分組進行過濾,則應該使用having子句,having子句後面也是一個條件表達式,只有知足該條件表達式的分組纔會被選出來。having子句和where子句很是容易混淆,它們都有過濾功能,但它們有以下區別

  • 不能在where子句中過濾組,where子句僅用於過濾行。過濾組必須使用having子句

  • 不能在where子句中使用組函數,having子句纔可以使用組函數

在SQL中增長HAVING子句緣由是,WHERE關鍵字沒法與合計函數一塊兒使用
SQL HAVING 語法

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value
select *
from student_table
group by java_teacher
# 對組進行過濾
having count(*) >2;

多表鏈接查詢

如下book與student數據表:
clipboard.pngclipboard.png

交叉鏈接(cross join)

交叉鏈接無須任何鏈接條件。返回左表中的全部行,左表中的每一行與右表中的全部行組合。交叉聯接也稱做笛卡爾積

select * 
from book as a 
# cross join交叉鏈接,至關於廣義笛卡爾積
cross join stu as b 
order by a.id

clipboard.png

天然鏈接

天然鏈接會以兩個表中的同名列做爲鏈接條件;若是兩個表沒有同名列,則天然鏈接與交叉鏈接效果徹底同樣——由於沒有鏈接條件。

select s.*, teacher_name
from student_table s
# natural join 天然鏈接使用兩個表中的同名列做爲鏈接條件
natural join teacher_table t;

在鏈接條件中使用等於(=)運算符比較被鏈接列的列值,但它使用選擇列表指出查詢結果集合中所包括的列,並刪除鏈接表中的重複列

使用using子句的鏈接

using子句能夠指定一列或多列,用於顯示指定兩個表中的同名列做爲鏈接條件。假設兩個表中有超過一列的同名列,若是使用natural join,則會把全部的同名列當成鏈接條件;使用using子句,就可顯示指定使用哪些同名列做爲鏈接條件

select s.*, teacher_name
from student_table s
# join鏈接另外一個表
join teacher_table t
using(teacher id);

使用on子句的鏈接

最經常使用的的鏈接方式,並且每一個on子句只指定一個鏈接條件。這意味着:若是須要進行N錶鏈接,則須要有N-1個join...on對

select s.*, teacher_name
from student_table s
# join鏈接另外一個表
join teacher_table t
# 使用on來指定鏈接條件
on s.java_teacher = t.teacher_id;

on子句的鏈接條件除了等值條件以外,也能夠是非等值條件

select s.*, teacher_name
from student_table s
# join鏈接另外一個表
join teacher_table t
# 使用on來指定鏈接條件
on s.java_teacher > t.teacher_id;
  • 等值鏈接:在鏈接條件中使用等於號(=)運算符比較被鏈接列的列值,其查詢結果中列出被鏈接表中的全部列,包括其中的重複列

  • 不等值鏈接:在鏈接條件使用除等於運算符之外的其它比較運算符比較被鏈接的列的列值。這些運算符包括>、>=、<=、<、!>、!<和<>

全外鏈接或者左、右外連接

這三種外鏈接分別使用left[outer]join、right[outer]join和full[outer]join,這三種外鏈接的鏈接條件同樣經過on子句來指定,既能夠是等值鏈接條件,也能夠是非等值鏈接條件

左聯接

是以左表爲基準,將a.stuid = b.stuid的數據進行鏈接,而後將左表沒有的對應項顯示,右表的列爲null

select * 
from book as a 
left join stu as b 
on a.sutid = b.stuid

clipboard.png

右鏈接

是以右表爲基準,將a.stuid = b.stuid的數據進行鏈接,然以將右表沒有的對應項顯示,左表的列爲null

select * 
from book as a 
right join stu as b 
on a.sutid = b.stuid

clipboard.png

全鏈接

完整外部聯接返回左表和右表中的全部行。當某行在另外一個表中沒有匹配行時,則另外一個表的選擇列表列包含空值。若是表之間有匹配行,則整個結果集行包含基表的數據值

clipboard.png

子查詢

子查詢就是在查詢語句中嵌套另外一個查詢,子查詢能夠支持多層嵌套。對於一個普通的查詢語句而言,子查詢能夠出如今兩個位置

  • form語句後當成數據表,這種用法也被稱爲行內視圖,由於該子查詢的實質就是一個臨時視圖

  • where條件後做爲過濾條件的值

使用子查詢時的注意點

  • 子查詢要用括號括起來

  • 把子查詢做爲數據表時(出如今from後),可爲其起別名,做爲前綴來限定數據列時,必須給子查詢起別名

  • 把子查詢做爲過濾條件時,將子查詢放在比較運算符的右邊,可加強查詢的可讀性

  • 把子查詢做爲過濾條件時,單行子查詢使用單行運算符,多行子查詢使用多行運算符

select *
# 把子查詢當成數據表
from (select * from student_table) t
where t.java_teacher > 1;
  • 把子查詢當成where條件中的值,若是子查詢返回單行、單列值,則被當成一個標量值使用,也就可使用單行記錄比較運算符

select *
from student_table
where java_teacher > 
# 返回單行、單列的子查詢能夠當成標量值使用
(select teacher_id 
from teacher_table 
where teacher_name = 'Pigeau');
  • 若是子查詢返回多個值,則須要使用in、any和all等關鍵字

  • in能夠單獨使用,此時能夠把子查詢返回的多個值當成一個值列表

select *
from student_table
where student_id in
(select teacher_id
from teacher_table);
  • any、all可與>、>=、<、<=、<>、=等運算符結合使用。與any結合表示大於、大於等於、小於、小於等於、不等於、等於其中任意一個值;與all結合表示大於、大於等於、小於、小於等於、不等於、等於所有值

  • =any與in的做用相同

select *
from student_table
where student_id =
any(select teacher_id
from teacher_table);
  • <ANY只要小於值列表中的最大值便可,>ANY只要大於值列表中的最小值便可。<ALL要求小於值列表中的最小值,>ALL要求大於值列表中的最大值

# 選出student_table表中student_id大於teacher_table表中全部teacher_id的記錄
select *
from student_table
where student_id >
all(select teacher_id
from teacher_table);
  • 還有一種子查詢能夠返回多行、多列,此時where子句中應該有對應的數據列,並使用圓括號將多個數據列組合起來

select *
from student_table
where (student_id, student_name)
=any(select teacher_id, teacher_name
from teacher_table);

集合運算

爲了對兩個結果集進行集合運算,這兩個結果集必須知足以下條件

  • 兩個結果集所包含的數據列的數量必須相等

  • 兩個結果集所包含的數據列的數據類型也必須一一對應

union運算

union運算的語法格式

select 語句 union select 語句

查詢全部教師的信息和主鍵小於4的學生信息

# 查詢結果包含兩列,第一列爲int類型,第二列爲varchar類型
select * from teacher_table
union
select student_id , student_name from student_table;

minus運算

minus運算的語法格式,MySQL實則不支持這種運算

select 語句 minus select 語句

從全部學生記錄中「減去」老師記錄的ID相同、姓名相同的記錄,則可進行以下的minus運算

select student_id, student_name from student_table
minus
# 兩個結果集的數據列的數量相等,數據類型一一對應,能夠進行minus運算
select teacher_id, teacher_name from teacher_table;

intersect運算

intersect運算的語法格式

select 語句 intersect select 語句

找出學生記錄中與老師記錄中的ID相同、姓名相同的記錄

select student_id, student_name from student_table
intersect
# 兩個結果集的數據列的數量相等,數據類型一一對應,能夠進行intersect運算
select teacher_id, teacher_name from teacher_table;
相關文章
相關標籤/搜索