摘要:數據庫管理系統的全稱是,簡稱。命令的語法表名數據庫約束約束是表上強制執行的數據校驗規則,約束主要用于保證數據庫里數據的完整性。
SQL語句是對所有關系數據庫都通用的命令語法,而JDBC API只是執行SQL語句的工具,JDBC允許對不同的平臺、不同的數據庫采用相同的編程接口來執行SQL語句
關系數據庫基本概念和MySQL基本命令數據庫僅僅是存放用戶數據的地方。當用戶訪問、操作數據庫中的數據時,就需要數據庫管理系統的幫助。數據庫管理系統的全稱是Database Management System,簡稱DBMS。把數據庫和數據庫管理系統籠統地稱為數據庫,通常所說的數據庫既包括存儲用戶數據的部分,也包括管理數據庫的管理系統
DBMS是所有數據的知識庫,它負責管理數據的存儲、安全、一致性、并發、恢復和訪問等操作。DBMS有一個數據字典(也稱為系統表),用于存儲它擁有的每個事務的相關信息,例如名字、結構、位置和類型,這種關于數據的數據也稱為元數據
在數據庫的發展歷史中,按時間順序主要出現了如下幾種類型的數據庫系統:
網狀型數據庫
層次型數據庫
關系數據庫
面向對象數據庫
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)數據庫對象
數據庫里的幾種常見的數據庫對象
創建表的語法create table [模式名.] 表名 ( # 可以定義有多個列定義 columnName1 datatype [default expr] , ... )
每個列定義之間以英文逗號(,)隔開,最后一個列定義不需要使用英文逗號,而是直接以括號結束
列名放在前面,列類型放在后面。如果要指定列的默認值,則使用default關鍵字,而不是使用等號(=)
使用子查詢建表語句,可以在建表的同時插入數據。子查詢建表的語法
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語句最簡單的功能如圖所示
單表查詢的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中比較運算符、邏輯運算符的優先級
執行查詢后的結果默認按插入順序排序;如果需要在查詢結果按某列值的大小進行排序,則可以使用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子句中
根據函數對多行數據的處理方式,函數被分為單行函數和多行函數,單行函數對每行輸入值多帶帶計算,每行得到一個計算結果返回給用戶;多行函數對多行輸入值整體計算,最后只會得到一個結果
SQL中的函數和java語言中的方法有點相似,但SQL中的函數是獨立的程序單元,也就是說,調用函數時無需使用任何類、對象作為調用者,而是直接執行函數。如下:
function_name(arg1,arg2...)
多行函數也稱為聚集函數、分組函數,主要用于完成一些統計功能,在大部分數據庫中基本相同。但不同數據庫中的單行函數差別非常大,MySQL中的單行函數具有如下特征
單行函數的參數可以是變量、常數或數據列。單行函數可以接收多個參數,但只返回一個值
單行函數會對每行多帶帶起作用,每行(可能包括多個參數)返回一個結果
使用單行函數可以改變參數的數據類型。單行函數支持嵌套使用,即內層函數的返回值是外層函數的參數
MySQL的單行函數分類如圖所示
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_value1、compare_value2、...依次進行比較,如果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數據表:
交叉連接無須任何連接條件。返回左表中的所有行,左表中的每一行與右表中的所有行組合。交叉聯接也稱作笛卡爾積
select * from book as a # cross join交叉連接,相當于廣義笛卡爾積 cross join stu as b order by a.id自然連接
自然連接會以兩個表中的同名列作為連接條件;如果兩個表沒有同名列,則自然連接與交叉連接效果完全一樣——因為沒有連接條件。
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右連接
是以右表為基準,將a.stuid = b.stuid的數據進行連接,然以將右表沒有的對應項顯示,左表的列為null
select * from book as a right join stu as b on a.sutid = b.stuid全連接
完整外部聯接返回左表和右表中的所有行。當某行在另一個表中沒有匹配行時,則另一個表的選擇列表列包含空值。如果表之間有匹配行,則整個結果集行包含基表的數據值
子查詢子查詢就是在查詢語句中嵌套另一個查詢,子查詢可以支持多層嵌套。對于一個普通的查詢語句而言,子查詢可以出現在兩個位置
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);
# 選出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;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66467.html
摘要:系統默認集成了很多開發工具其中就包括所需要的一些軟件工具下面我們將搭建最簡單的開發環境每一步都會驗證上一步的操作結構請一步一步跟我一起搭建吧服務器之是一款服務器用于運行文件除了外也可以是服務器默認情況下已經預裝了服務自然不用服務器了現在什么 Mac 系統默認集成了很多開發工具,其中就包括 php 所需要的一些軟件工具. 下面我們將搭建最簡單的 php 開發環境,每一步都會驗證上一步的操...
摘要:系統默認集成了很多開發工具其中就包括所需要的一些軟件工具下面我們將搭建最簡單的開發環境每一步都會驗證上一步的操作結構請一步一步跟我一起搭建吧服務器之是一款服務器用于運行文件除了外也可以是服務器默認情況下已經預裝了服務自然不用服務器了現在什么 Mac 系統默認集成了很多開發工具,其中就包括 php 所需要的一些軟件工具. 下面我們將搭建最簡單的 php 開發環境,每一步都會驗證上一步的操...
閱讀 3566·2021-08-02 13:41
閱讀 2413·2019-08-30 15:56
閱讀 1523·2019-08-30 11:17
閱讀 1179·2019-08-29 15:18
閱讀 583·2019-08-29 11:10
閱讀 2679·2019-08-26 13:52
閱讀 512·2019-08-26 13:22
閱讀 2954·2019-08-23 15:41