我的 Oracle 联接更新语句有什么问题?
我正在使用 Oracle 10g 数据库。
我有以下两个表:
T_DEBTOR :
- ID_DEBTOR
- HEADER
T_ELEMENT :
- ID_ELEMENT
- ID_DEBTOR
- INSURER
这两个表使用 ID_DEBTOR 字段连接。
仅当 HEADER 不为空时,我才想用关联的 T_DEBTOR.HEADER 更新 T_ELEMENT.INSURER 值。 换句话说:
If T_DEBTOR.HEADER != null
Then T_ELEMENT.INSURER = T_DEBTOR.HEADER
Else T_ELEMENT.INSURER is not modified!
我尝试使用以下 SQL 查询:
update
T_ELEMENT elt
set elt.INSURER = (
select HEADER
from T_DEBTOR debtor
where
debtor.HEADER is not null
and debtor.ID_DEBTOR = elt.ID_DEBTOR);
此查询适用于链接到 HEADER 不为空的债务人的所有元素。 但是,当 T_DEBTOR.HEADER 为 null 时,此查询将 T_ELEMENT.INSURER 设置为 null,这是不正确的。
即:
If T_DEBTOR.HEADER != null
Then T_ELEMENT.INSURER = T_DEBTOR.HEADER --> This part is OK
Else T_ELEMENT.INSURER is set to null --> This part is NOT OK
我的查询有什么问题?
编辑,关于 Brian Storrar 的回答:
我想做的是这样的:
update
T_ELEMENT elt
set elt.INSURER = (
select HEADER
from T_DEBTOR debtor
where
debtor.HEADER is not null
and debtor.ID_DEBTOR = elt.ID_DEBTOR)
where debtor.HEADER is not null;
I am working with an Oracle 10g Database.
I have the following two tables:
T_DEBTOR :
- ID_DEBTOR
- HEADER
T_ELEMENT :
- ID_ELEMENT
- ID_DEBTOR
- INSURER
These two tables are joined using the ID_DEBTOR field.
I want to update the T_ELEMENT.INSURER value with the associated T_DEBTOR.HEADER only if HEADER is not null.
In others words:
If T_DEBTOR.HEADER != null
Then T_ELEMENT.INSURER = T_DEBTOR.HEADER
Else T_ELEMENT.INSURER is not modified!
I tried to use the following SQL query:
update
T_ELEMENT elt
set elt.INSURER = (
select HEADER
from T_DEBTOR debtor
where
debtor.HEADER is not null
and debtor.ID_DEBTOR = elt.ID_DEBTOR);
This query is working for all elements linked to debtors that has a HEADER not null.
However, when the T_DEBTOR.HEADER is null, then this query set the T_ELEMENT.INSURER to null, which is not correct.
ie:
If T_DEBTOR.HEADER != null
Then T_ELEMENT.INSURER = T_DEBTOR.HEADER --> This part is OK
Else T_ELEMENT.INSURER is set to null --> This part is NOT OK
What is wrong with my query?
Edit, regarding the Brian Storrar answer:
What I want to do is something like that:
update
T_ELEMENT elt
set elt.INSURER = (
select HEADER
from T_DEBTOR debtor
where
debtor.HEADER is not null
and debtor.ID_DEBTOR = elt.ID_DEBTOR)
where debtor.HEADER is not null;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
好问题。
为了模拟您的情况,我创建了示例表:
通过您当前的更新语句,问题变得清晰:“不更新”值设置为 NULL:
执行此更新的最佳方法是更新联接两个表的。 但是有一些限制:
通过绕过 ujvc 提示,我们可以绕过此限制。
但不建议这样做,除非您确实确定 t_debtor.id_debtor 是唯一的。
最好只添加一个主键。 您可能已经准备好了这个:
问候,
抢。
Good question.
To simulate your situation, I've created sample tables:
And with your current update statement, the problem becomes clear: the "not to be updated" values are set to NULL:
The best way to do this update, is to update a join of both tables. There are some restrictions however:
With the bypass ujvc hint, we can circumvent this restriction.
But it is not advisable to do so unless you know really really sure that t_debtor.id_debtor is unique.
It's better to just add a primary key. You'll probably have this one already in place:
Regards,
Rob.
我找到了解决我的问题的解决方案(添加了where子句):
如果您有更好的解决方案,请随时发布!
I've found a solution to solve my problem (the where clause is added):
If you have a better solution, do not hesitate to post it!
从 Oracle 8i 开始(我没有尝试过使用之前的版本),如果表是“键保留的”(即:如果您要从父子关系中更新子项),则可以更新联接。 在这里,如果 id_debtor 是 T_DEBTOR 的主键,您可以:
干杯,
--
文森特
since Oracle 8i (I haven't tried with the preceeding versions), you can update a join if the tables are "key-preserved" (i-e: if you're updating the child from in a parent-child relationship). Here, if id_debtor is the primary key of T_DEBTOR, you can :
Cheers,
--
Vincent
你尝试过
或者类似的东西 吗
承认这有点没有选择性,但我认为它会达到你的目的。
Have you tried
or something similar
admittedy this is a bit unselective but I think it will do what you intend.
您可以通过更新选择的结果来做到这一点,但表必须“保留键”:
这会创建您的表(提示 - 如果您可以为示例发布 SQL,这将非常有用!)。
现在您可以更新选择的结果以提供您想要的结果...
这会失败,因为表未保留键,但一些约束将解决此问题:
现在更新将起作用,因为表已保留键:
You can do this by updating the results of a select, but the tables have to be 'key preserved':
That creates your tables (hint - it's very useful if you can post SQL for your example!).
Now you can update the results of a select to give what you want ...
This fails because the table is not key preserved, but a few constraints will solve this:
Now the update will work, because the tables are key preserved:
你有没有尝试过
Have you tried
您可以使用 SQL Case 语句来区分 HEADER 何时为空以及何时有值:
http://www.tizag.com/sqlTutorial/sqlcase.php
You could use the SQL Case statement, to distinguish when HEADER is null and when it has a value:
http://www.tizag.com/sqlTutorial/sqlcase.php
@Rob 感谢您的 /*+bypass_ujvc*/ 提示。 我有几个案例需要使用它。 我希望我的 DBA 能够做到这一点。 有几次我不得不创建一个光标来解决这个问题。
@Rob Thanks for the /*+ bypass_ujvc */ Tip. I have a couple cases where I need to use this. I wish my DBA told be able this. There are a couple times I had to create a cursor to get around this.