你可以解释SQLwise为什么只有SELECT语句失败才能运行这个INSERT语句? (rails first_or_create)

时间:2013-03-03 17:23:26

标签: sql ruby-on-rails ruby

我正在查看Rails指南并遇到the section on active record's first_or_create method。它说明了以下代码:

Client.where(:first_name => 'Andy').first_or_create(:locked => false)
# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">

会生成以下SQL:

SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1
BEGIN
INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 0, NULL, '2011-08-30 05:22:57')
COMMIT

我理解first_or_create在使用时的作用,我的问题。 。 。

从SQL语句的角度来看。为什么只有SELECT语句失败才会运行Insert语句?

1 个答案:

答案 0 :(得分:2)

这就是方法的重点。 first_or_create将获取第一条记录,如果没有与查询匹配的记录,则创建一条记录。您可以从源代码中看到:

# File activerecord/lib/active_record/relation.rb, line 117
def first_or_create(attributes = nil, options = {}, &block)
  first || create(attributes, options, &block)
end

SELECT语句查找所有符合WHERE子句的记录,并且仅限于1条记录,因此first

如果第一条记录不存在,则创建它,因此INSERT语句和方法名称的_or_create部分。


对于SQL语句本身,简单地调用它确实每次都会创建一条新记录。我认为文档显示了所有可以生成的SQL,并且首先要理解

SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1

查询

,如果没有回来,则插入

BEGIN
INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 0, NULL, '2011-08-30 05:22:57')
COMMIT