ORACLE 始终将标识列保持为一 (1)
ORACLE keep identity columns always as one (1)
我发现了一些与我类似的问题,但找不到确切的解决方案。在我们拥有的数据仓库中,当我们解决某些问题或其他类似问题时,有时会 "Delete" 或 "Truncate" table。但是,在Oracle中,标识列总是从下一个字符串开始,如何让字符串总是从1开始呢?这会扰乱其他维度和事实。
是否可以永远或至少在插入过程中放置此配置?
我总是通过 SQL 开发人员手动重置身份列,因为我不知道如何通过 PL/SQL 进行重置,如下所示(软件是葡萄牙语,抱歉)。
创建的标识列示例:
CREATE TABLE "DW_FUNCESP"."D_DEPARTAMENTO"
(
"ID_DEPARTAMENT" NUMBER(10,0) GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1
START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE
)
谢谢!
编辑:根据我当时的了解,我是对的,但事实证明我是不正确的。在评论和相关联的 fiddle 中,@micklesh 展示了如何使用 ALTER TABLE MODIFY...
来完成此操作。我已经要求他 post 一个答案以便它可以被接受 - 同时我将这个答案留在这里以便其他人至少可以 follow the link to his dbfiddle。但实际上 - 这是不正确的。
抱歉,您不能这样做。
关于如何获取系统为 GENERATED ALWAYS AS IDENTITY
列创建的序列的名称,以及如何将 LONG 值转换为字符串,以及如何重置序列的起始值 - 所有好东西,和
it made a really nice db<>fiddle - 然后当我把它全部包起来时,我最后一次通过它 - 并得到
ORA-32793: cannot alter a system-generated sequence
因此 - Oracle 不允许您更改它为 GENERATED ALWAYS AS IDENTITY
列生成的序列。我认为这意味着你被困住了,你将不得不忍受这些数字无法重置为从 1 开始的事实。您的其他选择是
删除并重新创建 table,这还需要您重新创建任何关联的触发器,并重新编译任何使用此 table 的 procedures/functions/packages,并且可能其他我没有想到的;或
不要使用 GENERATE ALWAYS AS IDENTITY
,创建你自己的序列,使用触发器从你的序列中设置标识列,然后 然后 你应该能够使用以下过程来重置您的序列:
CREATE OR REPLACE FUNCTION RESET_SEQUENCE(pinSequence IN VARCHAR2,
pinStart_value IN NUMBER DEFAULT 1,
pinIncrement IN NUMBER DEFAULT 1)
RETURN NUMBER
AS
nVal NUMBER;
BEGIN
-- Get the next value from the sequence
EXECUTE IMMEDIATE 'SELECT ' || pinSequence || '.NEXTVAL ' ||
' FROM DUAL'
INTO nVal;
-- Change the sequence so it decrements or increments to the desired
-- start value the next time NEXTVAL is invoked.
EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || pinSequence ||
' INCREMENT BY ' || (nVal - (pinStart_value - pinIncrement)) * -1 ||
' MINVALUE 0';
-- Decrement/increment the sequence to the desired start value
EXECUTE IMMEDIATE 'SELECT ' || pinSequence || '.NEXTVAL ' ||
' FROM DUAL'
INTO nVal;
-- Reset the sequence so it uses the desired "increment-by"
EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || pinSequence ||
' INCREMENT BY ' || pinIncrement ||
' MINVALUE 0';
RETURN 1;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('RESET_SEQUENCE : ' || SQLCODE || ' ' || SQLERRM);
RETURN 0;
END RESET_SEQUENCE;
/
And here's a db<>fiddle 显示 RESET_SEQUENCE
函数的一般测试。
人
注意:
完整示例已准备就绪 ,我只是稍微调整了解决方案以使用 ALTER TABLE 子句(按照约定)
全部归功于@Bob Jarvis
正如评论中已经提到的,Oracle IDENTITY 列仅由系统创建的 SEQUENCE 提供支持。可以找到一些详细信息,例如 here(带有官方 Oracle 文档的正确链接)。
Oracle 没有重置序列值的简单方法,但是 here's 关于如何使用非常简单的步骤进行重置的广泛讨论
不幸的是(尽管可能是幸运的)不允许以这种方式更改系统创建的序列,但是可以通过 运行 ALTER TABLE 更改序列属性修改 个命令。可以在这里看到摘录
BEGIN
-- Get the next value from the sequence
EXECUTE IMMEDIATE 'SELECT ' || v_sequence || '.NEXTVAL ' ||
' FROM DUAL'
INTO v_num;
-- Change the sequence so it decrements or increments to the desired
-- start value the next time NEXTVAL is invoked.
v_sql := 'ALTER TABLE ' || p_table_name || ' MODIFY ('
|| p_column_name || ' GENERATED BY DEFAULT ON NULL AS IDENTITY (INCREMENT BY '
|| (-v_num) || ' MINVALUE 0))' ;
EXECUTE IMMEDIATE v_sql;
-- Decrement/increment the sequence to the desired start value
EXECUTE IMMEDIATE 'SELECT ' || v_sequence || '.NEXTVAL FROM DUAL'
INTO v_num;
-- Reset the sequence so it uses the desired "increment by"
v_sql := 'ALTER TABLE ' || p_table_name || ' MODIFY ('
|| p_column_name || ' GENERATED BY DEFAULT ON NULL AS IDENTITY (INCREMENT BY 1))' ;
EXECUTE IMMEDIATE v_sql;
END;
/
以及 dbfiddle
上的完整示例
我发现了一些与我类似的问题,但找不到确切的解决方案。在我们拥有的数据仓库中,当我们解决某些问题或其他类似问题时,有时会 "Delete" 或 "Truncate" table。但是,在Oracle中,标识列总是从下一个字符串开始,如何让字符串总是从1开始呢?这会扰乱其他维度和事实。
是否可以永远或至少在插入过程中放置此配置?
我总是通过 SQL 开发人员手动重置身份列,因为我不知道如何通过 PL/SQL 进行重置,如下所示(软件是葡萄牙语,抱歉)。
创建的标识列示例:
CREATE TABLE "DW_FUNCESP"."D_DEPARTAMENTO"
(
"ID_DEPARTAMENT" NUMBER(10,0) GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1
START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE
)
谢谢!
编辑:根据我当时的了解,我是对的,但事实证明我是不正确的。在评论和相关联的 fiddle 中,@micklesh 展示了如何使用 ALTER TABLE MODIFY...
来完成此操作。我已经要求他 post 一个答案以便它可以被接受 - 同时我将这个答案留在这里以便其他人至少可以 follow the link to his dbfiddle。但实际上 - 这是不正确的。
抱歉,您不能这样做。
关于如何获取系统为 GENERATED ALWAYS AS IDENTITY
列创建的序列的名称,以及如何将 LONG 值转换为字符串,以及如何重置序列的起始值 - 所有好东西,和
it made a really nice db<>fiddle - 然后当我把它全部包起来时,我最后一次通过它 - 并得到
ORA-32793: cannot alter a system-generated sequence
因此 - Oracle 不允许您更改它为 GENERATED ALWAYS AS IDENTITY
列生成的序列。我认为这意味着你被困住了,你将不得不忍受这些数字无法重置为从 1 开始的事实。您的其他选择是
删除并重新创建 table,这还需要您重新创建任何关联的触发器,并重新编译任何使用此 table 的 procedures/functions/packages,并且可能其他我没有想到的;或
不要使用
GENERATE ALWAYS AS IDENTITY
,创建你自己的序列,使用触发器从你的序列中设置标识列,然后 然后 你应该能够使用以下过程来重置您的序列:
CREATE OR REPLACE FUNCTION RESET_SEQUENCE(pinSequence IN VARCHAR2,
pinStart_value IN NUMBER DEFAULT 1,
pinIncrement IN NUMBER DEFAULT 1)
RETURN NUMBER
AS
nVal NUMBER;
BEGIN
-- Get the next value from the sequence
EXECUTE IMMEDIATE 'SELECT ' || pinSequence || '.NEXTVAL ' ||
' FROM DUAL'
INTO nVal;
-- Change the sequence so it decrements or increments to the desired
-- start value the next time NEXTVAL is invoked.
EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || pinSequence ||
' INCREMENT BY ' || (nVal - (pinStart_value - pinIncrement)) * -1 ||
' MINVALUE 0';
-- Decrement/increment the sequence to the desired start value
EXECUTE IMMEDIATE 'SELECT ' || pinSequence || '.NEXTVAL ' ||
' FROM DUAL'
INTO nVal;
-- Reset the sequence so it uses the desired "increment-by"
EXECUTE IMMEDIATE 'ALTER SEQUENCE ' || pinSequence ||
' INCREMENT BY ' || pinIncrement ||
' MINVALUE 0';
RETURN 1;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('RESET_SEQUENCE : ' || SQLCODE || ' ' || SQLERRM);
RETURN 0;
END RESET_SEQUENCE;
/
And here's a db<>fiddle 显示 RESET_SEQUENCE
函数的一般测试。
人
注意:
完整示例已准备就绪
正如评论中已经提到的,Oracle IDENTITY 列仅由系统创建的 SEQUENCE 提供支持。可以找到一些详细信息,例如 here(带有官方 Oracle 文档的正确链接)。
Oracle 没有重置序列值的简单方法,但是 here's 关于如何使用非常简单的步骤进行重置的广泛讨论
不幸的是(尽管可能是幸运的)不允许以这种方式更改系统创建的序列,但是可以通过 运行 ALTER TABLE 更改序列属性修改 个命令。可以在这里看到摘录
BEGIN
-- Get the next value from the sequence
EXECUTE IMMEDIATE 'SELECT ' || v_sequence || '.NEXTVAL ' ||
' FROM DUAL'
INTO v_num;
-- Change the sequence so it decrements or increments to the desired
-- start value the next time NEXTVAL is invoked.
v_sql := 'ALTER TABLE ' || p_table_name || ' MODIFY ('
|| p_column_name || ' GENERATED BY DEFAULT ON NULL AS IDENTITY (INCREMENT BY '
|| (-v_num) || ' MINVALUE 0))' ;
EXECUTE IMMEDIATE v_sql;
-- Decrement/increment the sequence to the desired start value
EXECUTE IMMEDIATE 'SELECT ' || v_sequence || '.NEXTVAL FROM DUAL'
INTO v_num;
-- Reset the sequence so it uses the desired "increment by"
v_sql := 'ALTER TABLE ' || p_table_name || ' MODIFY ('
|| p_column_name || ' GENERATED BY DEFAULT ON NULL AS IDENTITY (INCREMENT BY 1))' ;
EXECUTE IMMEDIATE v_sql;
END;
/
以及 dbfiddle
上的完整示例