日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Find、Take、First和Last函數的區別

來源: 責編: 時間:2023-10-19 09:28:06 265觀看
導讀大家好,我是漁夫子。在gorm中,要想從數據庫中查找數據有多種方法,可以通過Find、Take和First來查找。但它們之間又有一些不同。本文就詳細介紹下他們之間的不同。一、準備工作首先我們有一個m_tests表,其中id字段是自增的

大家好,我是漁夫子。V1828資訊網——每日最新資訊28at.com

在gorm中,要想從數據庫中查找數據有多種方法,可以通過Find、Take和First來查找。但它們之間又有一些不同。本文就詳細介紹下他們之間的不同。V1828資訊網——每日最新資訊28at.com

一、準備工作

首先我們有一個m_tests表,其中id字段是自增的主鍵,同時該表里有3條數據。如下:V1828資訊網——每日最新資訊28at.com

CREATE TABLE `m_tests` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `name` varchar(100) NOT NULL DEFAULT '' COMMENT '姓名',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;INSERT INTO test01.m_test (id,name) VALUES (1,'John'), (2,'Jack'),(3,'David');

基于這個表,我們來看看這幾個函數查詢出來的結果是什么。V1828資訊網——每日最新資訊28at.com

二、First函數

我們通過ToSql函數將First函數轉成對應的sql語句來看。如下:V1828資訊網——每日最新資訊28at.com

func main() {	dsn := "username:password@tcp(127.0.0.1:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"	config := &gorm.Config{		NamingStrategy: schema.NamingStrategy{			SingularTable: true, // 禁用表名復數		}}	db, _ := gorm.Open(mysql.Open(dsn), config)	var row MTest	sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {		return tx.First(&row)	})	fmt.Printf("接收的sql語句:%s/n", sql)}

通過該程序,可以看到最終的sql語句如下:V1828資訊網——每日最新資訊28at.com

接收的sql語句:SELECT * FROM `m_test` ORDER BY `m_test`.`id` LIMIT 1

發現First函數是通過主鍵排序后,只獲取一條數據。我們在通過explain來解釋一下該條語句:V1828資訊網——每日最新資訊28at.com

explain SELECT * FROM `m_test` ORDER BY `m_test`.`id` LIMIT 1

其輸出結果如下:V1828資訊網——每日最新資訊28at.com

也就是說在查詢的時候也只掃描一行數據。也就是說First函數只掃描一行數據。V1828資訊網——每日最新資訊28at.com

三、Last函數

同樣,我們還是通過ToSQL來講Last函數轉化的sql語句打印出來:V1828資訊網——每日最新資訊28at.com

func main() {	dsn := "username:password@tcp(127.0.0.1:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"	config := &gorm.Config{		NamingStrategy: schema.NamingStrategy{			SingularTable: true, // 禁用表名復數		}}	db, _ := gorm.Open(mysql.Open(dsn), config)	var rows []MTest	sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {		return tx.Last(&rows)	})	fmt.Printf("接收的sql語句:%s/n", sql)  db.Last(&rows)  fmt.Printf("最終接收:%+v/n", rows)}

我們看到Last轉換成的sql語句如下:V1828資訊網——每日最新資訊28at.com

接收的sql語句:SELECT * FROM `m_test` ORDER BY `m_test`.`id` DESC LIMIT 1

所以,Take實際上是按主鍵倒序排列,并且只獲取1行數據的一個sql。V1828資訊網——每日最新資訊28at.com

我們再看最終獲取的結果rows,雖然是個數組,但也只有一行數據。:V1828資訊網——每日最新資訊28at.com

最終結果數據:[{Id:6 Name:}]

所以,Last和First的相同點在于只掃描到表的一條目標數據后就截止了,并賦值給接收變量。不同點在于First是按主鍵正序排列,Last是按主鍵倒序排列。V1828資訊網——每日最新資訊28at.com

四、Take函數

再來看看Take函數的執行過程。如下:V1828資訊網——每日最新資訊28at.com

func main() {	dsn := "username:password@tcp(127.0.0.1:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"	config := &gorm.Config{		NamingStrategy: schema.NamingStrategy{			SingularTable: true, // 禁用表名復數		}}	db, _ := gorm.Open(mysql.Open(dsn), config)	var row MTest	sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {		return tx.Take(&row)	})	fmt.Printf("接收的sql語句:%s/n", sql)}

Take函數執行時最終轉換成的sql語句如下:V1828資訊網——每日最新資訊28at.com

SELECT * FROM `m_test` LIMIT 1

也是只獲取一行數據,但和First不同的是缺少了Order BY m_test.id``。V1828資訊網——每日最新資訊28at.com

我們再通過explain來解釋下該條語句,如下, type列是ALL,rows列是3,因為我們表里只有3行數據。是全表掃描,然后再隨機獲取一行數據。如下:V1828資訊網——每日最新資訊28at.com

mysql> explain SELECT * FROM `m_test` LIMIT 1;+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+|  1 | SIMPLE      | m_test | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL  |+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+1 row in set, 1 warning (0.09 sec)

所以,Take函數是掃描全表,并隨機獲取一條數據。所以,Take函數要比First函數性能差。V1828資訊網——每日最新資訊28at.com

同時,我們注意到,因為在sql語句中可以看到都有LIMIT 1的限制,所以Take和First都只能獲取一條數據,即便是給傳遞了一個數組,也只能獲取一行數據,不能獲取多行數據。V1828資訊網——每日最新資訊28at.com

五、Find函數

再來看看Take函數的執行過程。我們首先給Find函數傳遞一個普通的非切片變量,如下:V1828資訊網——每日最新資訊28at.com

func main() {	dsn := "username:password@tcp(127.0.0.1:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"	config := &gorm.Config{		NamingStrategy: schema.NamingStrategy{			SingularTable: true, // 禁用表名復數		}}	db, _ := gorm.Open(mysql.Open(dsn), config)	var row MTest	sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {		return tx.Find(&row)	})	fmt.Printf("接收的sql語句:%s/n", sql)}

轉換成的sql語句如下:V1828資訊網——每日最新資訊28at.com

接收的sql語句:SELECT * FROM `m_test`

和First和Take相比,缺少了Order子句和Limit子句。掃描的是整個表,獲取的也是表的所有數據,但因為接收者是一個非切片變量,所以最終只接收了一行數據到row中。V1828資訊網——每日最新資訊28at.com

我們再來看看給Find傳遞一個切片變量來接收的情況:V1828資訊網——每日最新資訊28at.com

func main() {	dsn := "username:password@tcp(127.0.0.1:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"	config := &gorm.Config{		NamingStrategy: schema.NamingStrategy{			SingularTable: true, // 禁用表名復數		}}	db, _ := gorm.Open(mysql.Open(dsn), config)	var rows []MTest	tx.Find(&rows)	fmt.Printf("rows:%+v/n", rows)}

這個結果是接收所有查找到的行的數據到rows中。所以大家一定要注意,在使用Find查詢的時候一定要加Where條件和查詢的數量,以避免掃描和查詢全表的數據,尤其是在大數量的表中。V1828資訊網——每日最新資訊28at.com

六、總結

本文主要講解了First、Last、Take和Find查詢函數的不同之處。希望在使用過程中大家根據自己的應用場景選擇合適的函數。V1828資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-14122-0.htmlFind、Take、First和Last函數的區別

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 壓測工具界的 “悍馬” :wrk 使用

下一篇: Java中的代碼重構:技巧、優秀實踐與方法

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 罗定市| 兴文县| 汕尾市| 定陶县| 延津县| 屯留县| 保靖县| 全州县| 从江县| 扶绥县| 廉江市| 宣汉县| 连云港市| 木兰县| 长武县| 海晏县| 大埔区| 蓝田县| 平原县| 广河县| 休宁县| 三穗县| 晴隆县| 获嘉县| 乌苏市| 滨州市| 桑植县| 鸡泽县| 蒙阴县| 子长县| 玛多县| 霍邱县| 克东县| 视频| 建阳市| 灵璧县| 乌苏市| 许昌县| 旅游| 东至县| 阿瓦提县|