今天小編給大家分享一下go語言中sql指的是什么的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
成都創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站制作、成都做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)與策劃設(shè)計,三明網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10余年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:三明等地區(qū)。三明做網(wǎng)站價格咨詢:028-86922220
SQL是指“結(jié)構(gòu)化查詢語言”,是一種操作數(shù)據(jù)庫的語言,包括創(chuàng)建數(shù)據(jù)庫、刪除數(shù)據(jù)庫、查詢記錄、修改記錄、添加字段等。SQL是關(guān)系型數(shù)據(jù)庫的標(biāo)準(zhǔn)語言,所有的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),比如 MySQL、Oracle、SQL Server、MS Access、Sybase、Informix、Postgres 等,都將 SQL 作為其標(biāo)準(zhǔn)處理語言。
SQL是什么
SQL 是一種操作數(shù)據(jù)庫的語言,包括創(chuàng)建數(shù)據(jù)庫、刪除數(shù)據(jù)庫、查詢記錄、修改記錄、添加字段等。SQL 雖然是一種被 ANSI 標(biāo)準(zhǔn)化的語言,但是它有很多不同的實(shí)現(xiàn)版本。
SQL 是 Structured Query Language 的縮寫,中文譯為“結(jié)構(gòu)化查詢語言”。SQL 是一種計算機(jī)語言,用來存儲、檢索和修改關(guān)系型數(shù)據(jù)庫中存儲的數(shù)據(jù)。
SQL 是關(guān)系型數(shù)據(jù)庫的標(biāo)準(zhǔn)語言,所有的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),比如 MySQL、Oracle、SQL Server、MS Access、Sybase、Informix、Postgres 等,都將 SQL 作為其標(biāo)準(zhǔn)處理語言。
SQL 的用途
SQL 之所以廣受歡迎,是因?yàn)樗哂幸韵掠猛荆?/p>
允許用戶訪問關(guān)系型數(shù)據(jù)庫系統(tǒng)中的數(shù)據(jù);
允許用戶描述數(shù)據(jù);
允許用戶定義數(shù)據(jù)庫中的數(shù)據(jù),并處理該數(shù)據(jù);
允許將 SQL 模塊、庫或者預(yù)處理器嵌入到其它編程語言中;
允許用戶創(chuàng)建和刪除數(shù)據(jù)庫、表、數(shù)據(jù)項(xiàng)(記錄);
允許用戶在數(shù)據(jù)庫中創(chuàng)建視圖、存儲過程、函數(shù);
允許用戶設(shè)置對表、存儲過程和視圖的權(quán)限。
Go語言操作數(shù)據(jù)庫(MySQL)
在Go語言標(biāo)準(zhǔn)庫提供了進(jìn)行數(shù)據(jù)庫操作的sql 庫,可以利用SQL語言來操作數(shù)據(jù)庫。
go get -u github.com/go-sql-driver/mysql
func Open(driverName, dataSourceName string) (*DB, error)
Open打開一個dirverName指定的數(shù)據(jù)庫,dataSourceName指定數(shù)據(jù)源,一般至少包括數(shù)據(jù)庫文件名和其它連接必要的信息。
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判斷的下面
}
Open函數(shù)可能只是驗(yàn)證其參數(shù)格式是否正確,實(shí)際上并不創(chuàng)建與數(shù)據(jù)庫的連接。如果要檢查數(shù)據(jù)源的名稱是否真實(shí)有效,應(yīng)該調(diào)用Ping方法
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
//需要注意 這里需要引用自己的mysql文件
var db *sql.DB
func initDB()(err error) {
//賬號 密碼 端口號(tcp)127.0.0.1:3306 表名 字符集 校驗(yàn)時間
dsn := "root:123456@tcp(127.0.0.1:3306)/gomysql?charset=utf8mb4&parseTime=true"
//加載驅(qū)動
//這里需要是=而不是:=因?yàn)槲覀兪墙o全局變量(db)賦值
db,err = sql.Open("mysql",dsn)
if err!=nil {
return err
}
//嘗試和數(shù)據(jù)庫建立連接(校驗(yàn)dsn正確)
//然后用了ping命令
err=db.Ping()
if err!=nil {
return err
}
return nil
}
func main() {
err := initDB()
if err!=nil {
fmt.Printf("connect failed,err:%v\n",err)
return
}
}
SetMaxOpenConns
設(shè)置與數(shù)據(jù)庫建立連接的最大數(shù)目。 如果n大于0且小于最大閑置連接數(shù),會將最大閑置連接數(shù)減小到匹配最大開啟連接數(shù)的限制。 如果n<=0,不會限制最大開啟連接數(shù),默認(rèn)為0(無限制)
func (db *DB) SetMaxIdleConns(n int)
連接池中的最大閑置連接數(shù)
如果n大于最大開啟連接數(shù),則新的最大閑置連接數(shù)會減小到匹配最大開啟連接數(shù)的限制。 如果n<=0,不會保留閑置連接。
我們先在MySQL中創(chuàng)建一個名為sql_test
的數(shù)據(jù)庫
CREATE DATABASE sql_test;
進(jìn)入該數(shù)據(jù)庫:
use sql_test;
執(zhí)行以下命令創(chuàng)建一張用于測試的數(shù)據(jù)表:
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()
執(zhí)行一次查詢,并期望返回最多一行結(jié)果(即Row)。QueryRow總是返回非nil的值,直到返回值的Scan方法被調(diào)用時,才會返回被延遲的錯誤。(如:未找到結(jié)果)
func (db *DB) QueryRow(query string, args ...interface{}) *Row
func queryRowDemo() {
sqlStr := "select id, name, age from user where id=?"
var u user
// 非常重要:確保QueryRow之后調(diào)用Scan方法,否則持有的數(shù)據(jù)庫鏈接不會被釋放
err := db.QueryRow(sqlStr, 1).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)
}
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
// 查詢多條數(shù)據(jù)示例
func queryMultiRowDemo() {
sqlStr := "select id, name, age from user where id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
// 非常重要:關(guān)閉rows釋放持有的數(shù)據(jù)庫鏈接
defer rows.Close()
// 循環(huán)讀取結(jié)果集中的數(shù)據(jù)
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)
}
}
插入、更新和刪除操作都使用Exec
方法。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
Exec執(zhí)行一次命令(包括查詢、刪除、更新、插入等),返回的Result是對已執(zhí)行的SQL命令的總結(jié)。參數(shù)args表示query中的占位參數(shù)。
具體插入數(shù)據(jù)示例代碼如下:
// 插入數(shù)據(jù)
func insertRowDemo() {
sqlStr := "insert into user(name, age) values (?,?)"
ret, err := db.Exec(sqlStr, "王五", 38)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
theID, err := ret.LastInsertId() // 新插入數(shù)據(jù)的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)
}
具體更新數(shù)據(jù)示例代碼如下:
// 更新數(shù)據(jù)
func updateRowDemo() {
sqlStr := "update user set age=? where id = ?"
ret, err := db.Exec(sqlStr, 39, 3)
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影響的行數(shù)
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("update success, affected rows:%d\n", n)
}
具體刪除數(shù)據(jù)的示例代碼如下:
// 刪除數(shù)據(jù)
func deleteRowDemo() {
sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, 3)
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影響的行數(shù)
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("delete success, affected rows:%d\n", n)
}
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
// 定義一個全局對象db
var db *sql.DB
// 定義一個初始化數(shù)據(jù)庫的函數(shù)
func initDB() (err error) {
// DSN:Data Source Name
dsn := "root:123456@tcp(127.0.0.1:3306)/sql_test?charset=utf8&parseTime=True"
// 不會校驗(yàn)賬號密碼是否正確
// 注意!?。∵@里不要使用:=,我們是給全局變量賦值,然后在main函數(shù)中使用全局變量db
db, err = sql.Open("mysql", dsn)
if err != nil {
return err
}
// 嘗試與數(shù)據(jù)庫建立連接(校驗(yàn)dsn是否正確)
err = db.Ping()
if err != nil {
return err
}
return nil
}
type user struct {
id int
age int
name string
}
func queryRowDemo() {
sqlStr := "select id, name, age from user where id=?"
var u user
// 非常重要:確保QueryRow之后調(diào)用Scan方法,否則持有的數(shù)據(jù)庫鏈接不會被釋放
err := db.QueryRow(sqlStr, 1).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)
}
// 查詢多條數(shù)據(jù)示例
func queryMultiRowDemo() {
sqlStr := "select id, name, age from user where id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
// 非常重要:關(guān)閉rows釋放持有的數(shù)據(jù)庫鏈接
defer rows.Close()
// 循環(huán)讀取結(jié)果集中的數(shù)據(jù)
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)
}
}
func insertRowDemo() {
sqlStr := "insert into user(name,age) value (?,?)"
//
ret,err := db.Exec(sqlStr,"王五",40)
if err!=nil {
fmt.Printf("inserf failed,err:%v\n",err)
return
}
//插入成功之后需要返回這個id
theID,err:=ret.LastInsertId()
if err != nil{
fmt.Printf("get the last insertid failed,err:%v\n",theID)
return
}
fmt.Printf("insert success,theID is:%v\n",theID)
}
func updateRowDemo() {
sqlStr := "update user set name =? where id = ?"
//執(zhí)行含有sqlStr參數(shù)的語句
ret,err:=db.Exec(sqlStr,"趙四",4)
if err!=nil {
fmt.Printf("update failed,err:%v\n",err)
return
}
AnoID,err:=ret.RowsAffected()
if err!=nil {
fmt.Printf("updateRowAffected failed,err:%v\n",err)
return
}
fmt.Printf("update success AnoID:%v\n",AnoID)
}
// 刪除數(shù)據(jù)
func deleteRowDemo() {
sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, 5)
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影響的行數(shù)
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("delete success, affected rows:%d\n", n)
}
func main() {
err := initDB() // 調(diào)用輸出化數(shù)據(jù)庫的函數(shù)
if err != nil {
fmt.Printf("init db failed,err:%v\n", err)
return
}
//queryRowDemo()
//insertRowDemo()
//updateRowDemo()
deleteRowDemo()
queryMultiRowDemo()
}
普通SQL語句執(zhí)行過程:
客戶端對SQL語句進(jìn)行占位符替換得到完整的SQL語句。
客戶端發(fā)送完整SQL語句到MySQL服務(wù)端
MySQL服務(wù)端執(zhí)行完整的SQL語句并將結(jié)果返回給客戶端。
預(yù)處理執(zhí)行過程:
把SQL語句分成兩部分,命令部分與數(shù)據(jù)部分。
先把命令部分發(fā)送給MySQL服務(wù)端,MySQL服務(wù)端進(jìn)行SQL預(yù)處理。
然后把數(shù)據(jù)部分發(fā)送給MySQL服務(wù)端,MySQL服務(wù)端對SQL語句進(jìn)行占位符替換。
MySQL服務(wù)端執(zhí)行完整的SQL語句并將結(jié)果返回給客戶端
優(yōu)化MySQL服務(wù)器重復(fù)執(zhí)行SQL的方法,可以提升服務(wù)器性能,提前讓服務(wù)器編譯,一次編譯多次執(zhí)行,節(jié)省后續(xù)編譯的成本。
避免SQL注入問題。
func (db *DB) Prepare(query string) (*Stmt, error)
查詢操作的預(yù)處理示例代碼如下:
// 預(yù)處理查詢示例
func prepareQueryDemo() {
sqlStr := "select id, name, age from user where id > ?"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare failed, err:%v\n", err)
return
}
defer stmt.Close()
rows, err := stmt.Query(0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
defer rows.Close()
// 循環(huán)讀取結(jié)果集中的數(shù)據(jù)
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)
}
}
插入、更新和刪除操作的預(yù)處理十分類似,這里以插入操作的預(yù)處理為例:
// 預(yù)處理插入示例
func prepareInsertDemo() {
sqlStr := "insert into user(name, age) values (?,?)"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare failed, err:%v\n", err)
return
}
defer stmt.Close()
_, err = stmt.Exec("小王子", 18)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
_, err = stmt.Exec("沙河娜扎", 18)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
fmt.Println("insert success.")
}
我們?nèi)魏螘r候都不應(yīng)該自己拼接SQL語句!
// sql注入示例
func sqlInjectDemo(name string) {
sqlStr := fmt.Sprintf("select id, name, age from user where name='%s'", name)
fmt.Printf("SQL:%s\n", sqlStr)
var u user
err := db.QueryRow(sqlStr).Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("exec failed, err:%v\n", err)
return
}
fmt.Printf("user:%#v\n", u)
}
此時以下輸入字符串都可以引發(fā)SQL注入問題:
sqlInjectDemo("xxx' or 1=1#")
sqlInjectDemo("xxx' union select * from user #")
sqlInjectDemo("xxx' and (select count(*) from user) <10 #")
數(shù)據(jù)庫 | 占位符語法 |
---|---|
MySQL | ? |
PostgreSQL | $1 , $2 等 |
SQLite | ? 和$1 |
Oracle | :name |
以上就是“go語言中sql指的是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享題目:go語言中sql指的是什么
當(dāng)前鏈接:http://chinadenli.net/article0/gpcdoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、搜索引擎優(yōu)化、網(wǎng)站制作、網(wǎng)站排名、營銷型網(wǎng)站建設(shè)、用戶體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)