从子查询中获取表名以在一行中用于 Oracle 中的删除/更新/插入子句

Posted

技术标签:

【中文标题】从子查询中获取表名以在一行中用于 Oracle 中的删除/更新/插入子句【英文标题】:Get table name from sub-query to use in delete / update / insert clauses in Oracle in one line 【发布时间】:2017-04-25 12:03:07 【问题描述】:

目标是在插入/更新/删除语句中使用从子选择返回的表名。它未能达到预期的效果。


如果我们使用 TABLE 执行(TABLE 是 reference 中描述的 oracle 语法词)

delete from TABLE
  (select DECODE(this returns table name as string) from REF_TABLE where where_clause);

然后: 22905. 00000 - “无法访问非嵌套表项中的行”


如果我们在没有 TABLE 的情况下执行:

delete from
  (select DECODE(this returns table name as string) from REF_TABLE where where_clause);

然后它实际上从 REF_TABLE 中删除满足 when 子句的记录。


将表名从子选择传递到外部查询的正确方法是什么?


Doc examples

EXECUTE IMMEDIATE 'delete from table :1' USING (select DECODE(...) from REF_TABLE WHERE where_clause);

PLS-00103:遇到符号“从表 :1 中删除”时 期待以下之一:

:= 。 (@%; 06550. 00000 - “第 %s 行,第 %s 列:\n%s” *原因:通常是 PL/SQL 编译错误。 *行动:

【问题讨论】:

提示:execute immediate。你不能用一条语句来做到这一点。您必须使用动态 SQL。 谢谢,但它不想按照错误提示进行编译。为什么? 您需要提前创建字符串。您不能将标识符作为参数传递。 有什么方法可以在一行中使用“立即执行”或其他方式实现目标吗? 为什么需要一行?您只是在寻找最简单的解决方案,还是需要解决一些奇怪的工具限制? Sandeep 在下面的回答是一个单一的陈述,可以说是“一行代码”。这有点牵强,但您可以将 PL/SQL 逻辑放在 SELECT 的 WITH 子句中,并在大多数人认为“一行”的单个 SELECT 语句中运行它。最干净的解决方案可能是创建一个过程来完成这项工作,然后在一行中调用该过程。 【参考方案1】:

在执行 DML 查询(例如插入、更新和删除)时,您永远不会提及 table 关键字

delete from table_name;
update table_name set field='value';
insert into table_name (field) values ('value');

在执行 Create、Alter、drop 和 Truncate 等 DDL 语句时会提到 Table 关键字

Create table table_name (field varchar2(100));
Alter table table_name modify field1 varchar2(1000);
Drop table table_name;
truncate  table table_name;

因此您提到的以下查询是正确的

delete from
  (select DECODE(this returns table name as string) from REF_TABLE where where_clause);

上述查询的唯一限制是您必须使用来自固定表或视图的 table_name 源,即不能从数据字典视图中选择它,否则您将收到以下错误。

SQL Error: ORA-02030: can only select from fixed tables/views
02030. 00000 -  "can only select from fixed tables/views"
*Cause:    An attempt is being made to perform an operation other than
           a retrieval from a fixed table/view.
*Action:   You may only select rows from fixed tables/views.

您可以使用类似于下面提到的 PL/SQL 块来递归删除表

DECLARE
  CURSOR c
  IS
    SELECT table_name FROM user_tables WHERE table_name LIKE '%SANDEEP26FEB16_2%';
BEGIN
  FOR c1 IN c
  LOOP
    EXECUTE IMMEDIATE 'delete from ' || c1.table_name;
    COMMIT;
  END LOOP;
END;

【讨论】:

以上是关于从子查询中获取表名以在一行中用于 Oracle 中的删除/更新/插入子句的主要内容,如果未能解决你的问题,请参考以下文章

如何从子查询中只获取一行?

在 Python Flask 中从数据库中查询数据时获取表名

如何使用 jQuery 从子元素中获取数据以在 xml api 中查找其他子元素?

从子记录(或超链接)获取数据以在 netsuite 高级 html pdf 中打印

oracle 语句之对数据库的表名就行模糊查询,对查询结果进行遍历,依次获取每个表名结果中的每个字段

从查询中删除 / 反斜杠以在 oracle 中获取有效数据