# [南應大資管]網頁程式設計:資料庫互動 ###### tags: `PHP` `HTML` `台南應用科技大學資訊管理系` `MySQL` `MariaDB` ---- ## SQL 指令 - 連接資料庫:UI/CLI - 建立資料庫 - 建立使用者 - 建立資料表 ---- ### 建立資料庫 編碼/字元集 ```sql CREATE DATABASE 資料表名稱; 或 CREATE DATABASE 資料表名稱 CHARACTER SET 字元集 COLLATE 字元定序; ``` ```sql CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; ``` ```sql CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` ```sql CREATE DATABASE mydb CHARACTER SET utf8 COLLATE utf8_general_ci; ``` ---- ### 使用資料庫 ```sql USE 資料庫; ``` ```sql USE mydb; ``` ---- ### 建立使用者 ```sql CREATE USER 帳號@來源 IDENTIFIED BY '密碼'; ``` ```sql CREATE USER apple@localhost IDENTIFIED BY '1234'; ``` ```sql CREATE USER apple@'localhost' IDENTIFIED BY '1234'; ``` ```sql CREATE USER apple@'%' IDENTIFIED BY '1234'; ``` ---- ### 賦予使用者權限 ```sql GRANT 權限 ON 資料庫.資料表 TO 帳號@來源; ``` ```sql GRANT ALL PRIVILEGES ON mydb.* TO apple@localhost; ``` ```sql GRANT select,insert ON mydb.xxxx TO apple@'%'; ``` ---- ### 建立資料表 ```sql CREATE TABLE 資料表名稱 ( 欄位名稱 欄位格式, 欄位名稱 欄位格式, 欄位名稱 欄位格式 ) 其他定義; ``` ```sql CREATE TABLE 資料表名稱 ( 欄位名稱 欄位格式, 欄位名稱 欄位格式, 欄位名稱 欄位格式 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` ---- ### 資料表欄位 ```sql 欄位名稱 格式 其他定義 ``` - 常用格式 - 整數 INTEGER, INT, BIGINT - 浮點數 DECIMAL, NUMERIC, FLOAT, DOUBLE - 字串 CHAR, VARCHAR, BLOB, TEXT - 日期 DATE, DATETIME, TIMESTAMP - 常用定義 - DEFAULT 預設值 - NOT NULL, NULL 允許空值 - AUTO_INCREMENT 自動遞增 - UNIQUE [KEY] 唯一 - [PRIMARY] KEY (主)鍵 ```sql id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ``` ```sql usr VARCHAR(36) ``` ```sql msg VARCHAR(288) ``` ---- ### PUT IT ALL TOGETHER ```sql CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE mydb; CREATE USER apple@localhost IDENTIFIED BY '1234'; GRANT ALL PRIVILEGES ON mydb.* TO apple@localhost; CREATE TABLE board ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, usr VARCHAR(36), msg VARCHAR(288) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` ---- ## PHP - mysql / mysqli / PDO - 建立資料庫連線 ---- ### 建立資料庫連線 ```php new PDO('連線字串','帳號','密碼',參數) ``` - mysql 連線的資料庫系統 - host= 資料庫主機位置或領域名稱 - dbname = 資料庫名字 - charset= 字元編碼!! - 帳號, 密碼 對照 當初的SQL指令 ```CREATE USER apple@localhost IDENTIFIED BY '1234'``` ```php try { $pdo = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8mb4', 'apple','1234', [ PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ] ); } catch (Exception $e) { // echo $e->getMessage(); // 顯示錯誤訊息 exit('發生錯誤'); } ``` 參數 - PDO::ATTR_EMULATE_PREPARES 模擬prepare指令 - false 取消使用真實prepare加快速度 - PDO::ATTR_DEFAULT_FETCH_MODE 預設取得資料模式 - PDO::FETCH_ASSOC 使用關係陣列 - PDO::ATTR_ERRMODE 發生錯誤時的反應方式 - PDO::ERRMODE_EXCEPTION 例外 ---- ### 執行指令 準備 SQL 指令,然後執行 ```php $stmt = $pdo->prepare('SQL指令'); $stmt->execute(); ``` 準備帶有嵌入參數位置的 SQL 指令,然後執行時帶入參數 ```php $stmt = $pdo->prepare('帶 ? 的SQL指令'); $stmt->execute([值,值,值]); ``` 例如: ```php $stmt = $pdo->prepare('DELETE FROM board'); $stmt->execute(); ``` 例如: ```php $stmt = $pdo->prepare('INSERT INTO board (usr,msg) VALUES (?,?)'); $stmt->execute(['cat','this is a book']); // 可以執行多次 $stmt->execute(['lion','i wanna know']); $stmt->execute(['elephant','somewhere over the ranbower']); ``` ---- ### CRUD Create 新增 Read 讀取 Update 修改 Delete 刪除 ---- ### Create 顯示畫面 ```php <form method="POST" action="XXXX.php"> <input type="text" name="user"> <textarea name="message"></textarea> <button type="submit">張貼新文章</button> </form> ``` XXXX.php ```php $pdo = 略 $user = $_POST['user']; $message = $_POST['message']; $stmt = $pdo->prepare('INSERT INTO board (usr,msg) VALUES (?,?)'); $stmt->execute([$user,$message]); ``` ---- ### execute() ```php $pdo = 略 $user = $_POST['user']; $message = $_POST['message']; $stmt = $pdo->prepare('INSERT INTO board (usr,msg) VALUES (?,?)'); $stmt->execute([$user,$message]); ``` v.s. ```php $pdo = 略 $user = $_POST['user']; $message = $_POST['message']; $stmt = $pdo->prepare('INSERT INTO board (usr,msg) VALUES (?,?)'); $stmt->bindParam(1, $user, PDO::PARAM_STR, 36); $stmt->bindParam(2, $message, PDO::PARAM_STR, 288); $stmt->execute(); ``` ---- ### Read ```php $pdo = 略 $stmt = $pdo->prepare('SELECT * FROM board order by id desc'); $stmt->execute(); $data = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($data as $r) { echo( $r->id ); echo( $r->usr ); echo( $r->msg ); } ``` ---- ### Update (1/2) 先取得資料,用來顯示編輯界面 ```php $pdo = 略 $id = 略 $stmt = $pdo->prepare('SELECT usr,msg FROM board where id = ?'); $stmt->execute(); if ($r = $stmt->fetch(PDO::FETCH_OBJ) ) { echo('<form method="POST" action="XXXX.php">'); echo(' <input type="hidden" name="id" value="' . $id . '">'); echo(' <input type="text" name="user" value="' . $r->usr . '">'); echo(' <textarea name="message">' . $r->msg . '</textarea>'); echo(' <button type="submit">修改文章</button>'); echo('</form>'); } ``` 預計將長出 ```php <form method="POST" action="XXXX.php"> <input type="hidden" name="id" value="XXXXX"> <input type="text" name="user" value="XXXXX"> <textarea name="message">XXXXX</textarea> <button type="submit">修改文章</button> </form> ``` ---- ### Update (2/2) 將修改後的資料填入資料庫中 ```php $pdo = 略 $id = $_POST['id']; $user = $_POST['user']; $message = $_POST['message']; $stmt = $pdo->prepare('UPDATE board set usr=?,msg=? where id = ?'); $stmt->execute([$user,$message,$id]); ``` 或 ```php $stmt = $pdo->prepare('UPDATE board set usr=?,msg=? where id = ?'); $stmt->bindParam(1, $user, PDO::PARAM_STR, 36); $stmt->bindParam(2, $message, PDO::PARAM_STR, 288); $stmt->bindParam(3, $id, PDO::PARAM_INT); $stmt->execute(); ``` ---- ### Delete ```php $pdo = 略 $id = 略 $stmt = $pdo->prepare('DELETE FROM board where id = ?'); $stmt->bindParam(1, $id, PDO::PARAM_INT); $stmt->execute(); ``` 或 ```php $pdo = 略 $id = 略 $stmt = $pdo->prepare('DELETE FROM board where id = ?'); $stmt->execute([$id]); ``` ----- ### 換行 HTML 使用 `<br>` `<textarea>` 中使用 `\n` `\n` 轉 `<br>` ```php $s = str_replace(array("\r\n", "\n", "\r"), '<br>', $s); ``` ---- ### 補充 mysql dump 傾印匯入 #### 匯出單一資料庫 `mysqldump -u帳號 -p 資料庫名稱 > 匯出的檔名` `mysqldump -uaaaa -p sampledb > backup.sql` #### 匯入單一資料庫 進資料庫系統 `myql -uroot -p` 建資料庫 `CREATE DATABASE sampledb CHARSET SET utf8mb4 COLLATE utf8mb4_unicode_ci;` 建使用者 `CREATE USER aaaa@localhost IDENTIFIED BY 'bbbb';` 設定使用者權限 `GRANT ALL PRIVILEGES ON sampledb.* TO aaaa@localhost;` 離開資料庫系統 `exit` 匯入 `mysql -u帳號 -p 資料庫名稱 < 匯入的檔名` `mysql -uaaaa -p samepledb < backup.sql` #### 匯入單一資料庫 (其他做法) 準備文字檔 `init.sql`, 內容如: ``` CREATE DATABASE sampledb CHARSET SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER aaaa@localhost IDENTIFIED BY 'bbbb'; GRANT ALL PRIVILEGES ON sampledb.* TO aaaa@localhost; ``` 匯入 ``` mysql -uroot -p < init.sql mysql -uaaaa -p samepledb < backup.sql ``` #### 匯出全部的資料庫 (用root, 包括帳號資料表..設定資料表...) `mysqldump -uroot -p --all-databases > backup.sql` #### 匯入全部的資料庫 匯入 `mysql -uroot -p < backup.sql` 進資料庫系統 `myql -uroot -p` 補設定權限的指令 `flush privileges` ---- ## DEMO (2020/06/03) ### SQL ```sql CREATE DATABASE sampledb CHARSET SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER aaaa@localhost IDENTIFIED BY 'bbbb'; GRANT ALL PRIVILEGES ON sampledb.* TO aaaa@localhost; CREATE TABLE boards ( bid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, bname VARCHAR(200) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE posts ( bid INT NOT NULL, pid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, title VARCHAR(144), message VARCHAR(288) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE comments ( pid INT NOT NULL, cid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, message VARCHAR(288) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; insert into boards(bname) values ('測試'),('資管系'),('亂七八糟'); insert into posts(bid,title,message) values (1,'aaa','aaa123141231212'), (1,'bbb','bbbdasfsfsadfas'),(2,'ccc','cccdsfsafafdfasfda'),(3,'ddd','ddddfadfaf'); ``` ---- ### config.php ```php <?php const DB_USER = 'aaaa'; const DB_PASSWORD = 'bbbb'; ``` ---- ### db.php ```php <?php require_once('config.php'); // 建立資料庫連線 try{ $pdo = new PDO('mysql:host=localhost;dbname=sampledb;charset=utf8mb4', DB_USER, # 帳號 DB_PASSWORD, # 密碼 [ PDO::ATTR_EMULATE_PREPARES => false, # 不要模擬 prepare PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, # 錯誤時拋出例外 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ ]); } catch (Exception $e) { exit('資料庫連線有問題'); } ``` ---- ### index.php ```php <?php require('db.php'); ?> <!DOCTYPE html> <html lang="zh-Hant"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>討論區</title> </head> <body> <h1>討論區</h1> <table> <?php // 查詢所有的討論板名稱 $stmt = $pdo->prepare('select * from boards'); $stmt->execute(); $data = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($data as $r) { echo('<tr><td>'); echo("<a href=\"board.php?bid=$r->bid\">$r->bname</a>"); echo('</td></tr>'); } ?> </table> </body> </html> ``` ---- ### board.php ```php <?php $bid = $_GET['bid']; if (!$bid) { header('Location: /', true, 302); exit(); } require('db.php'); ?> <!DOCTYPE html> <html lang="zh-Hant"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>討論區</title> </head> <body> <h1>討論版</h1> <table> <?php // 查詢所有的討論板名稱 $stmt = $pdo->prepare('select pid,title from posts where bid=?'); $stmt->bindParam(1, $bid, PDO::PARAM_INT); $stmt->execute(); $data = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($data as $r) { echo('<tr><td>'); echo("<a href=\"post.php?pid=$r->pid\">$r->title</a>"); echo('</td></tr>'); } ?> </table> </body> </html> ``` ---- ### post.php ```php <?php $pid = $_GET['pid']; if (!$pid) { header('Location: /', true, 302); exit(); } require('db.php'); ?> <!DOCTYPE html> <html lang="zh-Hant"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>討論區</title> </head> <body> <h1>討論版</h1> <table> <?php // 查詢所有的討論板名稱 $stmt = $pdo->prepare('select title,message from posts where pid=?'); $stmt->bindParam(1, $pid, PDO::PARAM_INT); $stmt->execute(); // TODO: 只有一筆,不用 foreach $data = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($data as $r) { echo($r->title); echo($r->message); } ?> </table> </body> </html> ```