---
# System prepended metadata

title: SQL學習筆記

---

# SQL學習筆記
* [Greeksforgeeks教程](https://www.geeksforgeeks.org/30-days-of-sql-from-basic-to-advanced-level/)
* 環境:mySQL 8.0,windows
---

[Toc]

---
基礎語法就略過
## debug
### Could not acquire management access for administration
#### 假若mySQL連登入密碼都無法輸入，代表server的服務沒有啟動，需要手動執行
![](https://i.imgur.com/CrhLCQm.png)
#### 我先前架server在MAMP PRO上，他預設的伺服器架構是apache+mySQL+php，似乎是版本上沒有完全對應到，所以跳出錯誤，通常是程式重開可以解決衝突的問題，否則網路上有提到，需要進BIOS去開啟一個服務
![](https://i.imgur.com/wHXAlZ3.png)
![](https://i.imgur.com/XGW6GVT.png)
#### 這裡也可以看到兩個服務是各自獨立的，到時如果發布在MAMP上，便不會有這個問題
![](https://i.imgur.com/esQlBF1.png)


## UPDATE
#### 建database
![](https://i.imgur.com/TNRjnMC.png)
#### 這邊要做更新data
```
update s_list
set n = "JENNA" , age = 23
where id = 55;
```
![](https://i.imgur.com/bkAZ61d.png)
## FOREIGN KEY
### REFERENCES
#### 外來鍵限制表格內的某一個值指到(references)其他table的*primary key，注意一下外來鍵一定只能對應到主鍵
```
create table p_list(
p_id int(3) primary key,
n varchar(20),
s_id int(3),
price int(5),
foreign key (s_id) references s_list(id)
);
```
## 運算子
### Arithmetic Operators
#### 做簡單的運算處理
```
select id,n,age+10 as "age+10" from s_list;
```
![](https://i.imgur.com/WXojjGo.png)
#### 新增一項salary，計算薪資除以年紀
![](https://i.imgur.com/yzSQ5YJ.png)
```
update s_list
set salary = age*1000;
```
#### 這裡嘗試以運算子update資料的數值，報錯顯示我在安全模式下無法以其他data(KEY column)更新資料，如果進去preferences更動設定可以解決這個問題，但就先不做更動，手動更新資料
```
select id,n,age,salary,salary/age as "salary/age" from s_list;
```
![](https://i.imgur.com/hO3Atso.png)
### order
#### 讓他排序以薪資比來做順序排列
```
select id,n,age,salary,salary/age as "salary/age" from s_list
order by salary/age desc;
```
![](https://i.imgur.com/iiM3AJ2.png)

### Logical Operators
#### 邏輯運算，最基本的就是AND,OR,NOT
```
select * from s_list
where id>10 and age<50 or salary> 50000; 
```
![](https://i.imgur.com/VlcI7fQ.png)
#### 比較特別的用法還有BETWEEN
```
select * from s_list
where salary between 10000 and 50000; 
```
![](https://i.imgur.com/x0jDdoY.png)
#### 可以注意到他的範圍是包括極值
## 萬用字元(Wildcard operators)
#### 這是一個很酷的概念，囊括你查詢的字串可以用以代替字元的用法
```
select * from s_list
where n like "%A%"; 
```
![](https://i.imgur.com/89MGFip.png)
#### 笑死我這才發現，我取的每個名字都有A在裡頭
```
select * from s_list
where n like "%AN%"; 
```
![](https://i.imgur.com/zVd4JsJ.png)
## 函數
### count計算資料數總和，total總共五筆資料
```
select count(*) from s_list;
```
![](https://i.imgur.com/LLSZuLj.png)
### avg
```
select avg(salary) from s_list;
```
![](https://i.imgur.com/SXdJf6M.png)
### sum
```
select sum(salary) from s_list;
```
![](https://i.imgur.com/NzQfvfR.png)
### max
```
select max(salary),id,n,age from s_list;
```
![](https://i.imgur.com/p0mrdNK.png)
### TOP
#### 在mySQL當中的語法以limit來作替代，本身select top是無法使用的，但得到的結果相同，取得資料庫最上方的幾筆資料
```
select * from s_list limit 3;
```
![](https://i.imgur.com/gQJg1je.png)
## MINUS
#### 會用到兩個select，用途就是將第一個查詢結果減去第二個
#### mySQL不能用，以left join來模擬
```
create table x_list(
id int(3) primary key,
temp int(3),
stock_id char(10)
);
insert into x_list values (1,2,"AAPL"),(2,3,"NVDIA");
```
```
select id from s_list
left join x_list using (id)
where x_list.id is null;
```
![](https://i.imgur.com/DJ45qfY.png)

## UNION
#### 用法就像OR(聯集)，將兩個以上的select串聯在一起查詢
```
select n from s_list where id<20
union
select id from s_list;
```
![](https://i.imgur.com/Jk3tyLg.png)
## JOIN
#### 建立另一個表格參照第一個s_list，設定foreign key連接到id，可以當作是交易明細或是任何客戶及商品的對應database
![](https://i.imgur.com/qvNDLY9.png)
![](https://i.imgur.com/uJwf0Pz.png)
### LEFT JOIN
#### JOIN也是相當於OR的用法，與UNION的差異是，UNION是以垂直整合，JOIN則將欄位整合成一個table
```
select p_list.p_id,p_list.n as "stock",s_list.id,s_list.n,p_list.trading*p_list.price as "i_total"
from p_list
left join s_list
on p_list.s_id = s_list.id;
```
![](https://i.imgur.com/TkwMHPx.png)
#### 將兩個table整理在一起
```
select p_list.p_id,s_list.n,s_list.age,s_list.salary,p_list.n as "stock",p_list.price,p_list.trading,p_list.trading*p_list.price as "i_total"
from p_list
left join s_list
on p_list.s_id = s_list.id;
```
![](https://i.imgur.com/xJmOTWm.png)
### RIGHT JOIN
### INNER JOIN
#### 查詢的資料都要符合條件才會顯示，倘若有NULL或是其他空集合的資料，就不會顯示出來
![](https://i.imgur.com/QHOEffT.png)
![](https://i.imgur.com/BTRwp74.png)

```
select p_list.p_id,s_list.n,p_list.price
from p_list
inner join s_list
on p_list.s_id = s_list.id
order by p_list.p_id;
```
![](https://i.imgur.com/J0yLwd3.png)

#### 這裡可以看到**第八筆**因為s_id為null，在inner join的參照又是對到s_id，他就被剃除掉，但第九筆的s_id因為還留著，即使其他資料不完整但也被顯示出來

## HAVING
#### 在函數的條件設定下，不能用WHERE來做限制，此時使用HAVING代替WHERE的查詢功能
![](https://i.imgur.com/gVisEkt.png)
用前兩個表格參照查詢總投資的金額
```
select s_list.n,sum(p_list.trading*p_list.price) as "stoock"
from p_list
left join s_list
on p_list.s_id = s_list.id
group by s_list.n
having sum(p_list.trading*p_list.price)>70000;
```
![](https://i.imgur.com/37OpDbf.png)
顯示投資金額大於70000的客戶

## VIEW
#### VIEW的概念就是虛擬的database，他也是由row,column組成，但是select參照其他資料得到的
### VIEW的特性
#### 適用於安全性的考量，可以把資料的原始屬性隱藏起來，甚至操控不同權限的使用者，可以看到特定的內容，也可以直接簡化資料，只顯示有需要使用的資料
#### 由於view的資料是唯讀的，也就代表外部使用者是無法對view做更動
#### 當資料需要作暫時的更動，僅需操作view，而不需要直接動用程式去更新database
### CREATE VIEW
```
create view view_1(n,stock,trading) as
select s_list.n,p_list.trading*p_list.price,p_list.trading
from p_list
join s_list
on p_list.s_id = s_list.id;
```
![](https://i.imgur.com/ooe7zoG.png)
#### 針對這個交易報表再做分析，找到交易金額特別高的幾個客戶
```
select n,sum(stock),sum(trading)
from view_1
group by n
having sum(stock)>30000;
```
![](https://i.imgur.com/tsR97xb.png)

### DROP VIEW
#### 用法都跟一般的table相同
```
drop view view_1;
```
### CREATE OR REPLACE VIEW
#### 用以更新view，假如view已存在，則可以當作alter使用
```
create or replace view view_1(n,stock,trading,age,salary) as
select s_list.n,p_list.trading*p_list.price,p_list.trading,s_list.age,s_list.salary
from p_list
join s_list
on p_list.s_id = s_list.id;
```
![](https://i.imgur.com/G5Aoxxt.png)

## *除法(DIVISION)

## GRANT
### 授予db使用權限
#### 建立一個新帳號後，你要授與資料庫使用權限給這位使用者，這帳號才能開始連線進去資料庫操作
```
GRANT type_of_permission ON database_name.table_name TO 'username'@'hostname';
```
#### hostname 表示允許這帳號能從什麼地方連線到資料庫。localhost 表示只允許從本地端登入
```
GRANT ALL PRIVILEGES ON *.* TO 'andy'@'%';
```
#### % 是萬用字元，表示允許andy從任何address登入
#### 權限型態
* ALL PRIVILEGES
* CRETAE
* DROP
* INSERT
* DELETE
* SELECT(*)
* UPDATE(可以更動資料)
* GRANT OPTION(給予他人權限)
### FLUSH PRIVILEGES
#### 讓權限生效
```
FLUSH PRIVILEGES;
```
## CASE
#### SQL允許直接使用直覺的if,then,else，但前面要寫case做抬頭
```
select *,
case when trading > 100 then price*10
when trading > 1000 then price
else price*20
end "saved weight"
from p_list;
```
![](https://i.imgur.com/kdqFHqL.png)
#### 這裡要注意select跟case之間一定要有逗號做分隔

# mysqli database connect
![](https://i.imgur.com/ilXVhjZ.png)
![](https://i.imgur.com/jcWmu6Q.png)
## phpmyadmin create db
[link text][reference]pw:5-0*j1}[([!PI%MB
![](https://i.imgur.com/Nh8NJl4.png)
![](https://i.imgur.com/wz7SP2J.png)
![](https://i.imgur.com/Hed4XP5.png)

## create table
![](https://i.imgur.com/9q2eN1i.png)
## php連接資料庫
```
<?php
// 建立MySQL的資料庫連接 
$link = @mysqli_connect( 
            'localhost',  // MySQL主機名稱 
            'root',       // 使用者名稱 
            '1234',  // 密碼 
            'test');  // 預設使用的資料庫名稱 
if ( !$link ) {
   echo "MySQL資料庫連接錯誤!<br/>";
   exit();
}
else {
   echo "MySQL資料庫test連接成功!<br/>";
}
mysqli_close($link);  // 關閉資料庫連接
?
```
#### 基本上基本的語法就是這樣，設php變數post get進db，步驟很簡單，但第一次寫還有很多bug要找，網路上對javascript submit表單的資料不多，可能現在的資料庫都是綁定網頁架構平台，包括phpmyadmin，事實上在架設的過程都非常簡單人性化，甚至sql injection的問題也會直接做防範，以往需要對輸入的資料做一系列的篩檢，或是限制，如今一個指令就可以幫你過濾可能會有問題的輸入格式
![](https://i.imgur.com/idu2grf.png)
![](https://i.imgur.com/rwcZU6o.jpg)
## Google search console
![](https://i.imgur.com/WUekE1W.png)
![](https://i.imgur.com/dzeSRJv.png)
