n+1查询
有时查询一条数据时会关联许多数据,会导致内部查询很多很多次,所带来的坏处可想而知,主要就是查询时间过长.解决方法就是使用includes(表名)
find vs find_by
1.find 只能查询用户id.下面可以看出两种都可以同查询出数据,但是如果要查询数据库中没有的数据时,使用find_by则会返回一个nil,而find方法则会抛出异常
2.2.3 :001 > u = User.find 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User id: 1, username: "wu", password: "123456", created_at: "2016-06-03 07:32:33", updated_at: "2016-06-03 07:32:33">
2.2.3 :005 > u = User.find_by id:1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User id: 1, username: "wu", password: "123456", created_at: "2016-06-03 07:32:33", updated_at: "2016-06-03 07:32:33">
2.find_by可以查询任何的数据通过key-value的形式
2.2.3 :007 > u = User.find_by username: "wu"
User Load (0.8ms) SELECT `users`.* FROM `users` WHERE `users`.`username` = 'wu' LIMIT 1
=> #<User id: 1, username: "wu", password: "123456", created_at: "2016-06-03 07:32:33", updated_at: "2016-06-03 07:32:33">
根据这两点酌情使用
find_by!
! 在ruby中大多是修改数据自身.而在rails不太一样.如在rails console中查询一个不存在的数据,使用find_by!时就会抛出异常,需要我们手动抓取异常
find_by_sql
这个是让我们用原生的sql语句去查询数据的如:
2.2.3 :009 > u = User.find_by_sql "select * from users"
User Load (0.6ms) select * from users
=> [#<User id: 1, username: "wu", password: "123456", created_at: "2016-06-03 07:32:33", updated_at: "2016-06-03 07:32:33">, #<User id: 2, username: "wu2", password: "123456", created_at: "2016-06-03 07:32:59", updated_at: "2016-06-03 07:32:59">]
# 可以看出其实是把数据封装成一个数组,所以也可以用下面的方式查询
2.2.3 :010 > u.first.id
=> 1
用于非常复杂的数据查询,但有可能会有sql注入的不安全隐患.另外,我们使用这种方式查询时,model和user或者其他的表没有对应关系,也就是可以查询其他随意一张表,但会把其封装成此model的对象.还有如果出现同名表的情况,那只能访问从前往后的第一个,后面访问不到(as:声明别名).
where
类似嵌入一些ruby的语法去查询,如:
# 使用数组
2.2.3 :011 > u = User.where(["id = ?",2])
User Load (1.0ms) SELECT `users`.* FROM `users` WHERE (id = 2)
=> #<ActiveRecord::Relation [#<User id: 2, username: "wu2", password: "123456", created_at: "2016-06-03 07:32:59", updated_at: "2016-06-03 07:32:59">]>
# 使用hash
2.2.3 :012 > u = User.where(id:2)
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2
=> #<ActiveRecord::Relation [#<User id: 2, username: "wu2", password: "123456", created_at: "2016-06-03 07:32:59", updated_at: "2016-06-03 07:32:59">]>
where其实是把查询的数据封装成一个对象,但是在我们没有使用each,to_a等方法之前他并没有将操作传递给数据库,所以我们可以一直利用这个对象继续查询,他会把所有查询过的数据全部封装为一个对象
2.2.3 :019 > w = User.where(id:1)
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
=> #<ActiveRecord::Relation [#<User id: 1, username: "wu", password: "123456", created_at: "2016-06-03 07:32:33", updated_at: "2016-06-03 07:32:33">]>
2.2.3 :021 > w = w.where(username: "wu")
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 AND `users`.`username` = 'wu'
=> #<ActiveRecord::Relation [#<User id: 1, username: "wu", password: "123456", created_at: "2016-06-03 07:32:33", updated_at: "2016-06-03 07:32:33">]>