为什么在 oracle12c 中删除和创建 PK 会使 PK 从 `all_indexes` 中消失?
Why dropping and creating a PK in oracle12c makes the PK disappear from `all_indexes`?
我正在尝试重置主键“hail mary”样式 - 删除并创建。
但是,之后,它从 all_indexes
table 中消失了。
PK 似乎存在,因为行为是正确的:
- 再次尝试创建时,提示我只能创建一个主键。
- 此外,不能插入具有相同 ID 的 2 行 - 违反唯一约束。
脚本:
set echo on;
-- whenever sqlerror exit sql.sqlcode;
set timing on
SET LINESIZE 2000
create table MY_TABLE (
date_col DATE DEFAULT SYSTIMESTAMP NOT NULL,
id NUMBER(10) NOT NULL,
hash NUMBER(19) DEFAULT '0' NOT NULL,
value1 NUMBER(19) DEFAULT '0' NOT NULL,
value2 NUMBER(19) DEFAULT '0' NOT NULL,
CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash)
);
-- Res: Table created.
CREATE INDEX MY_TABLE_I ON MY_TABLE (id, hash, date_col ASC);
-- Res: Index created.
select index_name from all_indexes where table_name = 'MY_TABLE' order by index_name;
-- Res: MY_TABLE_I, MY_TABLE_PK
ALTER TABLE MY_TABLE DROP primary key;
-- Res: Table altered.
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash);
-- Res: Table altered.
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash);
-- Res: ORA-02260: table can have only one primary key
insert into MY_TABLE values (SYSDATE, 1, 123456, 10, 20);
-- Res: 1 row created.
insert into MY_TABLE values (SYSDATE, 1, 123456, 10, 20);
-- Res: ORA-00001: unique constraint (ALIK.MY_TABLE_PK) violated
select index_name from all_indexes where table_name = 'MY_TABLE' order by index_name;
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-- Res: !!!!! Just MY_TABLE_I !!!!!
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
知道为什么 PK 游戏后 all_indexes
消失了吗?
数据库版本:12.1.0.2.0
干杯。
当您添加主键或唯一约束时,数据库会检查是否存在具有相同前导列的现有索引。如果有,数据库可以使用它。
即使索引列与约束的顺序不同,数据库也会这样做。因此,由于 MY_TABLE_I
具有与 PK 相同的列,因此数据库使用它。
如果你查看 *_constraints
,你应该会发现 PK 使用索引 MY_TABLE_I
:
select constraint_name, index_name
from user_constraints
where table_name = 'MY_TABLE'
and constraint_type = 'P';
CONSTRAINT_NAME INDEX_NAME
MY_TABLE_PK MY_TABLE_I
为避免这种情况,请使用 using index
子句来 define/specify 您希望 PK 使用的索引:
ALTER TABLE MY_TABLE
ADD CONSTRAINT MY_TABLE_PK
PRIMARY KEY (date_col, id, hash)
USING INDEX (
CREATE INDEX MY_TABLE_PK ON MY_TABLE (date_col, id, hash)
);
基本上,据我了解 Chris 所写的内容,另一个索引接管了 PKs 索引 - 尽管它的顺序不正确。
这意味着如果我查询,例如,仅通过 date_col
,查询会很慢,因为它是接管的索引的最后一个参数。
另一个解决方案是在删除 PK 之前先删除具有一组类似于 PK 的值的任何索引。
所以,为了达到相同的状态,我需要删除索引,这样它就不会接管。示例:
DROP INDEX MY_TABLE_I;
-- Res: Index dropped.
ALTER TABLE MY_TABLE DROP primary key;
-- Res: Table altered.
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash);
-- Res: Table altered.
CREATE INDEX MY_TABLE_I ON MY_TABLE (id, hash, date_col ASC);
-- Res: Index created.
select index_name from all_indexes where table_name = 'MY_TABLE' order by index_name;
-- Res: MY_TABLE_PK and MY_TABLE_I
我正在尝试重置主键“hail mary”样式 - 删除并创建。
但是,之后,它从 all_indexes
table 中消失了。
PK 似乎存在,因为行为是正确的:
- 再次尝试创建时,提示我只能创建一个主键。
- 此外,不能插入具有相同 ID 的 2 行 - 违反唯一约束。
脚本:
set echo on;
-- whenever sqlerror exit sql.sqlcode;
set timing on
SET LINESIZE 2000
create table MY_TABLE (
date_col DATE DEFAULT SYSTIMESTAMP NOT NULL,
id NUMBER(10) NOT NULL,
hash NUMBER(19) DEFAULT '0' NOT NULL,
value1 NUMBER(19) DEFAULT '0' NOT NULL,
value2 NUMBER(19) DEFAULT '0' NOT NULL,
CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash)
);
-- Res: Table created.
CREATE INDEX MY_TABLE_I ON MY_TABLE (id, hash, date_col ASC);
-- Res: Index created.
select index_name from all_indexes where table_name = 'MY_TABLE' order by index_name;
-- Res: MY_TABLE_I, MY_TABLE_PK
ALTER TABLE MY_TABLE DROP primary key;
-- Res: Table altered.
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash);
-- Res: Table altered.
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash);
-- Res: ORA-02260: table can have only one primary key
insert into MY_TABLE values (SYSDATE, 1, 123456, 10, 20);
-- Res: 1 row created.
insert into MY_TABLE values (SYSDATE, 1, 123456, 10, 20);
-- Res: ORA-00001: unique constraint (ALIK.MY_TABLE_PK) violated
select index_name from all_indexes where table_name = 'MY_TABLE' order by index_name;
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-- Res: !!!!! Just MY_TABLE_I !!!!!
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
知道为什么 PK 游戏后 all_indexes
消失了吗?
数据库版本:12.1.0.2.0
干杯。
当您添加主键或唯一约束时,数据库会检查是否存在具有相同前导列的现有索引。如果有,数据库可以使用它。
即使索引列与约束的顺序不同,数据库也会这样做。因此,由于 MY_TABLE_I
具有与 PK 相同的列,因此数据库使用它。
如果你查看 *_constraints
,你应该会发现 PK 使用索引 MY_TABLE_I
:
select constraint_name, index_name
from user_constraints
where table_name = 'MY_TABLE'
and constraint_type = 'P';
CONSTRAINT_NAME INDEX_NAME
MY_TABLE_PK MY_TABLE_I
为避免这种情况,请使用 using index
子句来 define/specify 您希望 PK 使用的索引:
ALTER TABLE MY_TABLE
ADD CONSTRAINT MY_TABLE_PK
PRIMARY KEY (date_col, id, hash)
USING INDEX (
CREATE INDEX MY_TABLE_PK ON MY_TABLE (date_col, id, hash)
);
基本上,据我了解 Chris 所写的内容,另一个索引接管了 PKs 索引 - 尽管它的顺序不正确。
这意味着如果我查询,例如,仅通过 date_col
,查询会很慢,因为它是接管的索引的最后一个参数。
另一个解决方案是在删除 PK 之前先删除具有一组类似于 PK 的值的任何索引。
所以,为了达到相同的状态,我需要删除索引,这样它就不会接管。示例:
DROP INDEX MY_TABLE_I;
-- Res: Index dropped.
ALTER TABLE MY_TABLE DROP primary key;
-- Res: Table altered.
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_PK PRIMARY KEY (date_col, id, hash);
-- Res: Table altered.
CREATE INDEX MY_TABLE_I ON MY_TABLE (id, hash, date_col ASC);
-- Res: Index created.
select index_name from all_indexes where table_name = 'MY_TABLE' order by index_name;
-- Res: MY_TABLE_PK and MY_TABLE_I