聊聊數據庫~3.SQL基礎篇

上篇回顧:聊聊數據庫~SQL環境篇php

擴展:爲用戶添加新數據庫的權限

PS:先使用root建立數據庫,而後再受權grant all privileges on 數據庫.* to 用戶名@"%" identified by "密碼";並刷新flush privileges;html

3.1.爲用戶添加新數據庫權限.png

查看權限:show grants for dnt;
3.2.查看權限.png前端

效果:
3.3.效果.pngpython

1.3.MySQL部署

以前有園友說,爲啥不順便說說UbuntuServer的部署呢?呃。。。通常來講公司服務器都是CentOS的佔大多數,而後UbuntuServer更多的是我的雲服務比較多(推薦初創公司使用),畢竟它們兩個系統追求的不太同樣,一個是追求穩(部署麻煩),一個是追求軟件儘可能新的狀況下穩定(更新太快)mysql

那麼長話短說,步入正軌:linux

1.Ubuntu最多見的包問題

Ubuntu不得不說的就是這個apt出問題的處理 :(換源就不說了/etc/apt/sources.listgit

# 通常刪除這幾個鎖文件,而後再從新配置下就能夠了
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差很少,全部命令前加個sudogithub

1.安裝比較簡單:sudo apt install mysql-server -y
2.1.Ubuntu.pngweb

2.容許遠程鏈接:註釋掉 bind-address=127.0.0.1(/etc/mysql/mysql.conf.d/mysqld.cnf)
2.2.遠程鏈接.pngsql

PS:經常使用配置(/etc/mysql/mysql.conf.d/mysqld.cnf
2.2.1.經常使用配置.png

3.關於爲何是這個路徑的說明:sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
2.3.爲何是這個路徑.png

4.全部配置修改都須要從新啓動下:sudo systemctl restart mysql
2.4.記得重啓一下

5.第一次初始化和MariaDB不太同樣:sudo mysql_secure_installation(其餘一路y便可)

須要選下你設置root密碼的複雜度:(通常1就能夠了,就算設置再複雜,入了系統也是虛的)
2.5.初始化-注意下密碼複雜程度

PS:能夠看看拓展文章:Ubuntu16安裝mysql5.7未提示輸入密碼,安裝後修改mysql默認密碼【不推薦】修改mysql密碼策略

6.而後輸入密碼你就能夠登陸了sudo mysql -uroot -p(PS:你直接sudo mysql也能夠直接登陸)

這邊我就不像上節課一步步演示了,直接受權和建立一步走了grant all privileges on 數據庫.* to "用戶名"@"%" identified by "複雜密碼";
2.6.受權建立一步走.png

7.記得flush privileges;刷新一下系統表
2.7.測試.png

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(MySQLSQLServerMSSQL)通用的SQL語句),逆天好幾年沒用SQLServer了(幾年前講過MSSQL),這邊就一帶而過(歡迎糾錯)

PS:後面MariaDB我也直接說成MySQL了(有區別的地方我會說下,畢竟也是MySQL的分支,類似度仍是很大的)

1.概念

1.1.傳統概念

來講說傳統概念:

  1. 關係型數據庫中的關係:表(行、列)
  2. 設計範式
    • 第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.常見組件

關係型數據庫常見組件:

  1. 數據庫:database
  2. :table
    • 行:row
    • 列:column
  3. 索引:index
  4. 視圖:view
    • PS:若是有數據庫遷移的需求則不建議使用
    • PS:MySQL的視圖功能不是特別完素,儘可能不使用
  5. 存儲過程:procedure
  6. 存儲函數:function
  7. 觸發器:trigger
  8. 事件調度器:event、scheduler
  9. 用戶:user
  10. 權限:privilege

PS:MySQL常見的文件類型:

  1. 數據:數據文件、索引文件
  2. 日記:錯誤日誌、查詢日誌、慢查詢日誌、二進制日誌、(重作日誌、撤銷日誌、中繼日誌)

2.MySQL標準存儲引擎

2.1.MySQL

先說說MySQL標準存儲引擎(表類型):

  1. MyISAM:只支持表級鎖,不支持事務
  2. InnoDB:支持事務間隙鎖行鎖等等

2.2.MariaDB

首先是插件式存儲引擎(表類型)的改進和擴充 PS:其實也就是支持更多的存儲引擎(包括自定義的)

MariaDB對標準存儲引擎進行了改造升級:

  1. MyISAM ==> Aria:支持崩潰後的恢復
  2. 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不同)

  1. 字符型:
    1. 定長字符型:
      • char():不區分字符大小寫類型的字符串,max:255個字符
      • binary():區分字符大小寫類型的二進制字符串
    2. 變長字符型:
      • varchar(): 不區分字符大小寫類型的字符串
        • max:65535(2^16 - 1)個字節(utf8編碼下最多支持21843個字符
        • 能夠理解爲SQLServernvarchar
      • varbinary():區分字符的大小寫類型的二進制字符串
    3. 對象存儲:
      • text:不區分字符大小寫的不限長字符串
        • 最大長度爲65,535(2^16 - 1)個字符
        • 若是值包含多字節字符,則有效最大長度減小
      • blob:區分字符大小寫的不限長二進制字符串
    4. 內建類型:(不推薦使用)
      • enum:單選字符串數據類型,適合表單中的單選值
      • set:多選字符串數據類型,適合表單的多選值
      • PS:MySQL系獨有,SQLServer沒有
  2. 數值型:
    1. 精確數值型:
      • 整型:int
        1. bool:布爾類型(MySQL沒有)
          • PS:SQLServerbit
          • 至關於MySQLtinyint(1)
        2. tinyint:微小整型(1字節,8位)
          • [-2^7, 2^7)(-128 ~ 127)
          • 無符號:[0, 2^8)(0 ~ 255)
        3. smallint(2bytes,16bit):小整型
          • 無符號:0 ~ 65535
        4. mediumint(3bytes,24位):中等整型
          • PS:SQLServer中沒這個類型
        5. int(4bytes,32bit)
          • [-2^31, 2^31)[-2147483648,2147483648)
          • 無符號:[0, 2^32)[0,4294967296)
        6. bigint(8bytes,64bit)
          • [-2^63, 2^63)
          • 無符號:[0, 2^64)
    2. 浮點類型:
      • float:單精度浮點數(4字節)
      • double:雙精度浮點數(8字節)
        • PS:SQLServerfloat類型至關於MySQLdouble
      • decimal:精確小數類型(比double更精確)
        • 錢相關用的比較多:decimal(位數,小數點位數)
        • eg:decimal(2,1) => x.x
  3. 日期和時間類型:(和MySQL同樣)
    1. date:日期(3bytes)
    2. time:時間(3bytes)
    3. year:年
      • eg:year(2)00~99(1bytes)
      • eg:year(4)0000~9999(1bytes)
      • PS:SQLServer沒有這個類型
    4. datetime:既有時間又有日期(8bytes)
    5. timestamp:時間戳(4bytes)【精度更高】
  4. 修飾符:
    • 全部類型都適用:
      • 是否爲null:null | not null
      • 默認值:default xxx_value
      • 主 鍵:primary key
      • 惟一鍵:unique key
    • 數值類型適用:
      • 無符號:unsigned(MySQL系獨有)
      • 自增加:auto_increment (通常只用於整型,MSSQL是identity
        • 獲取ID:last_insert_id()
    • PS:多列設置
      1. 主鍵:primary key(xx,...)
      2. 惟一鍵:unique key(xx,...)
      3. 索引: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

知識點歸納:

  1. 建立數據庫:
    • create database [if not exists] db_name;
  2. 刪除數據庫:
    • drop database [if exists] db_name;
  3. 建立表:
    • create table [if not exists] tb_name(列名1,數據類型 修飾符,列名2,數據類型 修飾符);
  4. 刪除表:
    • drop table [if exists] db_name.tb_name;
  5. 修改表:
    1. 字段
      • 添加字段: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 字段名
    2. 索引
      • 添加索引: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:通常在常常用作查詢條件的列設置索引
    3. 表選項
      • 能夠參考這篇文章:https://www.cnblogs.com/huangxm/p/5736807.html
  6. SQL Model:定義MySQL對約束的響應行爲:
    • 會話修改:
      • mysql> set [session] sql_model='xx_mode'
      • mysql> set @@session.sql_mode='xx_mode'
      • PS:只在當前會話生效
    • 全局修改:須要有權限,而且不會當即生效,對之後新建的會話生效(從全局繼承的)
      • mysql> set global sql_mode='xx_mode'
      • mysql> set @@global.sql_mode='xx_mode'
      • PS: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權限)
    • 經常使用mode:(阿里服務器默認是:strict_trans_tables
      • traditional:使用傳統模型,不容許對非法值作插入操做
      • strict_trans_tables:對全部支持事物類型的表作嚴格約束
      • strict_all_tables:對全部表作嚴格約束
      • 查詢當前設置:select @@sql_mode
    • 詳情能夠查看我以前寫的文章:http://www.javashuo.com/article/p-vmgtwffb-u.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;

知識回顧:

  1. 01.SQLServer性能優化之---強大的文件組(分盤存儲)
  2. 02.SQLServer性能優化之---水平分庫擴展
  3. 03.SQLServer性能優化之---存儲優化系列

課後拓展:

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.區別

簡單列舉下上面的區別(歡迎補充):

  1. MySQL自增加是auto_increment,MSSQL是identity
  2. MySQL能夠設置無符號unsigned,MSSQL不能夠直接設置無符號整型,須要經過約束之類的來限制
  3. alter table的時候,MSSQL沒有[first | after 列名],並且語法差異也挺大

4.增刪改查(CURD)

4.1.MySQL

select語句執行流程

  1. from 表
  2. [inner|left|right] join 表 on 條件
  3. where 條件
    • 對select的結果進行過濾
  4. group by 字段
    • 根據指定條件把查詢結果進行分組,以用作聚合運算
  5. having 條件
    • 對分組聚合運算(group by)後的結果進行過濾
  6. order by 字段 [asc|desc]
    • 根據指定字段對查詢結果進行排序(默認升序asc
  7. select 字段
  8. 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.sqlhttps://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語句執行流程:

  1. from 表
  2. join類型 join 表 on 條件
  3. where 條件
    • 對select的結果進行過濾
  4. group by 字段
    • 根據指定條件把查詢結果進行分組,以用作聚合運算
  5. having 條件
    • 對分組聚合運算(group by)後的結果進行過濾
  6. select distinct 字段
  7. order by 字段 [asc|desc]
    • 根據指定字段對查詢結果進行排序(默認升序asc
  8. 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命令擴展:

  1. 命令幫助MySQL> help 命令
    • PS:版本查詢:select version();
  2. 查看字符集:show character set;
    • utf8:使用1~3bytes來表示一個Unicode字符(經常使用)
    • utf8mb4:使用1~4bytes來表示一個Unicode字符(Emoji表情 or 不經常使用漢字
  3. 排序規則:show collation;
    • eg:show collation where Collation like "%utf8%";
  4. 查看引擎:show engines;
    • InnoDB是默認存儲引擎
  5. 查看全部數據庫:show databases;
  6. 切換數據庫:use db_name;
  7. 查看全部表:show tables;
  8. 顯示錶狀態:show table status;
    • eg:show table status like 'users';
  9. 顯示錶結構:desc tb_name;
  10. 查看建立表時的SQL:show create table tb_name;
  11. 顯示錶的索引:show indexes from tb_name
  12. 查看mysql數據文件目錄show variables like '%dataDir%';
  13. 查詢當前會話的鏈接號:select connection_id();

PS:\G能夠豎排顯示show table status like 'users'\G

最後YY幾句:

  1. 沒使用Linux以前,我認爲C#是最優美、性價比最高、最簡單的語言,以後發現Python纔是最簡單的語言C#只能是最優美、性價比最高的語言
    • 如今準備接觸Golang,最終評價先待定吧
  2. 剛接觸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才能建立主鍵
相關文章
相關標籤/搜索