自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Find、Take、First和Last函數(shù)的區(qū)別

開(kāi)發(fā) 前端
本文主要講解了First、Last、Take和Find查詢函數(shù)的不同之處。希望在使用過(guò)程中大家根據(jù)自己的應(yīng)用場(chǎng)景選擇合適的函數(shù)。

大家好,我是漁夫子。

在gorm中,要想從數(shù)據(jù)庫(kù)中查找數(shù)據(jù)有多種方法,可以通過(guò)Find、Take和First來(lái)查找。但它們之間又有一些不同。本文就詳細(xì)介紹下他們之間的不同。

一、準(zhǔn)備工作

首先我們有一個(gè)m_tests表,其中id字段是自增的主鍵,同時(shí)該表里有3條數(shù)據(jù)。如下:

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');

基于這個(gè)表,我們來(lái)看看這幾個(gè)函數(shù)查詢出來(lái)的結(jié)果是什么。

二、First函數(shù)

我們通過(guò)ToSql函數(shù)將First函數(shù)轉(zhuǎn)成對(duì)應(yīng)的sql語(yǔ)句來(lái)看。如下:

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, // 禁用表名復(fù)數(shù)
		}}
	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語(yǔ)句:%s\n", sql)
}

通過(guò)該程序,可以看到最終的sql語(yǔ)句如下:

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

發(fā)現(xiàn)First函數(shù)是通過(guò)主鍵排序后,只獲取一條數(shù)據(jù)。我們?cè)谕ㄟ^(guò)explain來(lái)解釋一下該條語(yǔ)句:

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

其輸出結(jié)果如下:

也就是說(shuō)在查詢的時(shí)候也只掃描一行數(shù)據(jù)。也就是說(shuō)First函數(shù)只掃描一行數(shù)據(jù)。

三、Last函數(shù)

同樣,我們還是通過(guò)ToSQL來(lái)講Last函數(shù)轉(zhuǎn)化的sql語(yǔ)句打印出來(lái):

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, // 禁用表名復(fù)數(shù)
		}}
	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語(yǔ)句:%s\n", sql)

  db.Last(&rows)
  fmt.Printf("最終接收:%+v\n", rows)
}

我們看到Last轉(zhuǎn)換成的sql語(yǔ)句如下:

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

所以,Take實(shí)際上是按主鍵倒序排列,并且只獲取1行數(shù)據(jù)的一個(gè)sql。

我們?cè)倏醋罱K獲取的結(jié)果rows,雖然是個(gè)數(shù)組,但也只有一行數(shù)據(jù)。:

最終結(jié)果數(shù)據(jù):[{Id:6 Name:}]

所以,Last和First的相同點(diǎn)在于只掃描到表的一條目標(biāo)數(shù)據(jù)后就截止了,并賦值給接收變量。不同點(diǎn)在于First是按主鍵正序排列,Last是按主鍵倒序排列。

四、Take函數(shù)

再來(lái)看看Take函數(shù)的執(zhí)行過(guò)程。如下:

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, // 禁用表名復(fù)數(shù)
		}}
	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語(yǔ)句:%s\n", sql)
}

Take函數(shù)執(zhí)行時(shí)最終轉(zhuǎn)換成的sql語(yǔ)句如下:

SELECT * FROM `m_test` LIMIT 1

也是只獲取一行數(shù)據(jù),但和First不同的是缺少了Order BY m_test.id``。

我們?cè)偻ㄟ^(guò)explain來(lái)解釋下該條語(yǔ)句,如下, type列是ALL,rows列是3,因?yàn)槲覀儽砝镏挥?行數(shù)據(jù)。是全表掃描,然后再隨機(jī)獲取一行數(shù)據(jù)。如下:

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函數(shù)是掃描全表,并隨機(jī)獲取一條數(shù)據(jù)。所以,Take函數(shù)要比First函數(shù)性能差。

同時(shí),我們注意到,因?yàn)樵趕ql語(yǔ)句中可以看到都有LIMIT 1的限制,所以Take和First都只能獲取一條數(shù)據(jù),即便是給傳遞了一個(gè)數(shù)組,也只能獲取一行數(shù)據(jù),不能獲取多行數(shù)據(jù)。

五、Find函數(shù)

再來(lái)看看Take函數(shù)的執(zhí)行過(guò)程。我們首先給Find函數(shù)傳遞一個(gè)普通的非切片變量,如下:

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, // 禁用表名復(fù)數(shù)
		}}
	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語(yǔ)句:%s\n", sql)
}

轉(zhuǎn)換成的sql語(yǔ)句如下:

接收的sql語(yǔ)句:SELECT * FROM `m_test`

和First和Take相比,缺少了Order子句和Limit子句。掃描的是整個(gè)表,獲取的也是表的所有數(shù)據(jù),但因?yàn)榻邮照呤且粋€(gè)非切片變量,所以最終只接收了一行數(shù)據(jù)到row中。

我們?cè)賮?lái)看看給Find傳遞一個(gè)切片變量來(lái)接收的情況:

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, // 禁用表名復(fù)數(shù)
		}}
	db, _ := gorm.Open(mysql.Open(dsn), config)

	var rows []MTest

	tx.Find(&rows)

	fmt.Printf("rows:%+v\n", rows)
}

這個(gè)結(jié)果是接收所有查找到的行的數(shù)據(jù)到rows中。所以大家一定要注意,在使用Find查詢的時(shí)候一定要加Where條件和查詢的數(shù)量,以避免掃描和查詢?nèi)淼臄?shù)據(jù),尤其是在大數(shù)量的表中。

六、總結(jié)

本文主要講解了First、Last、Take和Find查詢函數(shù)的不同之處。希望在使用過(guò)程中大家根據(jù)自己的應(yīng)用場(chǎng)景選擇合適的函數(shù)。

責(zé)任編輯:武曉燕 來(lái)源: 漁夫子
相關(guān)推薦

2010-10-27 10:42:36

oracle FIRS

2021-12-28 20:06:43

JavaScript開(kāi)發(fā)數(shù)組

2010-10-25 13:48:26

Oracle過(guò)程

2010-07-20 09:52:27

Perl構(gòu)造函數(shù)

2010-10-25 17:33:35

Oracle數(shù)學(xué)函數(shù)

2010-10-09 16:11:21

Mysql函數(shù)

2009-06-12 15:36:24

Hibernate fcreateQuery

2025-02-06 13:23:09

C++函數(shù)參數(shù)

2017-08-01 00:19:15

Javascript函數(shù)函數(shù)聲明

2012-05-22 01:52:48

EclipseColorer TakJava

2025-05-20 08:10:00

函數(shù)函數(shù)類型函數(shù)指針類型

2011-05-30 14:30:08

函數(shù)存儲(chǔ)過(guò)程

2023-11-29 07:47:29

Golang函數(shù)

2023-08-03 07:40:17

項(xiàng)目樣式查詢

2013-07-30 13:35:12

methodfunction

2010-09-09 11:32:26

SQL函數(shù)StDev

2021-07-30 07:05:31

C語(yǔ)言Memcpy Memmove

2024-05-16 08:37:12

FLIPFirst前端動(dòng)畫思維

2009-03-25 19:28:44

虛擬化Vmware服務(wù)器

2009-12-03 10:12:24

LinuxUnix
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)