Ruby on rails Ruby-交换两个ActiveRecord实例的主键?雅致
小问题。。。这是为了解决什么是一个简单的黑客和似乎愚蠢的不修复 如果有两个从ActiveRecord派生的同一类的项,如何交换它们的主键?下面的代码可以工作,但请看Ruby on rails Ruby-交换两个ActiveRecord实例的主键?雅致,ruby-on-rails,ruby,activerecord,primary-key,swap,Ruby On Rails,Ruby,Activerecord,Primary Key,Swap,小问题。。。这是为了解决什么是一个简单的黑客和似乎愚蠢的不修复 如果有两个从ActiveRecord派生的同一类的项,如何交换它们的主键?下面的代码可以工作,但请看 class Item < ActiveRecord::Base self.primary_keys = :p_key def self.swap( a, b ) return if a.nil? or a.nil? # fix this hack! temp_1 = a.p_key
class Item < ActiveRecord::Base
self.primary_keys = :p_key
def self.swap( a, b )
return if a.nil? or a.nil?
# fix this hack!
temp_1 = a.p_key
a.p_key = "999999" #these keys cannot ever occur in our software... promise!
a.p_key.save!
a.p_key = b.p_key
b.p_key = temp_2
b.save!
a.save!
end
end
ActiveRecord(与任何其他ORM一样)不允许更改主键。如果您将以某种方式对其进行更改,那么您的模型实例将引用不同的数据库记录(如果存在)
例如,假设您有一个具有主键10的项模型实例。如果更改任何字段并保存模型,ActiveRecord将生成一条SQL语句,如UPDATE。。。设置其中id=10
。此语句将更新id为10的数据库行
如果您以某种方式将主键更改为20,那么ActiveRecord将生成一条SQL语句,如UPDATE。。。设置其中id=20
。此语句更新另一行(如果存在),保持id=10的行不变
要更改主键,必须执行如下SQL语句:updatemyu table SET id=20,其中id=10
。之后,您将需要重新加载id为10和20的模型实例
编写一个SQL语句来交换两个数据库行的主键,这将有点棘手(但是可能,这取决于您的DB服务器)。但是ActiveRecord不会帮助您
你为什么需要这个?这个问题看起来很奇怪,所以我想您实际上还需要其他东西。假设您想交换键值1和键值2。在标准SQL中:
UPDATE tbl SET keycol = CASE keycol WHEN 1 THEN 2 WHEN 2 THEN 1 END
WHERE keycol IN (1,2);
您也可以用另一种方法来解决这个问题,交换每个非键列的值——当然,这最终也会产生相同的效果。这里有一种方法,但不幸的是,它不是标准的SQL。它适用于SQL Server和其他可能的应用程序,但我还没有在其他地方测试过它。为了在标准SQL中实现同样的效果,我认为您必须创建一个视图来代替派生表子查询
UPDATE t SET x1 = x2, y1 = y2, z1 = z2
FROM
(
SELECT t1.keycol keycol1, t2.keycol keycol2,
t1.x x1, t1.y y1, t1.z z1, t2.x x2, t2.y y2, t2.z z2
FROM tbl t1, tbl t2
WHERE (t1.keycol = 1 AND t2.keycol = 2)
OR (t1.keycol = 2 AND t2.keycol = 1)
) t;
在更高的层次上,你想做什么?
UPDATE t SET x1 = x2, y1 = y2, z1 = z2
FROM
(
SELECT t1.keycol keycol1, t2.keycol keycol2,
t1.x x1, t1.y y1, t1.z z1, t2.x x2, t2.y y2, t2.z z2
FROM tbl t1, tbl t2
WHERE (t1.keycol = 1 AND t2.keycol = 2)
OR (t1.keycol = 2 AND t2.keycol = 1)
) t;