执行立即更新返回 NULL 而非字符串查询工作正常
Posted
技术标签:
【中文标题】执行立即更新返回 NULL 而非字符串查询工作正常【英文标题】:execute immediate update returns NULL whilst the non string query works fine 【发布时间】:2019-03-26 12:24:23 【问题描述】:我有一个运行良好的更新查询。一旦我把它放在我的 PLSQL 块中,它就会返回 NULL 并且没有错误。在块的这一部分之前,我将默认值插入到目标表中,因此我知道更新实际上是将字段更新为 NULL。由于此查询是按另一列计算每个列组的行数,因此它总是有一个值。我从字符串外部的查询中得到正确的计数..
当我将查询放在我的 plsql 块中时,我使用立即执行,查询将是一个字符串,其中 my_table_name 和 my_column_names 和 Table_1 是可变的。
我搜索了很多,发现了我应该提交的东西等等。但问题仍然存在。
例如: Need help in execute immediate update query
update Table_FINAL r
set column_1 =
(
select max(totalcount)
from (
select 'my_table_name' as table_name, 'my_collumn_name' as column_name, column_3, count(*) as totalcount
from my_table_name a
where exists (select 1 from Table_2 where Table_2.column_x = a.column_x)
group by column_3
) s
where r.column_3 = s.column_3
)
;
这里是字符串:
execute immediate 'update Table_FINAL r
set column_1 =
(
select max(totalcount)
from (
select ''' || my_table_name || ''' as table_name, ''' || my_collumn_name || ''' as column_name, column_3, count(*) as totalcount
from ' || my_table_name || ' a
where exists (select 1 from Table_2 where Table_2.column_x = a.column_x)
group by column_3
) s
where r.column_3 = s.column_3
)'
;
【问题讨论】:
更新不返回任何内容;你的意思是表的column_1
最终为空吗?我猜您错误地提供或使用了变量表/列名称 - 请显示更新的动态版本以及您如何在问题中执行它。
使用动态 SQL 时:将 动态创建的 UPDATE 放入变量中,并使用 DBMS_OUTPUT.PUT_LINE 将其显示在屏幕上。复制/粘贴它,单独运行(不在 PL/SQL 块中)看看会发生什么。
我添加了字符串,并在第一个查询中更正了某事。我用 my_table_name 替换了 Table_1,因为它是一个变量
Alex,很抱歉误用了返回词。是的,我的意思是它将 column_1 更新为 NULL。我如何执行它到底是什么意思?我有一个块,其中有多个执行立即数。所有的工作,都是字符串。只有这个更新实际上是在做我不想要的事情。在每个执行立即部分之后,我也有一个提交。
我的意思是您在编辑中显示的内容。什么都没有跳出来(就为什么它会表现不同而言),但是按照 Littlefoot 的建议做,并检查生成的动态字符串是否与原始状态语句完全匹配。
【参考方案1】:
它将 column_1 更新为 NULL
如果您的动态 SQL 没有返回任何行,totalcount
将为 null,因此max(totalcount)
将为 null,在这种情况下,column_1
将更新为 null。
有几个明显的解决方案:
-
只有在有值时才执行更新:
... where r.column_3 = s.column_3 and totalcount is not null
。
处理空值:select max(nvl(totalcount,0)) …
现在,您断言更新查询“工作正常”。它是否适用于您作为my_table_name
传递的所有值? Another reason why 动态 SQL 的难点在于我们无法查看源代码并确定它在运行时会做什么。所以你需要做一些调试。在没有更新的情况下运行动态 SELECT 语句,看看你实际执行的是什么:
execute immediate ' select max(totalcount) from (
select ''' || my_table_name || ''' as table_name, ''' || my_collumn_name || ''' as column_name, column_3, count(*) as totalcount
from ' || my_table_name || ' a
where exists (select 1 from Table_2 where Table_2.column_x = a.column_x)
group by column_3)' into l_total_count;
dbms_ouput.put_line(my_table_name ||'.'|| my_collumn_name ||' max(totalcount) = ' || l_total_count);
请记住在您使用的任何客户端中启用 SERVEROUTPUT。
更新字符串在一个循环中,似乎在每个循环中它确实进行了正确的更新,但随后 ir 将其余部分更新为 NULL……但我没有完全明白我应该做什么,因为我有数百个字段。 .(原文如此)
我猜你是从循环中调用这段代码的。因此,并不是您不使用 null 覆盖“正确更新”,而是您不想用任何后续值覆盖任何值。我可以提供一些建议,但实际上这是您的数据模型和业务逻辑,因此只有您可以决定正确的处理方式。
-
像这样聚合
totalcount
:set column_1 = column_1 + total_count
。为此,您需要申请 nvl(max(totalcount),0)
。
向 TABLE_FINAL 添加一列以存储 my_collumn_value
的值。在 UPDATE 语句的 WHERE 子句中引用该列。 (显然,这假设了与先前建议完全不同的结果集)。您可能还需要一列来存储 my_table_name
的值。
【讨论】:
谢谢,但问题是实际上有一个值。正如我所说,只有当我将查询放入字符串时,它才会更新为 NULL。 谢谢你..只有一点。您正在写入变量的此选择将返回多行。由于我按 Column_3 分组,因此我将获取每个 Column_3 的最大值 好吧。这行得通,我设法打印出有效值。我依赖了一些东西。更新字符串在一个循环内,似乎在每个循环中它确实进行了正确的更新,但随后 ir 将其余部分更新为 NULL。我搜索了一下,我在这里找到了一个解决方案:asktom.oracle.com/pls/asktom/… 但我做到了因为我有数百个领域,所以没有完全得到我应该做的事情.. 我再次更新了我的答案。但这是最后一次了。以上是关于执行立即更新返回 NULL 而非字符串查询工作正常的主要内容,如果未能解决你的问题,请参考以下文章
Hive 嵌套的 get_json_object 在选择查询中工作正常,但在创建表中返回 null 作为选择查询 - 奇怪的行为
特例模式(Special Case Pattern)与空对象模式(Null Pointer Pattern)—— 返回特例对象而非 null