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
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 || '''
这是一个已知问题吗?
根据 12cR1 or 12cR2 文档,没有 NOPARTITION
选项。
该语句在 12cR1 中确实有效,但似乎被默默地忽略了,因为它似乎没有做任何事情——尽管它可能在幕后,正如@XING 的演示所暗示的那样。并且在 12cR2 和 11gR2 中预计会出现错误。
所以这个 似乎 是 12cR1 中一个未记录的(根据 MoS 搜索)错误,因为当包含无效选项时它不会导致错误。除了...在 MoS 中有一些命中间接地将其称为有效,例如错误 23210794,其中指定选项显示为解决方法;相反,文档 ID 2253744.1 提到
PARTITION
/NOPARTITION
keyword, which is not a 12.1 feature, was used during the sequence creation
有趣的是,all_sequences
视图在 12cR1, but then lost it again in 12cR2 中获得了 partition_count
列。 (纯粹是猜测,但这可能与分区表的自动增量列的内部实现有关,并且不会真正意味着暴露给其他序列。)
要了解更多信息,您需要向 Oracle 提出服务请求。
但解决问题的方法是从语句中删除 NOPARTITION
关键字。
如@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;
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 || '''
这是一个已知问题吗?
根据 12cR1 or 12cR2 文档,没有 NOPARTITION
选项。
该语句在 12cR1 中确实有效,但似乎被默默地忽略了,因为它似乎没有做任何事情——尽管它可能在幕后,正如@XING 的演示所暗示的那样。并且在 12cR2 和 11gR2 中预计会出现错误。
所以这个 似乎 是 12cR1 中一个未记录的(根据 MoS 搜索)错误,因为当包含无效选项时它不会导致错误。除了...在 MoS 中有一些命中间接地将其称为有效,例如错误 23210794,其中指定选项显示为解决方法;相反,文档 ID 2253744.1 提到
PARTITION
/NOPARTITION
keyword, which is not a 12.1 feature, was used during the sequence creation
有趣的是,all_sequences
视图在 12cR1, but then lost it again in 12cR2 中获得了 partition_count
列。 (纯粹是猜测,但这可能与分区表的自动增量列的内部实现有关,并且不会真正意味着暴露给其他序列。)
要了解更多信息,您需要向 Oracle 提出服务请求。
但解决问题的方法是从语句中删除 NOPARTITION
关键字。
如@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;