Oracle PL/SQL 版本 12.2.0.1.0 与 12.1.0.2.0 - 使用参数立即执行

Posted

技术标签:

【中文标题】Oracle PL/SQL 版本 12.2.0.1.0 与 12.1.0.2.0 - 使用参数立即执行【英文标题】:Oracle PL/SQL Release 12.2.0.1.0 vs 12.1.0.2.0 - execute immediate with parameters 【发布时间】:2018-05-17 06:53:44 【问题描述】:
DECLARE
  max_id INTEGER;
BEGIN
  SELECT MAX(ID) + 1 INTO max_id FROM MY_TABLE;

  EXECUTE IMMEDIATE 'CREATE SEQUENCE  MY_TABLE_ID  MINVALUE 1 MAXVALUE 99999999999999 INCREMENT BY 1 START WITH ' || max_id || ' CACHE 100 NOORDER  NOCYCLE  NOPARTITION';

END;

在上面执行时给我ORA-00933: SQL command not properly ended

Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
PL/SQL Release 12.2.0.1.0 - Production

并且在

上正常工作
   Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production

在我将执行语句更改为以下之后,它在两个版本上都可以正常工作。

 CREATE SEQUENCE  MY_TABLE_ID  MINVALUE 1 MAXVALUE 99999999999999 INCREMENT BY 1 START WITH ' || max_id || '''

这是一个已知问题吗?

【问题讨论】:

不清楚它在哪里工作,以及它在哪里没有,因为您两次发布了 12.2.0.1.0(在“不起作用”和“工作”中)。 @Littlefoot 更新了问题 您编辑了消息,但 12.2.0.1.0 仍然存在于两个语句中。仔细看看。 @Littlefoot 真的很抱歉。现已更正 【参考方案1】:

正如@Alex 所提到的,使用 Partition 子句创建序列是未记录的功能,例如 WMCONCAT。见下文解释:

sql> create sequence s1;

Sequence created.

sql> select s1.nextval from dual;

     NEXTVAL
     ---------
     1

sql> select dbms_metadata.get_ddl('SEQUENCE','S1') from dual;

DBMS_METADATA.GET_DDL('SEQUENCE','S1')
--------------------------------------------------------------------------------

 CREATE SEQUENCE  "SCOTT"."S1"  MINVALUE 1 MAXVALUE 99999999999999999999999999
99 INCREMENT BY 1 START WITH 21 CACHE 20 NOORDER  NOCYCLE  NOPARTITION

您可以在此处看到,oracle 内部将序列定义保存在一些 partition 中,因此它显示在 DDL 中。

创建另一个序列

sql> create sequence s2 partition;

  Sequence created.

sql> select s2.nextval from dual;

     NEXTVAL
---------------
      4103920000000000000000000000000001

sql> select dbms_metadata.get_ddl('SEQUENCE','S2') from dual;

DBMS_METADATA.GET_DDL('SEQUENCE','S2')
--------------------------------------------------------------------------------

 CREATE SEQUENCE  "SCOTT"."S2"  MINVALUE 1 MAXVALUE 99999999999999999999999999
99 INCREMENT BY 1 START WITH 21 CACHE 20 NOORDER  NOCYCLE  PARTITION 100000000

您现在看到,这次 Oracle 在某个分区中创建了序列,因此在 DDL 定义中显示了这一点。

oracle 保留了一些功能供其内部使用,因此未记录在案。

在您的情况下,如果您删除该部分,其他部分将正常工作。见下文:

DECLARE
  max_id INTEGER;
BEGIN
  SELECT MAX(ID) + 1 INTO max_id FROM MY_TABLE;

  EXECUTE IMMEDIATE 'CREATE SEQUENCE  MY_TABLE_ID  MINVALUE 1 MAXVALUE 99999999999999 INCREMENT BY 1 START WITH '|| max_id||'  CACHE 100 NOORDER  NOCYCLE  ' ;
END;

【讨论】:

【参考方案2】:

根据12cR1 或12cR2 文档,没有NOPARTITION 选项。

该语句在 12cR1 中确实有效,但似乎被默默地忽略了,因为它似乎没有做任何事情 - 尽管它可能在幕后,正如 @XING 的演示所暗示的那样。预计 12cR2 和 11gR2 会出现错误。

所以这个似乎是 12cR1 中未记录的(根据 MoS 搜索)错误,因为当包含无效选项时它不会导致错误。除了...... MoS 中有一些点击间接将其称为有效,例如错误 23210794,其中指定选项显示为解决方法;相反,文档 ID 2253744.1 提到

在序列创建过程中使用了PARTITION/NOPARTITION 关键字,它不是 12.1 的功能

有趣的是,all_sequences 视图在12cR1 中获得了partition_count 列,但随后在12cR2 中又丢失了它。 (纯属推测,但也许这与分区表的自增列的内部实现有关,并不真正意味着要暴露给其他序列。)

如需更多信息,您需要向 Oracle 提出服务请求。

但解决问题的方法是从语句中删除 NOPARTITION 关键字。

【讨论】:

以上是关于Oracle PL/SQL 版本 12.2.0.1.0 与 12.1.0.2.0 - 使用参数立即执行的主要内容,如果未能解决你的问题,请参考以下文章

sql developer哪个版本

Oracle PL/SQL语句基础学习笔记(上)

Oracle PL/SQL Developer集成TFS进行团队脚本文件版本管理

Oracle PL/SQL Developer集成TFS进行团队脚本文件版本管理

oracle SQL语句中怎么样调用存储过程

PL/SQL developer连接oracle11g2