mysql常用語句
操作 | 方法 |
---|---|
用戶登錄 | mysql -u root -p |
退出 | exit |
選中數據庫 | USE 數據庫名 ; use RUNOOB |
列出 MySQL 數據庫管理系統的數據庫列表 | SHOW DATABASES; |
顯示某個數據庫列表 | SHOW TABLES; |
顯示數據表的屬性 | SHOW COLUMNS FROM 數據表: |
顯示數據表的詳細索引信息 | SHOW INDEX FROM 數據表; |
創建數據庫 | CREATE DATABASE 數據庫名; |
刪除數據庫 | drop database 數據庫名; |
創建數據表 | CREATE TABLE table_name (column_name column_type); |
刪除數據表 | DROP TABLE table_name ; |
插入數據 | 見下面 |
查詢數據 | 見下面 |
WHERE 子句 | SELECT * from runoob_tbl WHERE runoob_author='菜鳥教程'; |
UPDATE 更新 | 見下面 |
事務 | 見下面 |
DELETE 語句 | 見下面 |
先記錄到這,以后應道再更新。。。。 |
對上面幾個重要的命令進行簡單實例:
創建數據表:
root@host# mysql -u root -p
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> CREATE TABLE runoob_tbl(
-> runoob_id INT NOT NULL AUTO_INCREMENT,
-> runoob_title VARCHAR(100) NOT NULL,
-> runoob_author VARCHAR(40) NOT NULL,
-> submission_date DATE,
-> PRIMARY KEY ( runoob_id )
-> )ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.16 sec)
mysql>
實例解析:
如果你不想字段為 NULL 可以設置字段的屬性為 NOT NULL, 在操作數據庫時如果輸入該字段的數據為NULL ,就會報錯。
AUTO_INCREMENT定義列為自增的屬性,一般用於主鍵,數值會自動加1。
PRIMARY KEY關鍵字用於定義列為主鍵。 您可以使用多列來定義主鍵,列間以逗號分隔。
ENGINE 設置存儲引擎,CHARSET 設置編碼。
插入數據:
#語法:
INSERT INTO table_name ( field1, field2,...fieldN )
VALUES
( value1, value2,...valueN );
#實例:
root@host# mysql -u root -p password;
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> INSERT INTO runoob_tbl
-> (runoob_title, runoob_author, submission_date)
-> VALUES
-> ("學習 PHP", "菜鳥教程", NOW());
Query OK, 1 rows affected, 1 warnings (0.01 sec)
查詢數據:
#語法:
SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]
1.查詢語句中你可以使用一個或者多個表,表之間使用逗號(,)分割,並使用WHERE語句來設定查詢條件。
2.SEECT 命令可以讀取一條或者多條記錄。
3.你可以使用星號(*)來代替其他字段,SELECT語句會返回表的所有字段數據
4.你可以使用 WHERE 語句來包含任何條件。
5.你可以使用 LIMIT 屬性來設定返回的記錄數。
6.你可以通過OFFSET指定SELECT語句開始查詢的數據偏移量。默認情況下偏移量為0。
#實例:
select * from runoob_tbl;
delete刪除:
語法
以下是 SQL DELETE 語句從 MySQL 數據表中刪除數據的通用語法:
DELETE FROM table_name [WHERE Clause]
- 如果沒有指定 WHERE 子句,MySQL 表中的所有記錄將被刪除。
- 你可以在 WHERE 子句中指定任何條件
- 您可以在單個表中一次性刪除記錄。
當你想刪除數據表中指定的記錄時 WHERE 子句是非常有用的。
DELETE FROM runoob_tbl WHERE runoob_id=3;
UPDATE 更新:
#語法
UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]
1.你可以同時更新一個或多個字段。
2.你可以在 WHERE 子句中指定任何條件。
3.你可以在一個單獨表中同時更新數據。
#實例
mysql> UPDATE runoob_tbl SET runoob_title='學習 C++' WHERE runoob_id=3;
Query OK, 1 rows affected (0.01 sec)
mysql> SELECT * from runoob_tbl WHERE runoob_id=3;
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
| 3 | 學習 C++ | RUNOOB.COM | 2016-05-06 |
+-----------+--------------+---------------+-----------------+
1 rows in set (0.01 sec)
事務:
MySQL 事務主要用於處理操作量大,復雜度高的數據。比如說,在人員管理系統中,你刪除一個人員,你既需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數據庫操作語句就構成一個事務!
- 在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。
- 事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要么全部執行,要么全部不執行。
- 事務用來管理 insert,update,delete 語句
MYSQL 事務處理主要有兩種方法:
1、用 BEGIN, ROLLBACK, COMMIT來實現
- BEGIN 開始一個事務
- ROLLBACK 事務回滾
- COMMIT 事務確認
2、直接用 SET 來改變 MySQL 的自動提交模式:
- SET AUTOCOMMIT=0 禁止自動提交
- SET AUTOCOMMIT=1 開啟自動提交
在 MySQL 命令行的默認設置下,事務都是自動提交的,即執行 SQL 語句后就會馬上執行 COMMIT 操作。因此要顯式地開啟一個事務務須使用命令 BEGIN 或 START TRANSACTION,或者執行命令 SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交。
mysql> use RUNOOB;
Database changed
mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb; # 創建數據表
Query OK, 0 rows affected (0.04 sec)
mysql> select * from runoob_transaction_test;
Empty set (0.01 sec)
mysql> begin; # 開始事務
Query OK, 0 rows affected (0.00 sec)
mysql> insert into runoob_transaction_test value(5);
Query OK, 1 rows affected (0.01 sec)
mysql> insert into runoob_transaction_test value(6);
Query OK, 1 rows affected (0.00 sec)
mysql> commit; # 提交事務
Query OK, 0 rows affected (0.01 sec)
mysql> select * from runoob_transaction_test;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.01 sec)
mysql> begin; # 開始事務
Query OK, 0 rows affected (0.00 sec)
mysql> insert into runoob_transaction_test values(7);
Query OK, 1 rows affected (0.00 sec)
mysql> rollback; # 回滾
Query OK, 0 rows affected (0.00 sec)
mysql> select * from runoob_transaction_test; # 因為回滾所以數據沒有插入
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.01 sec)
mysql>
下面內容轉載自Qimi老師的博客:
go操作mysql
連接
Go語言中的database/sql
包提供了保證SQL或類SQL數據庫的泛用接口,並不提供具體的數據庫驅動。使用database/sql
包時必須注入(至少)一個數據庫驅動。
我們常用的數據庫基本上都有完整的第三方實現。例如:MySQL驅動
下載依賴
go get -u github.com/go-sql-driver/mysql
使用MySQL驅動
func Open(driverName, dataSourceName string) (*DB, error)
Open打開一個dirverName指定的數據庫,dataSourceName指定數據源,一般至少包括數據庫文件名和其它連接必要的信息。
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
// DSN:Data Source Name
dsn := "user:password@tcp(127.0.0.1:3306)/dbname"
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
}
defer db.Close() // 注意這行代碼要寫在上面err判斷的下面
}
思考題: 為什么上面代碼中的defer db.Close()
語句不應該寫在if err != nil
的前面呢?
因為雖然defer語句是最后執行,但程序運行到該語句時,會先“登記”一下這個操作,放在
if err != nil
前面,當程序出現錯誤時,defer db.Close()
語句就會出現錯誤,可能會出現一些空指針的調用等問題。
初始化連接
Open函數可能只是驗證其參數格式是否正確,實際上並不創建與數據庫的連接。如果要檢查數據源的名稱是否真實有效,應該調用Ping方法。
原文解釋如下:
First, you should understand that a sql.DB is not a connection. When you use sql.Open() you get a handle for a database. The database/sql package manages a pool of connections in the background, and doesn't open any connections until you need them. Therefore sql.Open() doesn't directly open a connection. As a result, sql.Open() does not return an error, if the server isn't available or the connection data (Username, Password) isn't correct. If you want to check this before making queries (e.g at application startup) you can use db.Ping().
翻譯:
大致意思就是sql.DB怒視一個連接,他是一個管理連接池的句柄。如果不使用他,就不會建立來連接,因此即使你的dsn里的賬號密碼出錯,程序也不會提醒,所以要主動使用db.Ping()去檢測一下。
返回的DB對象可以安全地被多個goroutine並發使用,並且維護其自己的空閑連接池。因此,Open函數應該僅被調用一次,很少需要關閉這個DB對象。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"//只是用這個包力的init
)
func main() {
// DSN:Data Source Name
//數據庫信息
dsn := "root:5210@tcp(127.0.0.1:3306)/gotest"
db, err := sql.Open("mysql", dsn) //生成句柄
if err != nil {
panic(err)
}
defer db.Close() // 注意這行代碼要寫在上面err判斷的下面
err = db.Ping()//檢測是否出現錯誤
if err != nil {
fmt.Printf("open %s invaild ,err'=", err)
return
}
fmt.Println("connect database succsed")
}
其中sql.DB
是一個數據庫(操作)句柄,代表一個具有零到多個底層連接的連接池。它可以安全地被多個goroutine同時使用。database/sql
包會自動創建和釋放連接;它也會維護一個閑置連接的連接池。
SetMaxOpenConns
func (db *DB) SetMaxOpenConns(n int)
SetMaxOpenConns
設置與數據庫建立連接的最大數目。 如果n大於0且小於最大閑置連接數,會將最大閑置連接數減小到匹配最大開啟連接數的限制。 如果n<=0,不會限制最大開啟連接數,默認為0(無限制)。
SetMaxIdleConns
func (db *DB) SetMaxIdleConns(n int)
SetMaxIdleConns設置連接池中的最大閑置連接數。 如果n大於最大開啟連接數,則新的最大閑置連接數會減小到匹配最大開啟連接數的限制。 如果n<=0,不會保留閑置連接。
CRUD
下面是CURD操作常用的的函數。
建庫建表
我們先在MySQL中創建一個名為sql_test
的數據庫
CREATE DATABASE gotest;
進入該數據庫:
use gotest;
執行以下命令創建一張用於測試的數據表:
CREATE TABLE `user` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) DEFAULT '',
`age` INT(11) DEFAULT '0',
PRIMARY KEY(`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
查詢
單行查詢
- 調用
db.QueryRow()
- 調用
row.Scan()
單行查詢db.QueryRow()
執行一次查詢,並期望返回最多一行結果(即Row)。Scan將該行查詢結果各列分別保存進dest參數指定的值中。如果該查詢匹配多行,Scan會使用第一行結果並丟棄其余各行。如果沒有匹配查詢的行,Scan會返回ErrNoRows。
func (db *DB) QueryRow(query string, args ...interface{}) *Row
func (r *Row) Scan(dest ...interface{}) error
具體示例代碼:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB//初始化連接池
//實例化一個結構體,用於接受收據庫的返回值
//數據庫的每一行都對應一個結構體
type user struct {
id int
name string
age int
}
func initDB()(err error){
// DSN:Data Source Name
//數據庫信息
dsn := "root:5210@tcp(127.0.0.1:3306)/gotest"
db, err := sql.Open("mysql", dsn) //檢查格式
if err != nil {
panic(err)
}
defer db.Close() // 注意這行代碼要寫在上面err判斷的下面
err = db.Ping()
if err != nil {
fmt.Printf("open %s invaild ,err'=", err)
return
}
fmt.Println("connect database succsed")
return nil
}
func queryDemo(id int){
var u1 user
//1. 寫sql語句
sqlStr:="select id,name,age from user where id=?"//占位符
//2.調用查詢函數
rowObj:=db.QueryRow(sqlStr,id)
//3.調用scan函數拿到結果,映射到結構體中
rowObj.Scan(&u1.id,&u1.name,&u1.age)
fmt.Printf("u1:%v\n",u1)
//注:在redis中存入的都是字符串,若想取出來還原成結構體還需要進行反序列化
//這里是調用取出結果的一個方法來進行反向解析
}
func main() {
//初始化
err:=initDB()
if err != nil {
fmt.Printf("初始化連接失敗 err=%v\n",err)
return
}
//查詢
queryDemo(2)
}
多行查詢
多行查詢db.Query()
執行一次查詢,返回多行結果(即Rows),一般用於執行select命令。參數args表示query中的占位參數。
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
核心示例代碼:
//查詢多條
func queryMore(id int){
//1. 寫sql語句
sqlStr:= "select * from user where id>?"//這里會查詢多條
//2.調用查詢函數
rows,err:=db.Query(sqlStr,id)
if err != nil {
fmt.Printf("query err=", err)
return
}
defer rows.Close()//這個在多行查詢時要手動關閉連接.
//3.使用rows.Next遍歷rows
for rows.Next(){
var u2 user
//4. scan解析每一行
err=rows.Scan(&u2.id,&u2.name,&u2.age)
fmt.Printf("u2:%v\n",u2)
}
}
插入數據
插入、更新和刪除操作都使用Exec
方法。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
Exec執行一次命令(包括查詢、刪除、更新、插入等),返回的Result是對已執行的SQL命令的總結。參數args表示query中的占位參數。
具體插入數據示例代碼如下:
//插入
func insert(){
//1. 寫sql語句
sqlStr:="insert into user(name,age) value(?,?)"
//2. 執行
ret,err:=db.Exec(sqlStr,"韓非子",1200)
if err != nil {
panic(err)
}
//3. 查看插入行id
newId,err:=ret.LastInsertId()
fmt.Println(newId)
}
更新數據
具體更新數據示例代碼如下:
func upDate(newage int, id int) {
//1 寫sql語句
sqlStr := "update user set age=? where id=?;"
//2. exec
ret, err := db.Exec(sqlStr, newage, id)
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() //操作影響的行數
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("update success, affected rows:%d\n", n)
}
刪除數據
具體刪除數據的示例代碼如下:
//刪除操作
func deleteDemo(id int) {
//1 寫sql語句
sqlStr := "delete from user where id=?;"
//2. exec
ret, err := db.Exec(sqlStr, id)
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected()
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("update success, affected rows:%d\n", n)
}
MySQL預處理
什么是預處理?
普通SQL語句執行過程:
- 客戶端對SQL語句進行占位符替換得到完整的SQL語句。
- 客戶端發送完整SQL語句到MySQL服務端
- MySQL服務端執行完整的SQL語句並將結果返回給客戶端。
預處理執行過程:
- 把SQL語句分成兩部分,命令部分與數據部分。
- 先把命令部分發送給MySQL服務端,MySQL服務端進行SQL預處理。
- 然后把數據部分發送給MySQL服務端,MySQL服務端對SQL語句進行占位符替換。
- MySQL服務端執行完整的SQL語句並將結果返回給客戶端。
為什么要預處理?
- 優化MySQL服務器重復執行SQL的方法,可以提升服務器性能,提前讓服務器編譯,一次編譯多次執行,節省后續編譯的成本。
- 避免SQL注入問題。
Go實現MySQL預處理
Go中的
func (db *DB) Prepare(query string) (*Stmt, error)
Stmt的幾個方法:
Prepare
方法會先將sql語句發送給MySQL服務端,返回一個准備好的狀態用於之后的查詢和命令。返回值可以同時執行多個查詢和命令。
func prepare() {
//1 寫sql語句
sqlStr := "select id, name, age from user where id > ?"
//2.發送給mysql服務器進行准備,返回一個狀態
stem, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare failed, err:%v\n", err)
return
}
defer stem.Close()
rows, err := stem.Query(1)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
defer rows.Close()
//循環讀取得到的結果
for rows.Next() {
var u user
//逐行解析
err = rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
}
}
Go實現MySQL事務
與事務相關的幾個操作:
事務相關方法
Go語言中使用以下三個方法實現MySQL中的事務操作。 開始事務
func (db *DB) Begin() (*Tx, error)
提交事務
func (tx *Tx) Commit() error
回滾事務
func (tx *Tx) Rollback() error
代碼實例:
// 事務操作示例
// 事務操作示例
func transactionDemo() {
tx, err := db.Begin() // 開啟事務
if err != nil {
if tx != nil {
tx.Rollback() // 回滾
}
fmt.Printf("begin trans failed, err:%v\n", err)
return
}
sqlStr1 := "Update user set age=30 where id=?"
ret1, err := tx.Exec(sqlStr1, 2)
if err != nil {
tx.Rollback() // 回滾
fmt.Printf("exec sql1 failed, err:%v\n", err)
return
}
affRow1, err := ret1.RowsAffected()
if err != nil {
tx.Rollback() // 回滾
fmt.Printf("exec ret1.RowsAffected() failed, err:%v\n", err)
return
}
sqlStr2 := "Update user set age=40 where id=?"
ret2, err := tx.Exec(sqlStr2, 3)
if err != nil {
tx.Rollback() // 回滾
fmt.Printf("exec sql2 failed, err:%v\n", err)
return
}
affRow2, err := ret2.RowsAffected()
if err != nil {
tx.Rollback() // 回滾
fmt.Printf("exec ret1.RowsAffected() failed, err:%v\n", err)
return
}
fmt.Println(affRow1, affRow2)
if affRow1 == 1 && affRow2 == 1 {
fmt.Println("事務提交啦...")
tx.Commit() // 提交事務
} else {
tx.Rollback()
fmt.Println("事務回滾啦...")
}
fmt.Println("exec trans success!")
}
sqlx使用
第三方庫sqlx
能夠簡化操作,提高開發效率。
安裝
go get github.com/jmoiron/sqlx
連接數據庫
var db *sqlx.DB
func initDB() (err error) {
dsn := "user:password@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True"
// 也可以使用MustConnect連接不成功就panic
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
fmt.Printf("connect DB failed, err:%v\n", err)
return
}
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
return
}
查詢
查詢單行數據示例代碼如下:
// 查詢單條數據示例
func queryRowDemo() {
sqlStr := "select id, name, age from user where id=?"
var u user
err := db.Get(&u, sqlStr, 1)
if err != nil {
fmt.Printf("get failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.ID, u.Name, u.Age)
}
查詢多行數據示例代碼如下:
// 查詢多條數據示例
func queryMultiRowDemo() {
sqlStr := "select id, name, age from user where id > ?"
var users []user
err := db.Select(&users, sqlStr, 0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
fmt.Printf("users:%#v\n", users)
}
插入、更新和刪除
sqlx中的exec方法與原生sql中的exec使用基本一致:
// 插入數據
func insertRowDemo() {
sqlStr := "insert into user(name, age) values (?,?)"
ret, err := db.Exec(sqlStr, "沙河小王子", 19)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
theID, err := ret.LastInsertId() // 新插入數據的id
if err != nil {
fmt.Printf("get lastinsert ID failed, err:%v\n", err)
return
}
fmt.Printf("insert success, the id is %d.\n", theID)
}
// 更新數據
func updateRowDemo() {
sqlStr := "update user set age=? where id = ?"
ret, err := db.Exec(sqlStr, 39, 6)
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影響的行數
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("update success, affected rows:%d\n", n)
}
// 刪除數據
func deleteRowDemo() {
sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, 6)
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影響的行數
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("delete success, affected rows:%d\n", n)
}