上篇回顧:聊聊數據庫~SQL環境篇
擴展:為用戶添加新數據庫的權限
PS:先使用root創建數據庫,然后再授權grant all privileges on 數據庫.* to 用戶名@"%" identified by "密碼";
並刷新flush privileges;
查看權限:show grants for dnt;
效果:
1.3.MySQL部署
之前有園友說,為啥不順便說說UbuntuServer
的部署呢?呃。。。一般來說公司服務器都是CentOS
的占大多數,然后UbuntuServer
更多的是個人雲服務比較多(推薦初創公司使用),畢竟它們兩個系統追求的不太一樣,一個是追求穩(部署麻煩),一個是追求軟件盡量新的情況下穩定(更新太快)
那么長話短說,步入正軌:
1.Ubuntu最常見的包問題
Ubuntu不得不說的就是這個apt
出問題的處理 :(換源就不說了/etc/apt/sources.list
)
# 一般刪除這幾個鎖文件,然后再重新配置下就可以了
sudo rm /var/lib/dpkg/lock
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/apt/lists/lock
sudo rm /var/cache/apt/archives/lock
# 簡寫(千萬注意空格,不然你就是rm -rf / + 跑路了)
# sudo rm /var/lib/apt/lists/lock /var/cache/apt/archives/lock /var/lib/dpkg/lock /var/lib/dpkg/lock-frontend
# 重新配置下
sudo dpkg --configure -a
2.安裝注意(Ubuntu的特點就是使用起來簡單)
Ubuntu
推薦使用MySQL
(畢竟同是5.x
用起來基本上差不多,安裝過程和之前說的CentOS 下 MariaDB
差不多,所有命令前加個sudo
)
1.安裝比較簡單:sudo apt install mysql-server -y
2.允許遠程連接:注釋掉 bind-address=127.0.0.1
(/etc/mysql/mysql.conf.d/mysqld.cnf
)
PS:常用配置(/etc/mysql/mysql.conf.d/mysqld.cnf
)
3.關於為什么是這個路徑的說明:sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
4.所有配置修改都需要重新啟動下:sudo systemctl restart mysql
5.第一次初始化和MariaDB不太一樣:sudo mysql_secure_installation
(其他一路y
即可)
需要選下你設置root密碼的復雜度:(一般1就可以了,就算設置再復雜,入了系統也是虛的)
PS:可以看看拓展文章:Ubuntu16安裝mysql5.7未提示輸入密碼,安裝后修改mysql默認密碼 和 【不推薦】修改mysql密碼策略
6.然后輸入密碼你就可以登錄了sudo mysql -uroot -p
(PS:你直接sudo mysql
也可以直接登錄)
這邊我就不像上節課一步步演示了,直接授權和創建一步走了grant all privileges on 數據庫.* to "用戶名"@"%" identified by "復雜密碼";
7.記得flush privileges;
刷新一下系統表
PS:數據文件一般都是放在/var/lib/mysql
中
課后拓展:
淺析MySQL 8忘記密碼處理方式
https://www.cnblogs.com/wangjiming/p/10363357.html
MySQL5.6更改datadir數據存儲目錄
https://www.cnblogs.com/ding2016/p/7644675.html
1.4.基礎(MySQL and SQLServer)
腳本示例:https://github.com/lotapp/BaseCode/tree/master/database/SQL
PS:在MySQL中運行SQL腳本:mysql < script.sql
后面代碼優先使用通用SQL(MySQL
和SQLServer
(MSSQL
)通用的SQL語句),逆天好幾年沒用SQLServer
了(幾年前講過MSSQL),這邊就一帶而過(歡迎糾錯)
PS:后面MariaDB
我也直接說成MySQL
了(有區別的地方我會說下,畢竟也是MySQL的分支,相似度還是很大的)
1.概念
1.1.傳統概念
來說說傳統概念:
- 關系型數據庫中的關系:表(行、列)
- 設計范式:
- 第1范式:字段是原子性的
- 第2范式:每個表需要一個主鍵
- 第3范式:任何表都不應該有依賴於其他非主鍵表的字段
- DDL:數據定義語言(Data Defination Language)
create、drop、alter
- DML:數據操作語言(Data Manipulation Language)
insert、delete、update、select
- DCL:數據庫控制語言(Data Control Language)
grant
(授權)、revoke
(回收)
PS:CURD
(定義了用於處理數據的基本原子操作):創建(Create)更新(Update)讀取(Retrieve)刪除(Delete)操作
1.2.常見組件
關系型數據庫常見組件:
- 數據庫:database
- 表:table
- 行:row
- 列:column
- 索引:index
- 視圖:view
- PS:如果有
數據庫遷移
的需求則不建議使用 - PS:MySQL的視圖功能不是特別完素,盡量不使用
- PS:如果有
- 存儲過程:procedure
- 存儲函數:function
- 觸發器:trigger
- 事件調度器:event、scheduler
- 用戶:user
- 權限:privilege
PS:MySQL常見的文件類型:
- 數據:數據文件、索引文件
- 日記:錯誤日志、查詢日志、慢查詢日志、二進制日志、(重做日志、撤銷日志、中繼日志)
2.MySQL標准存儲引擎
2.1.MySQL
先說說MySQL
標准存儲引擎(表類型
):
MyISAM
:只支持表級鎖
,不支持事務
InnoDB
:支持事務
、間隙鎖
、行鎖
等等
2.2.MariaDB
首先是插件式存儲引擎(表類型
)的改進和擴充 PS:其實也就是支持更多的存儲引擎(包括自定義的)
MariaDB
對標准存儲引擎進行了改造升級:
MyISAM
==>Aria
:支持崩潰后的恢復InnoDB
==>XtraDB
:優化存儲性能
還進行了很多擴展並開發了新的功能(也提供了很多測試工具),比如添加一些NoSQL
的功能(SQLServer
也擴展了NoSQL
)
3.創建、刪除(數據庫 | 表)
字段類型(含異同)
官方文檔:
https://mariadb.com/kb/en/library/data-types
https://dev.mysql.com/doc/refman/5.7/en/data-types.html
以MariaDB
為例,簡單列舉下常用類型:(傾體說明和MySQL
不一樣)
- 字符型:
- 定長字符型:
char()
:不區分字符大小寫類型的字符串,max:255個字符
- binary():區分字符大小寫類型的二進制字符串
- 變長字符型:
varchar()
: 不區分字符大小寫類型的字符串- max:65535(2^16 - 1)個字節(
utf8編碼下最多支持21843個字符
) - 可以理解為
SQLServer
的nvarchar
- max:65535(2^16 - 1)個字節(
- varbinary():區分字符的大小寫類型的二進制字符串
- 對象存儲:
text
:不區分字符大小寫的不限長字符串- 最大長度為65,535(2^16 - 1)個字符
- 如果值包含多字節字符,則有效最大長度減少
- blob:區分字符大小寫的不限長二進制字符串
- 內建類型:(不推薦使用)
- enum:單選字符串數據類型,適合表單中的
單選值
- set:多選字符串數據類型,適合表單的
多選值
- PS:
MySQL系
獨有,SQLServer
沒有
- enum:單選字符串數據類型,適合表單中的
- 定長字符型:
- 數值型:
- 精確數值型:
- 整型:int
- bool:布爾類型(MySQL沒有)
- PS:
SQLServer
是bit
- 相當於
MySQL
的tinyint(1)
- PS:
tinyint
:微小整型(1字節,8位)[-2^7, 2^7)
(-128 ~ 127
)- 無符號:
[0, 2^8)
(0 ~ 255
)
- smallint(2bytes,16bit):小整型
- 無符號:
0 ~ 65535
- 無符號:
- mediumint(3bytes,24位):中等整型
PS:SQLServer中沒這個類型
int
(4bytes,32bit)[-2^31, 2^31)
,[-2147483648,2147483648)
- 無符號:
[0, 2^32)
,[0,4294967296)
bigint
(8bytes,64bit)[-2^63, 2^63)
- 無符號:
[0, 2^64)
- bool:布爾類型(MySQL沒有)
- 整型:int
- 浮點類型:
- float:單精度浮點數(4字節)
double
:雙精度浮點數(8字節)- PS:
SQLServer
的float
類型相當於MySQL
的double
- PS:
decimal
:精確小數類型(比double更精確)- 錢相關用的比較多:
decimal(位數,小數點位數)
- eg:
decimal(2,1)
=>x.x
- 錢相關用的比較多:
- 精確數值型:
- 日期和時間類型:(和
MySQL
一樣)- date:日期(3bytes)
- time:時間(3bytes)
- year:年
- eg:
year(2)
:00~99(1bytes)
- eg:
year(4)
:0000~9999(1bytes)
- PS:
SQLServer沒有這個類型
- eg:
datetime
:既有時間又有日期(8bytes)timestamp
:時間戳(4bytes)【精度更高】
- 修飾符:
- 所有類型都適用:
- 是否為null:
null
|not null
- 默認值:
default xxx_value
- 主 鍵:
primary key
- 唯一鍵:
unique key
- 是否為null:
- 數值類型適用:
- 無符號:
unsigned
(MySQL系獨有) - 自增長:
auto_increment
(一般只用於整型,MSSQL是identity
)- 獲取ID:
last_insert_id()
- 獲取ID:
- 無符號:
- PS:多列設置:
- 主鍵:
primary key(xx,...)
- 唯一鍵:
unique key(xx,...)
- 索引:
index index_name (xx,...)
- 主鍵:
- 所有類型都適用:
PS:現在新版本數據庫兼容了SQLServer的nvarchar
寫法(執行成功后數據類型變成varchar
)【不推薦使用】
課后拓展:
MySQL:char、varchar、text的區別
https://dev.mysql.com/doc/refman/5.7/en/char.html
https://blog.csdn.net/brycegao321/article/details/78038272
3.1.MySQL
知識點概括:
- 創建數據庫:
create database [if not exists] db_name;
- 刪除數據庫:
drop database [if exists] db_name;
- 創建表:
create table [if not exists] tb_name(列名1,數據類型 修飾符,列名2,數據類型 修飾符);
- 刪除表:
drop table [if exists] db_name.tb_name;
- 修改表:
- 字段
- 添加字段:add
alter table tb_name add 列名 數據類型 修飾符 [first | after 列名];
- PS:SQLServer沒有
[first | after 列名]
- 修改字段:alter、change、modify
- 修改字段名:
alter table tb_name change 舊列名 新列名 類型 類型修飾符
- 修改字段類型:
alter table tb_name modify 列名 類型 類型修飾符
- 添加默認值:
alter table tb_name alter 列名 set default df_value
- 修改字段名:
- 刪除字段:drop
alter table tb_name drop 字段名
- 添加字段:add
- 索引
- 添加索引:add(常用:
create index index_name on tb_name(列名,...);
)alter table tb_name add index [ix_name] (列名,...);
- 添加唯一鍵:
alter table tb_name add unique [uq_name] (列名,列名2...);
- PS:不指定索引名字,默認就是第一個字段名
- 刪除索引:drop(常用:
drop index index_name on tb_name
)alter table tb_name drop index index_name;
- 刪除唯一鍵:
alter table tb_name drop index uq_name;
- PS:唯一鍵的索引名就是第一個列名
- PS:一般在經常用做查詢條件的列設置索引
- 添加索引:add(常用:
- 表選項
- 可以參考這篇文章:
https://www.cnblogs.com/huangxm/p/5736807.html
- 可以參考這篇文章:
- 字段
SQL Model
:定義MySQL對約束的響應行為:- 會話修改:
- mysql>
set [session] sql_model='xx_mode'
- mysql>
set @@session.sql_mode='xx_mode'
- PS:只在當前會話生效
- mysql>
- 全局修改:需要有權限,並且不會立即生效,對以后新建的會話生效(從全局繼承的)
- mysql>
set global sql_mode='xx_mode'
- mysql>
set @@global.sql_mode='xx_mode'
- PS:MySQL重啟后失效
- mysql>
- 配置修改:永遠生效:
- eg:
vi /etc/my.cnf
,在[mysqld]
下添加sql_mode='xx'
,然后重啟數據庫 - PS:從MySQL8開始,可通過
set persist
命令將全局變量的修改持久化到配置文件中- 持久化到
/var/lib/mysql/mysqld-auto.cnf
配置文件中 - eg:
set persist log_timestamps='SYSTEM';
(需要root權限)
- 持久化到
- eg:
- 常用mode:(阿里服務器默認是:
strict_trans_tables
)traditional
:使用傳統模型,不允許對非法值做插入操作strict_trans_tables
:對所有支持事物類型的表做嚴格約束strict_all_tables
:對所有表做嚴格約束- 查詢當前設置:
select @@sql_mode
- 詳情可以查看我之前寫的文章:https://www.cnblogs.com/dotnetcrazy/p/10374091.html
- 會話修改:
3.1.1.創建、刪除數據庫
-- 如果存在就刪除數據庫
drop database if exists dotnetcrazy;
-- 創建數據庫
create database if not exists dotnetcrazy;
3.1.2.創建、刪除表
-- 如果存在就刪除表
drop table if exists dotnetcrazy.users;
-- mysql> help create table(低版本的默認值不支持函數)
-- 創建表 create table users(字段名 類型 修飾符,...)
create table if not exists dotnetcrazy.users
(
id int unsigned auto_increment, -- 主鍵,自增長【獲取ID:last_insert_id()】
username varchar(20) not null,
password char(40) not null, -- sha1:40
email varchar(50) not null,
ucode char(36) not null,-- default uuid(), -- uuid
createtime datetime not null,-- default now(),
updatetime datetime not null,-- default now(),
datastatus tinyint not null default 0, -- 默認值為0
primary key (id), -- 主鍵可多列
unique uq_users_email (email),
index ix_users_createtime_updatetime (createtime, updatetime) -- 索引,不指定名字默認就是字段名
)
-- 表選項
-- engine = 'innodb', -- 引擎
-- character set utf8, -- 字符集
-- collate utf8_general_ci, -- 排序規則
;
3.1.3.修改表
-- 修改表 mysql> help alter table
-- 3.1.添加一列 alter table tb_name add 列名 數據類型 修飾符 [first | after 列名]
alter table dotnetcrazy.users
add uid bigint not null unique first; -- MSSQL沒有[first | after 列名]
-- 在email后面添加手機號碼列
-- 手機號不會用來做數學運算,varchar可以模糊查詢(eg:like ‘138%’)
-- 牽扯到國家代號時,可能出現+、-、()等字符,eg:+86
alter table dotnetcrazy.users
add tel varchar(20) not null after email;
-- 3.2.刪除一列 alter table tb_name drop 字段名
alter table dotnetcrazy.users
drop uid;
-- 3.3.添加索引 alter table tb_name add index [ix_name] (列名,...)
alter table dotnetcrazy.users
add index ix_users_ucode (ucode); -- 不指定名字默認就是字段名
-- add index (ucode, tel); -- 不指定索引名字,默認就是第一個字段名
-- 添加唯一鍵 alter table tb_name add unique [uq_name] (列名,列名2...)
alter table dotnetcrazy.users
add unique uq_users_tel_ucode (tel, ucode);
-- add unique (tel, ucode);-- 不指定索引名字,默認就是第一個字段名
-- 3.4.刪除索引 alter table tb_name drop index ix_name
alter table dotnetcrazy.users
drop index ix_users_ucode;
-- 刪除索引(唯一鍵) alter table tb_name drop index uq_name
alter table dotnetcrazy.users
drop index uq_users_tel_ucode;
-- drop index tel; -- 唯一鍵的索引名就是第一個列名
-- 3.5.修改字段
-- 1.修改字段名:`alter table tb_name change 舊列名 新列名 類型 類型修飾符`
-- 此時一定要重新指定該列的類型和修飾符
alter table dotnetcrazy.users
change ucode usercode char(36); -- default uuid();
-- 2.修改字段類型
alter table dotnetcrazy.users
modify username varchar(25) not null;
-- 3.添加默認值:`alter table tb_name alter 列名 set default df_value`
alter table dotnetcrazy.users
alter password set default '7c4a8d09ca3762af61e59520943dc26494f8941b';
3.2.SQLServer
示例服務器:SQLServer 2014
3.2.1.創建、刪除數據庫
use master
--存在就刪除
if exists(select *
from sysdatabases
where Name = N'dotnetcrazy')
begin
drop database dotnetcrazy
end
--創建數據庫(簡化版:create database dotnetcrazy)
create database dotnetcrazy
on primary --數據庫文件,主文件組
(
name ='dotnetcrazy_Data', --邏輯名
size =10 mb, --初始大小
filegrowth =10%, --文件增長
maxsize =1024 mb, --最大值
filename =N'D:\Works\SQL\dotnetcrazy_data.mdf'--存放路徑(包含文件后綴名)
)
log on --日記
(
name ='dotnetcrazy_Log',
size =5 mb,
filegrowth =5%,
filename =N'D:\Works\SQL\dotnetcrazy_log.ldf'
);
-- 切換數據庫
use dotnetcrazy;
3.2.2.創建、刪除表
--存在就刪除表
if exists(select *
from sysobjects
where name = N'users')
begin
drop table users
end
-- dotnetcrazy.dbo.users
create table users
(
id int identity, -- 主鍵,自增長
username nvarchar(20) not null,
email varchar(50) not null,
password char(40) not null, -- sha1
ucode char(36) not null default newid(), -- guid
createtime datetime not null default getdate(),
updatetime datetime not null default getdate(),
datastatus tinyint not null default 0, -- 默認值為0
primary key (id), -- 主鍵可多列
unique (email),
index ix_users_createtime_updatetime (createtime, updatetime) -- 索引
);
3.1.3.修改表
-- 3.1.添加一列 alter table tb_name add 列名 數據類型 修飾符
-- 在email后面添加手機號碼列
alter table users
add tel varchar(20) not null;
-- 3.1.1.添加含唯一鍵的列
-- 先添加列
alter table users
add uid bigint not null
-- 再添加約束 alter table tb_name add constraint uq_name
alter table users
add constraint uq_users_uid unique (uid); -- 自定義名稱
-- 3.1.2.定義和約束一步走(系統設置名字)
-- alter table users
-- add uid bigint not null unique; -- 默認名稱
-- 3.2.含唯一鍵的列
-- 3.2.1.刪除約束 alter table tb_name drop constraint uq_name
if exists(select *
from sysobjects
where name = 'uq_users_uid')
alter table users
drop constraint uq_users_uid;
-- 3.2.2.刪除列 alter table tb_name drop column 字段名
alter table users
drop column uid;
-- 3.3.修改字段
-- 3.3.1.修改列名:exec sp_rename '表名.舊列名','新列名';
exec sp_rename 'users.ucode', 'usercode';
-- 3.3.2.修改字段類型
alter table users
alter column username varchar(25) not null;
-- 3.3.3.添加默認值:`alter table tb_name alter 列名 set default df_value`
alter table users
add default '7c4a8d09ca3762af61e59520943dc26494f8941b' for password;
知識回顧:
課后拓展:
SQLServer突破內存限制:
https://www.cnblogs.com/zkweb/p/6137423.html
官方demo:
https://www.microsoft.com/en-us/sql-server/developer-get-started/python/ubuntu
官方文檔:
https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-overview?view=sql-server-2017
PS:SQL Server默認端口為TCP 1433
3.3.區別
簡單列舉下上面的區別(歡迎補充):
- MySQL自增長是
auto_increment
,MSSQL是identity
- MySQL可以設置無符號
unsigned
,MSSQL不可以直接設置無符號整型,需要通過約束之類的來限制 alter table
的時候,MSSQL沒有[first | after 列名]
,而且語法差別也挺大
4.增刪改查(CURD)
4.1.MySQL
select語句執行流程:
from 表
[inner|left|right] join 表 on 條件
where 條件
- 對select的結果進行過濾
group by 字段
- 根據指定條件把查詢結果進行
分組
,以用做聚合
運算
- 根據指定條件把查詢結果進行
having 條件
- 對分組聚合運算(
group by
)后的結果進行過濾
- 對分組聚合運算(
order by 字段 [asc|desc]
- 根據指定字段對查詢結果進行排序(默認升序
asc
)
- 根據指定字段對查詢結果進行排序(默認升序
select 字段
limit [偏移量,]顯示數量
- 顯示多少條數據 | 分頁顯示
增刪改
-- 4.1.插入 help insert
-- 自增長主鍵和默認值的字段可以不寫
insert into dotnetcrazy.users(username, password, email, tel, usercode, createtime, updatetime, datastatus)
values ('dnt', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'dnt@qq.com', '18738002038', uuid(), now(), now(), 1);
-- 批量插入
insert into dotnetcrazy.users(username, password, email, tel, usercode, createtime, updatetime, datastatus)
values('xxx', '7c4a8d09ca3762af61e59520943dc26494f8942b', 'xxx@qq.com', '13738002038', uuid(), now(), now(), 0),('mmd', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'mmd@qq.com', '13718002038', uuid(), now(), now(), 1),('小張', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'zhang@qq.com', '13728002038', uuid(), now(), now(), 1);
-- 4.2.修改 help update
update dotnetcrazy.users
set datastatus=99,
updatetime = now()
where username = 'mmd'; -- 一定要有where條件!開發中一般都是先寫where條件再寫update
-- 4.3.刪除
-- 刪除數據(自增長不重置)help delete;
delete
from dotnetcrazy.users
where datastatus = 0;
-- 刪除全部數據(自增長重置)help truncate;
truncate table dotnetcrazy.users;
查詢
-- 數據構造見附錄
-- 4.4.查詢 help select
-- 查詢來源url(去重后)
select distinct url
from file_records;
-- 查詢來源url(分組方式)
select url
from file_records
group by url;
-- 分別統計一下url出現的次數(分組+聚合)
-- 分組一般都和聚合函數一起使用
select url, count(*) as count
from file_records
group by url;
-- 分別統計一下url出現的次數,已經刪除的文件不算進去
select url, count(*) as count
from file_records
group by url
having count > 3; -- 在group by的結果上篩選
-- 分別統計一下url出現的次數並查出對應的id
select group_concat(id) as ids, url
from file_records
group by url;
-- 內連接查詢 innet join tb_name on 關聯條件
select file_records.id,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
inet_ntoa(file_records.ip) as ip,
file_records.url
from users
inner join file_records on file_records.user_id = users.id -- 連接條件
where users.datastatus = 1
and file_records.datastatus = 1
order by file_records.file_name desc; -- 文件名降序排序
-- MySQL沒有`select top n`語法,可以使用 limit來實現,eg:top 5
select *
from file_records
limit 5; -- limit 0,5
-- 分頁查詢
-- page:1,count=5 ==> 0,5 ==> (1-1)*5,5
-- page:2,count=5 ==> 5,5 ==> (2-1)*5,5
-- page:3,count=5 ==> 10,5 ==> (3-1)*5,5
-- 推理:limit (page-1)*count,count
select file_records.id,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
inet_ntoa(file_records.ip) as ip,
file_records.url
from file_records
inner join users on file_records.user_id = users.id
limit 0,5;
-- limit后面跟表達式就會報錯
select file_records.id,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
inet_ntoa(file_records.ip) as ip,
file_records.url
from file_records
inner join users on file_records.user_id = users.id
limit 5,5;
-- limit (2-1)*5,5; -- limit錯誤寫法
-- limit要放在最后
select file_records.id,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
inet_ntoa(file_records.ip) as ip,
file_records.url
from file_records
inner join users on file_records.user_id = users.id
order by username desc, file_name desc
limit 10,5; -- 先order by排完序,然后再取第三頁的5個數據
-- 查找一下從來沒上傳過文件的用戶
-- right join:以右邊表(users)為基准連接
select file_records.id as fid,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
inet_ntoa(file_records.ip) as ip,
file_records.url
from file_records
right join users on file_records.user_id = users.id
where users.datastatus = 1
and file_records.id is null
order by username desc, file_name desc;
-- 自連接案例:
-- 二級聯動 p:province,c:city,a:area
-- 前端一般都會顯示省級信息,用戶選擇后可以獲得對應的二三級信息
select c.name, a.name
from city_infos as c
inner join city_infos as a on a.pcode = c.code
where c.pcode = '320000'; -- pcode設置為索引
-- 通過省名稱查詢
select p.name, c.name, a.name
from city_infos as c
inner join city_infos as p on c.pcode = p.code
inner join city_infos as a on a.pcode = c.code
where p.name = '江蘇省';
視圖
-- 簡單提一下視圖:
-- 創建視圖
create view view_userinfo as
select id, username, password, email, tel, datastatus
from dotnetcrazy.users;
-- 查詢視圖
select id, username, password, email, tel, datastatus
from dotnetcrazy.view_userinfo;
-- 刪除視圖
drop view if exists view_userinfo;
附錄:
知識點:
-- 把ip轉換成int
select inet_aton('43.226.128.3'); -- inet6_aton()
-- 把int轉換成ip
select inet_ntoa('736264195'); -- inet6_ntoa() ipv6
-- 將多個字符串連接成一個字符串
select concat(user_id, ',', file_name, ',', ip, ',', url) as concat_str
from file_records;
-- 將多個字符串連接成一個字符串+可以一次性指定分隔符
select concat_ws(',', user_id, file_name, ip, url) as concat_str
from file_records;
-- 在有group by的查詢語句中,select指定的字段要么就包含在group by語句的后面,作為分組的依據,要么就包含在聚合函數中
-- group_concat():將group by產生的同一個分組中的值連接起來,返回一個字符串結果
select group_concat(file_name) as file_name, url, count(*)
from file_records
group by url;
-- having一般對group by的結果進行篩選,where是對原表進行篩選
select group_concat(file_name) as file_name, group_concat(url) as url, count(*) as count
from file_records
group by url
having count >= 3;
-- 四舍五入到指定位數
select round(3.12345, 4);
-- 存小數數據為了不損傷精讀一般都是轉成整數,eg:3.1415 ==> 整數:31415,倍數:10000
數據構造:
city_data.sql
:https://github.com/lotapp/BaseCode/blob/master/database/SQL/city2017.sql
-- 編號,文件名,文件MD5,Meta(媒體類型),當前用戶,請求IP,來源地址,請求時間,數據狀態
drop table if exists file_records;
create table if not exists file_records
(
id int unsigned auto_increment primary key,
file_name varchar(100) not null,
md5 char(32) not null,
meta_type tinyint unsigned not null default 1,
user_id int unsigned not null,
ip int unsigned not null,
url varchar(200) not null default '/',
createtime datetime not null, -- default now(),
datastatus tinyint not null default 0
);
-- 可以插入2~3次(方便下面演示)
insert into file_records(file_name, md5, meta_type, user_id, ip, url, createtime, datastatus)
values ('2.zip', '3aa2db9c1c058f25ba577518b018ed5b', 2, 1, inet_aton('43.226.128.3'), 'http://baidu.com', now(), 1),
('3.rar', '6f401841afd127018dad402d17542b2c', 3, 3, inet_aton('43.224.12.3'), 'http://qq.com', now(), 1),
('7.jpg', 'fe5df232cafa4c4e0f1a0294418e5660', 4, 5, inet_aton('58.83.17.3'), 'http://360.cn', now(), 1),
('9.png', '7afbb1602613ec52b265d7a54ad27330', 5, 4, inet_aton('103.3.152.3'), 'http://cnblogs.com', now(), 1),
('1.gif', 'b5e9b4f86ce43ca65bd79c894c4a924c', 6, 3, inet_aton('114.28.0.3'), 'http://qq.com', now(), 1),
('大馬.jsp', 'abbed9dcc76a02f08539b4d852bd26ba', 9, 4, inet_aton('220.181.108.178'), 'http://baidu.com', now(),
99);
4.2.SQLServer
select語句執行流程:
from 表
join類型 join 表 on 條件
where 條件
- 對select的結果進行過濾
group by 字段
- 根據指定條件把查詢結果進行
分組
,以用做聚合
運算
- 根據指定條件把查詢結果進行
having 條件
- 對分組聚合運算(
group by
)后的結果進行過濾
- 對分組聚合運算(
select distinct 字段
order by 字段 [asc|desc]
- 根據指定字段對查詢結果進行排序(默認升序
asc
)
- 根據指定字段對查詢結果進行排序(默認升序
top 多少行
- 類比
limit
- 類比
增刪改
-- 4.1.插入 help insert
-- 自增長主鍵和默認值的字段可以不寫
insert into dotnetcrazy.dbo.users(username, password, email, tel, usercode, createtime, updatetime, datastatus)
values ('dnt', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'dnt@qq.com', '18738002038', newid(), getdate(), getdate(),
1);
-- 批量插入 SQLServer一次批量插入最多1000行左右
insert into dotnetcrazy.dbo.users(username, password, email, tel, usercode, createtime, updatetime, datastatus)
values ('xxx', '7c4a8d09ca3762af61e59520943dc26494f8942b', 'xxx@qq.com', '13738002038', newid(), getdate(), getdate(), 0),
('mmd', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'mmd@qq.com', '13738002038', newid(), getdate(), getdate(), 1),
('小明', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'xiaoming@qq.com', '13718002038', newid(), getdate(), getdate(), 1),
('小張', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'zhang@qq.com', '13728002038', newid(), getdate(), getdate(), 1),
('小潘', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'pan@qq.com', '13748002038', newid(), getdate(), getdate(), 1),
('小周', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'zhou@qq.com', '13758002038', newid(), getdate(), getdate(), 1),
('小羅', '7c4a8d09ca3762af61e59520943dc26494f8941b', 'luo@qq.com', '13768002038', newid(), getdate(), getdate(), 1);
-- 4.2.修改 help update
update dotnetcrazy.dbo.users
set datastatus=99,
updatetime = getdate()
where username = 'mmd'; -- 一定要有where條件!開發中一般都是先寫where條件再寫update
-- 4.3.刪除
-- 刪除數據(自增長不重置)help delete;
delete
from dotnetcrazy.dbo.users
where datastatus = 0;
-- 刪除全部數據(自增長重置)help truncate;
truncate table dotnetcrazy.dbo.users;
查詢
-- 查詢來源url(去重后)
select distinct url
from file_records;
-- 查詢來源url(分組方式)
select url
from file_records
group by url;
-- 分別統計一下url出現的次數(分組+聚合)
-- 分組一般都和聚合函數一起使用
select url, count(*) as count
from file_records
group by url;
-- 分別統計一下url出現的次數,已經刪除的文件不算進去
select url, count(*) as count
from file_records
group by url
having count(*) > 3; -- 在group by的結果上篩選,★寫成count就不行了★
-- 分別統計一下url出現的次數並查出對應的id
-- SQLServer2017新增string_agg
select ids =(select stuff((select ',' + cast(id as varchar(20)) from file_records as f
where f.url = file_records.url for xml path ('')), 1, 1, '')),url from file_records
group by url;
-- 內連接查詢 innet join tb_name on 關聯條件
select file_records.id,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
file_records.ip,
file_records.url
from users
inner join file_records on file_records.user_id = users.id -- 連接條件
where users.datastatus = 1
and file_records.datastatus = 1
order by file_records.file_name desc; -- 文件名降序排序
-- 顯示前5個數據
select top 5 * from file_records;
-- 分頁查詢 第3頁,每頁5條
select *
from (select row_number() over (order by username desc, file_name desc) as id,
file_records.id as fid,
users.id as uid,
users.username,
users.email,
file_records.file_name,
file_records.md5,
file_records.ip,
file_records.url
from file_records
inner join users on file_records.user_id = users.id) as temp
where id > (3 - 1) * 5 and id <= 3 * 5;
-- 簡單提一下視圖:
-- 存在就刪除
if exists(select *
from sysobjects
where name = N'view_userinfo')
begin
drop view view_userinfo
end
-- 創建視圖
create view view_userinfo as
select id, username, password, email, tel, datastatus
from users;
-- 查詢視圖
select id, username, password, email, tel, datastatus
from view_userinfo;
附錄
知識點:
select getdate() as datatime, newid() as uuid;
-- 類似於concat的效果
select cast(id as varchar(20)) + ','
from file_records for xml path ('');
-- 移除多余的字符
-- STUFF(<character_expression>,<開始>,<長度>,<character_expression>)
-- 將字符串插入到另一個字符串中。它會刪除開始位置第一個字符串中的指定長度的字符,然后將第二個字符串插入到開始位置的第一個字符串中
select stuff((select ',' + cast(id as varchar(20))
from file_records for xml path ('')), 1, 1, '');
數據構造:
--存在就刪除表
if exists(select *
from sysobjects
where name = N'file_records')
begin
drop table file_records
end
-- 因為SQLServer的int沒有unsigned,所以推薦使用bigint
create table file_records
(
id bigint identity (1,1) primary key,
file_name varchar(100) not null,
md5 char(32) not null,
meta_type tinyint not null default 1,
user_id int not null,
ip bigint not null, -- 在程序中自行轉換
url varchar(200) not null default '/',
createtime datetime not null default getdate(),
datastatus tinyint not null default 0
);
-- 可以插入3次(方便下面演示)
insert into file_records(file_name, md5, meta_type, user_id, ip, url, createtime, datastatus)
values ('2.zip', '3aa2db9c1c058f25ba577518b018ed5b', 2, 1, 736264195, 'http://baidu.com', getdate(), 1),
('3.rar', '6f401841afd127018dad402d17542b2c', 3, 3, 736103427, 'http://qq.com', getdate(), 1),
('7.jpg', 'fe5df232cafa4c4e0f1a0294418e5660', 4, 5, 978522371, 'http://360.cn', getdate(), 1),
('9.png', '7afbb1602613ec52b265d7a54ad27330', 5, 4, 1728288771, 'http://cnblogs.com', getdate(), 1),
('1.gif', 'b5e9b4f86ce43ca65bd79c894c4a924c', 6, 3, 1914437635, 'http://qq.com', getdate(), 1),
('大馬.jsp', 'abbed9dcc76a02f08539b4d852bd26ba', 9, 4, 3702877362, 'http://baidu.com', getdate(), 99);
5.MySQL命令擴展:
- 命令幫助:
MySQL>
help 命令
- PS:版本查詢:
select version();
- PS:版本查詢:
- 查看字符集:
show character set;
- utf8:使用1~3bytes來表示一個Unicode字符(常用)
- utf8mb4:使用1~4bytes來表示一個Unicode字符(
Emoji表情
or不常用漢字
)
- 排序規則:
show collation;
- eg:
show collation where Collation like "%utf8%";
- eg:
- 查看引擎:
show engines;
InnoDB是默認存儲引擎
- 查看所有數據庫:
show databases;
- 切換數據庫:
use db_name;
- 查看所有表:
show tables;
- 顯示表狀態:
show table status;
- eg:
show table status like 'users';
- eg:
- 顯示表結構:
desc tb_name;
- 查看創建表時的SQL:
show create table tb_name;
- 顯示表的索引:
show indexes from tb_name
- 查看mysql數據文件目錄
show variables like '%dataDir%';
- 查詢當前會話的連接號:
select connection_id();
PS:\G可以豎排顯示
:show table status like 'users'\G
最后YY幾句:
- 沒使用
Linux
之前,我認為C#是最優美、性價比最高、最簡單的語言
,之后發現Python才是最簡單的語言
,C#只能是最優美、性價比最高的語言
- 現在准備接觸Golang,最終評價先待定吧
- 剛接觸MySQL發現SQLServer真的很方便,研究MySQL越深越發現==>平心而講:
- 對應開發人員來說,
MySQL
真的比SQLServer
方便 - 對於運維人員來說,
SQLServer
真的太方便了 - PS:中小企業如果沒有專門運維人員,還是推薦
SQLServer
,如果有運維人員或者團隊有點Linux
運維功底的還是選擇MySQL
吧
- 對應開發人員來說,
送大家一句話:思維局限在一個維度里,認知就會發生偏移,希望大家能夠勇於嘗試和突破~
因為時間問題之后的SQL案例就不對比演示了,直接全部MySQL
走起(之后只能說盡量加上SQLServer
版的演示)
下節預估:查詢優化
課外拓展:
MySQL在線IDE:phpMyAdmin
https://www.phpmyadmin.net/downloads/
MySQL最火工具:Navicat Premium
https://www.cnblogs.com/dotnetcrazy/p/9711198.html
MySQL最佳工具:dbForge Studio for MySQL
https://www.devart.com/dbforge/mysql/studio/download.html
【跨平台】SQLServer工具:SqlOps
https://www.cnblogs.com/dunitian/p/8045081.html
https://github.com/Microsoft/azuredatastudio/releases
【跨平台】都支持:JetBrains DataGrip 【推薦】
https://www.cnblogs.com/dotnetcrazy/p/9711763.html
MariaDB數據類型
https://www.w3cschool.cn/mariadb/mariadb_data_types.html
MySQL 數據類型
https://www.w3cschool.cn/mysql/mysql-data-types.html
(MariaDB)MySQL數據類型詳解和存儲機制
https://www.cnblogs.com/f-ck-need-u/archive/2017/10/25/7729251.html
Sql Server中的數據類型和Mysql中的數據類型的對應關系
https://blog.csdn.net/lilong329329/article/details/78899477
ALTER TABLE和CREATE INDEX的區別
https://blog.csdn.net/qq_34578253/article/details/72236808
1. create index必須提供索引名,對於alter table,如果你不提供索引名稱,MySQL會自動創建索引名稱(默認為第一個列名)
2. create index一個語句一次只能建立一個索引,alter table可以在一個語句建立多個,如:
- `ALTER TABLE HeadOfState ADD PRIMARY KEY (ID), ADD INDEX (LastName,FirstName);`
3. 只有alter table才能創建主鍵