【问题标题】:UPDATE with JOIN syntax for Oracle Database使用 JOIN 语法更新 Oracle 数据库
【发布时间】:2016-08-28 07:47:06
【问题描述】:

首先,我执行以下 SQL 语句。

drop table names;
drop table ages;

create table names (id number, name varchar2(20));
insert into names values (1, 'Harry');
insert into names values (2, 'Sally');
insert into names values (3, 'Barry');

create table ages (id number, age number);
insert into ages values (1, 25);
insert into ages values (2, 30);
insert into ages values (3, 35);

select * from names;
select * from ages;

因此,创建了以下表格。

        ID NAME
---------- ----------
         1 Harry
         2 Sally
         3 Barry

        ID        AGE
---------- ----------
         1         25
         2         30
         3         35

现在,我想将 Sally 的年龄增加 1,即将其设置为 31。以下查询可以正常工作。

update ages set age = age + 1 where id = (select id from names where name = 'Sally');
select * from ages;

表格现在看起来像这样。

        ID        AGE
---------- ----------
         1         25
         2         31
         3         35

我想知道是否有一种方法可以通过连接来完成。例如,我尝试了以下查询,但都失败了。

SQL> update ages set age = age + 1 from ages, names where ages.id = names.id and names.name = 'Sally';
update ages set age = age + 1 from ages, names where ages.id = names.id and names.name = 'Sally'
                              *
ERROR at line 1:
ORA-00933: SQL command not properly ended


SQL> update ages set age = age + 1 from names join ages on ages.id = names.id where names.name = 'Sally';
update ages set age = age + 1 from names join ages on ages.id = names.id where names.name = 'Sally'
                              *
ERROR at line 1:
ORA-00933: SQL command not properly ended

【问题讨论】:

  • 您在 Oracle 手册中的什么地方找到了该语法?
  • @Ben(谁将此标记为完全重复)-您是否阅读了另一个较旧的问题?这不是重复的,更不用说精确的了。在旧问题中,连接用于查找更新语句的更新值。在这一行中,它用于标识要更新的行。这两个问题的正确解决方案之间的重叠可能接近于零。你愿意详细说明吗?
  • @Ben 为什么这被标记为重复?是否需要至少 5 票才能将其标记为重复?

标签: oracle join sql-update oracle12c


【解决方案1】:

UPDATE 语句的语法是:

http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10007.htm

dml_table_expression_clause 在哪里:

请注意上述语法的( subquery )部分。

subquery 是一项允许执行连接更新的功能。

最简单的形式可以是:

UPDATE (
   subquery-with-a-join
)
SET cola=colb

在更新联接之前,您必须了解此处列出的限制:

https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_8004.htm

视图不得包含以下任何构造:

  • 集合运算符
  • DISTINCT 运算符
  • 聚合或分析函数
  • GROUP BY、ORDER BY、MODEL、CONNECT BY 或 START WITH 子句
  • SELECT 列表中的集合表达式
  • SELECT 列表中的子查询
  • 指定为只读的子查询
  • 加入,但有一些例外,如 Oracle 数据库管理员指南中所述

还有与可更新视图相关的常见规则 - 此处(部分:Updating a Join View):
http://docs.oracle.com/cd/B19306_01/server.102/b14231/views.htm#sthref3055

连接视图的所有可更新列必须映射到 密钥保留表。有关以下内容的讨论,请参阅“密钥保留表” 保留键的表。如果视图是用 WITH CHECK 定义的 OPTION 子句,然后是所有连接列和所有重复的列 表不可更新。

我们可以先创建一个带有连接的子查询:

SELECT age 
FROM ages a
JOIN names m ON a.id = m.id
WHERE m.name = 'Sally'

此查询仅返回以下结果:

       AGE
----------
        30

现在我们可以尝试更新我们的查询:

UPDATE (
    SELECT age 
    FROM ages a
    JOIN names m ON a.id = m.id
    WHERE m.name = 'Sally'
)
SET age = age + 1;

但我们得到一个错误:

SQL 错误:ORA-01779:无法修改映射到非键保留表的列

这个错误意味着,上面的限制之一不符合(key-preserved table)。

但是,如果我们向表中添加主键:

alter table names add primary key( id );
alter table ages add primary key( id );

那么现在更新工作没有任何错误,最终结果是:

select * from ages;

        ID        AGE
---------- ----------
         1         25
         2         31
         3         35

【讨论】:

  • 感谢您的精心回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-16
  • 2011-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 2012-03-28
相关资源
最近更新 更多