如何在嵌套的pl/sql块中立即创建表

如何在嵌套的pl/sql块中立即创建表,sql,oracle,nested,block,Sql,Oracle,Nested,Block,我创建表,然后计算这些表的数量并将它们存储在变量中,所有这些都在Oracle数据库的嵌套pl/sql块中。我收到错误“ORA-00942:表或视图不存在”。如果我先创建表,然后运行我的块,它就会执行,不会出错 因此,我知道没有创建表,即使我使用了executeimmediate命令。(我认为该命令将绕过一个事实,即在执行PL/SQL块之前,PL/SQL块中使用的所有对象都必须存在。) 在这一点上,在我的块之外创建表是很困难的,还有其他方法吗 示例代码如下: DECLARE g_user va

我创建表,然后计算这些表的数量并将它们存储在变量中,所有这些都在Oracle数据库的嵌套pl/sql块中。我收到错误“ORA-00942:表或视图不存在”。如果我先创建表,然后运行我的块,它就会执行,不会出错

因此,我知道没有创建表,即使我使用了
executeimmediate
命令。(我认为该命令将绕过一个事实,即在执行PL/SQL块之前,PL/SQL块中使用的所有对象都必须存在。)

在这一点上,在我的块之外创建表是很困难的,还有其他方法吗

示例代码如下:

DECLARE
  g_user varchar2(30) := 'schema';
BEGIN
  /* more code and nested blocks*/
  DECLARE
    v_Count_Task1A number(6);
  BEGIN

    EXECUTE IMMEDIATE 'CREATE TABLE ' ||g_user||'.T_Task1A_Roles_w_User_IDs  AS
    SELECT ROWNUM AS Dummy_Field, USUS_ID AS Task1A_Role, User_ID AS Task1A_User_ID
    FROM Task1A_Roles_w_User_IDs';

    SELECT count(1) INTO v_Count_Task1A
    FROM T_Task1A_Roles_w_User_IDs;
    /*more operations like this*/
  END;
  /* more code and nested blocks*/
END;

问题不在于块运行时没有创建表,问题在于编译PL/SQL时表不存在,因此无法编译,因此根本无法运行

这里的解决方案是使用更动态的SQL来执行计数,因为动态SQL在执行块之前不会被解析:

DECLARE
  g_user varchar2(30) := 'schema';
BEGIN
  /* more code and nested blocks*/
  DECLARE
    v_Count_Task1A number(6);
  BEGIN

    EXECUTE IMMEDIATE 'CREATE TABLE ' ||g_user||'.T_Task1A_Roles_w_User_IDs  AS
    SELECT ROWNUM AS Dummy_Field, USUS_ID AS Task1A_Role, User_ID AS Task1A_User_ID
    FROM Task1A_Roles_w_User_IDs';

    EXECUTE IMMEDATE 'SELECT count(1) FROM T_Task1A_Roles_w_User_IDs' 
        INTO v_Count_Task1A;
    /*more operations like this*/
  END;
  /* more code and nested blocks*/
END;

问题不在于块运行时没有创建表,问题在于编译PL/SQL时表不存在,因此无法编译,因此根本无法运行

这里的解决方案是使用更动态的SQL来执行计数,因为动态SQL在执行块之前不会被解析:

DECLARE
  g_user varchar2(30) := 'schema';
BEGIN
  /* more code and nested blocks*/
  DECLARE
    v_Count_Task1A number(6);
  BEGIN

    EXECUTE IMMEDIATE 'CREATE TABLE ' ||g_user||'.T_Task1A_Roles_w_User_IDs  AS
    SELECT ROWNUM AS Dummy_Field, USUS_ID AS Task1A_Role, User_ID AS Task1A_User_ID
    FROM Task1A_Roles_w_User_IDs';

    EXECUTE IMMEDATE 'SELECT count(1) FROM T_Task1A_Roles_w_User_IDs' 
        INTO v_Count_Task1A;
    /*more operations like this*/
  END;
  /* more code and nested blocks*/
END;

您需要在动态sql中选择进入:

DECLARE
  g_user varchar2(30) := 'schema';
BEGIN
  /* more code and nested blocks*/
  DECLARE
    v_Count_Task1A number(6);
  BEGIN

    EXECUTE IMMEDIATE 'CREATE TABLE ' ||g_user||'.T_Task1A_Roles_w_User_IDs  AS
    SELECT ROWNUM AS Dummy_Field, USUS_ID AS Task1A_Role, User_ID AS Task1A_User_ID
    FROM Task1A_Roles_w_User_IDs';

    EXECUTE IMMEDIATE '
    SELECT count(1) 
    FROM T_Task1A_Roles_w_User_IDs'
    INTO v_Count_Task1A;
    /*more operations like this*/
  END;
  /* more code and nested blocks*/
END;

您需要在动态sql中选择进入:

DECLARE
  g_user varchar2(30) := 'schema';
BEGIN
  /* more code and nested blocks*/
  DECLARE
    v_Count_Task1A number(6);
  BEGIN

    EXECUTE IMMEDIATE 'CREATE TABLE ' ||g_user||'.T_Task1A_Roles_w_User_IDs  AS
    SELECT ROWNUM AS Dummy_Field, USUS_ID AS Task1A_Role, User_ID AS Task1A_User_ID
    FROM Task1A_Roles_w_User_IDs';

    EXECUTE IMMEDIATE '
    SELECT count(1) 
    FROM T_Task1A_Roles_w_User_IDs'
    INTO v_Count_Task1A;
    /*more operations like this*/
  END;
  /* more code and nested blocks*/
END;

我喜欢这个网站,很好的解释。解决方案很有魅力,谢谢。我喜欢这个网站,很好的解释。这个解决方案很有效,谢谢。你为什么要这么做?通常,您不会在pl/sql中创建表——您应该在数据库级别创建一次表,然后在代码中使用它们。此外,如果
g_user
不是当前模式,那么您的代码就没有多大意义。其目的只是生成报告,“他们”希望只有在运行时才存在除6个表以外的所有表,这可能会在夜间运行。我把
g_user
放在那里,只是为了在dev environment.Wow中用我自己的模式进行测试。在创建表的过程中,每天晚上都会再次删除它们,这会带来很大的开销。这也使得代码更加复杂!“他们”希望表格只在生成报告期间存在的原因是什么?制作报告时是否需要这些表格?它们可以从单个sql语句生成,而不需要先将数据存储到另一个表中吗?我同意,这感觉太复杂了。这段代码基本上是响应一个需要转换为SQL的ACL脚本,因为它们是ACL中的kill和fill表,并且对它们有效,所以我想保持这种方式。我认为有些桌子可能是不必要的,但另一些桌子是不必要的,因为有50多张桌子,我决定不去尝试每一张桌子,至少现在还没有。我现在想,复制那些有效的,站起来,然后改进。你最好只创建一次表,然后——如果绝对需要的话——填充/截断。或者,全局临时表(GTT)更合适——在事务/会话*期间,数据以会话为基础存储在它们中(即会话a可以插入数据,而会话b无法看到该数据)。你最好现在就花点时间找出最好的方法来利用数据库,而不是等到以后,因为我们都知道,时间永远不会晚,因为还有其他事情要做!(*取决于它们的设置方式)您尝试这样做的原因是什么?通常,您不会在pl/sql中创建表——您应该在数据库级别创建一次表,然后在代码中使用它们。此外,如果
g_user
不是当前模式,那么您的代码就没有多大意义。其目的只是生成报告,“他们”希望只有在运行时才存在除6个表以外的所有表,这可能会在夜间运行。我把
g_user
放在那里,只是为了在dev environment.Wow中用我自己的模式进行测试。在创建表的过程中,每天晚上都会再次删除它们,这会带来很大的开销。这也使得代码更加复杂!“他们”希望表格只在生成报告期间存在的原因是什么?制作报告时是否需要这些表格?它们可以从单个sql语句生成,而不需要先将数据存储到另一个表中吗?我同意,这感觉太复杂了。这段代码基本上是响应一个需要转换为SQL的ACL脚本,因为它们是ACL中的kill和fill表,并且对它们有效,所以我想保持这种方式。我认为有些桌子可能是不必要的,但另一些桌子是不必要的,因为有50多张桌子,我决定不去尝试每一张桌子,至少现在还没有。我现在想,复制那些有效的,站起来,然后改进。你最好只创建一次表,然后——如果绝对需要的话——填充/截断。或者,全局临时表(GTT)更合适——在事务/会话*期间,数据以会话为基础存储在它们中(即会话a可以插入数据,而会话b无法看到该数据)。你最好现在就花点时间找出最好的方法来利用数据库,而不是等到以后,因为我们都知道,时间永远不会晚,因为还有其他事情要做!(*取决于它们的设置方式)