根据foreign_key值更新每行中的值

时间:2011-05-14 16:08:27

标签: sql postgresql

下载表:

id (primary key)
user_id
item_id
created_at
updated_at

在这种情况下,user_id和item_id都是不正确的,但是,它们分别正确地存储在users和items表中(每个表中的import_id)。这是我正在尝试编写的内容:

downloads.each do |download|
    user = User.find_by_import_id(download.user_id)
    item = item.find_by_import_id(download.item_id)

   if user && item
    download.update_attributes(:user_id => user.id, :item.id => item.id)
   end
end

所以,

  1. 根据查找用户和项目 他们各自的“import_id”。然后
  2. 更新下载记录中的这些值
  3. 这需要大量的行。无论如何要在SQL中执行此操作?

2 个答案:

答案 0 :(得分:2)

如果我理解正确,您只需在SELECT语句中添加两个子查询来查找正确的ID。例如:

SELECT id, 
   (SELECT correct_id FROM User WHERE import_id=user_id) AS UserID,
   (SELECT correct_id FROM Item WHERE import_id=item_id) AS ItemID,
   created_at,
   updated_at
FROM Downloads

这会将您不正确的user_id转换为您希望来自User表的任何ID,它将对您的item_ids执行相同的操作。来自SQL的信息现在是正确的。

但是,如果要使用正确的信息更新表,可以这样写:

UPDATE Downloads
SET user_id = User.user_id,
    item_id = Item.item_id
FROM Downloads
INNER JOIN User ON Downloads.user_id = User.import_id
INNER JOIN Item ON Downloads.item_id = Item.import_id
WHERE ...

确保在WHERE子句中放置一些内容,这样就不会更新“下载”表中的每条记录(除非是计划)。我重写了上面的语句,因为原始版本每行有两个SELECT语句,因此有点激烈。

修改: 由于这是PostgreSQL,因此您不能在UPDATEFROM部分中拥有表名。相反,FROM部分中的表将连接到正在更新的表。以下是来自PostgreSQL网站的引用:

  

当存在FROM子句时,实质上发生的是目标表连接到fromlist中提到的表,并且连接的每个输出行表示目标表的更新操作。使用FROM时,应确保连接为每个要修改的行生成最多一个输出行。换句话说,目标行不应该连接到其他表的多个行。如果是,那么只有一个连接行将用于更新目标行,但是将使用哪一个不容易预测。

     

http://www.postgresql.org/docs/8.1/static/sql-update.html

考虑到这一点,这是一个我认为应该工作的例子(无法测试,抱歉):

UPDATE Downloads
SET user_id = User.user_id,
    item_id = Item.item_id
FROM User, Item 
WHERE Downloads.user_id = User.import_id AND
      Downloads.item_id = Item.import_id

这是基本的想法。不要忘记您仍需要在WHERE部分添加额外条件以限制更新的行。

答案 1 :(得分:1)

我完全猜测你的问题,但你有一些查找表,它会将导入的user_id与真实的 user_id相匹配,类似于项目。即假设是你的代码行:

User.find_by_import_id(download.user_id)

命中数据库进行查找。 import_users / import_items表只是我为查询表提供的名称。

UPDATE downloads
SET downloads.user_id = users.user_id
, downloads.item_id = items.items_id
FROM downloads
INNER JOIN import_users ON downloads.user_id = import_users.import_user_id
INNER JOIN import_items ON downloads.item_id = import_items.import_item_id

无论哪种方式(查找在DB中,或者它是从代码中派生出来的),首先正确插入信息会不会更容易?这意味着你不能在你的桌子上有任何FK,因为有时他们指向一个桌子,而其他人指向另一个桌子。看起来有点奇怪。