【问题标题】:update query on multiple tables在多个表上更新查询
【发布时间】:2010-03-08 04:59:22
【问题描述】:

我有一个类似的架构:

  • 员工(eno、ename、zip、hdate)
  • 客户(cno、cnmae、街道、邮编、电话)
  • 邮政编码(邮编、城市)

其中 zip 在邮政编码中为 pk,在其他表格中为 fk。
我必须编写一个更新查询,将整个数据库中所有出现的 zipcode 4994 更新为 1234。

update zipcodes,customers,employees  
  set zip = 0  
where customers.zip = zipcodes.zip 
  and employees.zip = zipcodes.zip;  

但我知道我做得不对。有没有办法在单个更新查询中更新所有表 zip?

【问题讨论】:

    标签: sql oracle sql-update


    【解决方案1】:

    Oracle 不支持多表更新语句。

    1. 确认ZIPCODES 表中存在邮政编码“1234”

      INSERT INTO ZIPCODES 
        (zip, city)
      VALUES
        (1234, '?')
      
    2. 为 CUSTOMERS 和 EMPLOYEES 表编写单独的更新语句:

      UPDATE CUSTOMERS
         SET zip = 1234
       WHERE zip = 4994
      
      UPDATE EMPLOYEES
         SET zip = 1234
       WHERE zip = 4994
      
    3. 删除之前的代码:

      DELETE FROM ZIPCODES
       WHERE zip = 4994
      

    【讨论】:

    • 我在第 1 行收到此更新邮政编码 * 错误:ORA-02292:违反完整性约束 - 找到子记录
    • @jon - 错误消息表明您正在更新 ZIPCODES 表,这不是 OMG Ponies 所建议的。
    【解决方案2】:

    您不能在一个更新语句中更新多个表。您将需要编写多个更新语句。

    新想法:您可以添加触发器以进行更新,这样您的应用程序可以更新 1 个表,而触发器将传播其余的表。

    【讨论】:

    • SQL> update zipcodes set zip =1234 where zip = 67226;更新邮政编码 * 第 1 行出现错误:ORA-02292:违反完整性约束 - 找到子记录
    • 我和@OMG Ponies 说了同样的话,你也发表了同样的回复。
    【解决方案3】:

    我认为,您应该首先在 zipcode 表中为新 zip 插入一个新行,然后更新其余表中的 zip,最后删除旧的 zipcode。

    【讨论】:

    • 您可以按照您指定的方式进行操作,但可能必须在更新期间保持系统锁定。实际上,在这两种情况下,您都需要锁定表以防止插入。
    【解决方案4】:

    我没有测试它——但是:SQL 语言允许可更新的视图。如果您查看here,您会发现Oracle 确实支持固有的可更新视图。这样,您可能可以使用一条语句更新更多表。 here 对连接有一些限制,但至少应该是可能的。

    但是;这显然不适用于您的情况,多个语句会更好。您可能会考虑“更新级联”,这样您将使用新邮政编码的城市更新表格,并且客户和员工将自动更新。

    更新:更新级联在 Oracle 中不起作用 :( 所以触发器或多个语句。

    【讨论】:

      【解决方案5】:

      使用存储过程。在那里,您可以使用条件语句执行此多表操作。

      【讨论】:

      • 仍需要多个更新语句。只在一个包装器中作为存储过程。
      【解决方案6】:

      它可能会解决您的问题。您可以根据值在 for 循环中更新或删除

      Begin
      for Zip_value in 1234.. 4559 loop
      update zipcodes
        set zip = 0   
      where customers.zip = zipcodes.zip  
        and employees.zip = zipcodes.zip;
        and zipcodes.zip = Zip_value;
      update customers
        set zip = 0   
      where customers.zip = zipcodes.zip  
        and employees.zip = zipcodes.zip;
        and zipcodes.zip = Zip_value;
      update employees   
        set zip = 0   
      where customers.zip = zipcodes.zip  
        and employees.zip = zipcodes.zip;
        and zipcodes.zip = Zip_value;
        END LOOP;
      commit;
      end;
      /
      

      【讨论】:

        猜你喜欢
        • 2021-01-15
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        • 2019-08-21
        • 1970-01-01
        • 2012-03-25
        • 1970-01-01
        相关资源
        最近更新 更多