缩小oracle中的列
假设我有一个具有以下定义的表,
create table dummy (col1 number(9) not null)
此 dummy.col1 中的所有值都是 7 位长。现在我想使用 alter 命令将该列的长度从 9 - 7 减少。 Oracle 给我错误,要修改的列必须为空以降低精度或比例。有道理。
我想问一下有什么办法可以减少列大小吗?
- 我无法删除该列中的值。
- 我无法将值从该列复制到另一列,因为它有数万亿数据。
Lets say i have a table with the following definition
create table dummy (col1 number(9) not null)
All the values in this dummy.col1 are 7 digit long. Now i want to reduce the length of this column from 9 - 7 using alter command. Oracle gives me error that column to be modified must be empty to decrease precision or scale. Makes sense.
I want to ask is there any work around to reduce the column size?
- I can't delete the values in the column.
- I can't copy values from this column to another since it has trillions of data.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
列大小与数据的物理存储方式无关(它们是可变长度),
例如,如果存储在数字(38)中,数字(2)中的“23”将占用完全相同的空间,
这纯粹是对列中可以存储的最大数量,因此您可以在列上添加一个约束:
如果您希望它运行得更快一点,请将
VALIDATE
更改为NOVALIDATE
显然这会不检查现有数据的有效性。The column size has no relationship to how the data is physically stored (they are variable length)
e.g. '23' in a number(2) will take exactly the same space if stored in a number(38)
It is purely a constraint on the maximum number that can be stored in the column therefore you could just add a constraint on the column:
if you want it to go a little quicker change
VALIDATE
toNOVALIDATE
obviously this will not check the validity of the existing data.凯文的回答非常好。
唯一的其他方法是
重命名现有列,
使用旧名称和新大小创建一个新列,
发出更新语句来填充新字段(您说不能这样做)
然后删除重命名的列。
您确定无法在周末找到一些休息时间来执行这项任务吗?
Kevin's answer is excellent.
The only other way to do it is to
rename the existing column,
create a new column with the old name and the new size,
issue an update statement to populate the new field (which you said you cannot do)
and then drop the renamed column.
Are you sure you cannot find some downtime one weekend to perform this task ?
解决方案 #1
我的下面的解决方案保留了原始的列顺序。
我发现这很重要,特别是如果存在预装 SQL 语句
那里(中间层,客户端层)指向您隐式的数据库
选择。
即
:
生成 DDL 为
1. 包含您要调整大小的列的表
2. 引用该表的所有关系约束、索引、检查约束、触发器。
3、引用本表主键的其他表的所有外键。
确保每个表引用对象 DDL 都是独立的,与
创建表 DDL。
您将得到类似的内容,
仅复制
CREATE TABLE
语句,更改表名称,然后减小要修改的列的大小:
将
tableName
中的数据插入tableName_YYYYMMDD
:删除引用原始表的所有对象。
另外,删除引用 tableName 主键 pkName 的所有外键。
别担心,您已经保存了 DDL,因此您可以重新创建它们。
请注意,我在将数据复制出 tableName 后删除了索引。
我这样做是因为也许其中一个索引将在
位于 SELECT 之上,以便操作更快地完成。
删除原始表。
重命名新表。
从您之前保存的 DDL 语句重新创建所有引用对象。
解决方案 #2
保持列顺序,但不重建可能包含列 2 的非唯一使用的 PK 索引。
Solution #1
My solution below keeps the original column order.
I found that to be important, especially if there are canned SQL statements out
there (middle tier, client tier) that point back to your database that do implicit
SELECTs.
i.e.
Here goes:
Generate the DDLs for
1. The table containing the column you intend to resize
2. All the relationship constraints, indexes, check constraints, triggers that reference that table.
3. All the foreign keys of other tables that reference the primary key of this table.
Make sure each table-referencing-object DDL is stand-alone, separate from the
CREATE TABLE DDL.
You'll have something like
Copy out just the
CREATE TABLE
statement, change the table name andreduce the size of the column you wish to modify:
Insert the data from
tableName
intotableName_YYYYMMDD
:Drop all objects referencing the original table.
Also, drop all foreign keys that reference the tableName primary key pkName.
Don't worry, you've saved the DDL so you'll be able to recreate them.
Notice that I drop indexes after copying the data out of tableName.
I do this because perhaps one of the indexes will be used in the
above SELECT so that operation will complete faster.
Drop the original table.
Rename the new table.
Recreate all referencing objects from the DDL statements you saved before.
Solution #2
Keep the column order but do not rebuild non-unique-used-by-PK indexes that might contain column2.