我有两个表:table1和table2。
数据类型为Varchar2(30)的table2中有一个customerId字段,如何使用%type更改table1以添加与table2相同数据类型的customerId字段。
我尝试了以下代码,但没有运气。
alter table table2
add customer_id table1.CUSTOMER_ID%type;
是否可以使用%type更改?这会有用吗请指教。
如果它不起作用,我应该通过陈述
手动完成alter table table2
add customer_id varchar2(30);
答案 0 :(得分:0)
这不是一个答案(mathguy已经告诉过你),但对于我想说的内容,评论有点“简短”。
在参加HrOUG会议时,我看到一个男人穿着T恤说
感谢您花费数月时间编写代码。为我们节省了几天的时间
换句话说,请仔细选择CUSTOMERID数据类型。如果您今天向13个客户销售产品,请不要将其设置为NUMBER(2)因为(如果您的公司发展并变得繁荣),您很快就会向成千上万的客户销售产品。您是首先将它(及其所有依赖列数据类型,以及它在您的应用程序中的所有外观)更改为NUMBER(3),然后更改为NUMBER(4)等?想想未来!
同样,在同一次会议上,有些人说他们有570列的表格。天哪! 5-7-0!他们用这样的桌子做什么?他们的答案是:“我们向Oracle支付了很多钱。它允许我们创建1000列的表格,我们将使用它们中的每一个。”观众有点疑惑(提示:正常化?),但是嘿 - 这是他们的选择。
是的,我注意到您为该ID列选择了VARCHAR2数据类型。 (我不是说它是错误的,但我不知何故,出于这种目的,我更喜欢数字而不是字符串。)那么,你怎么看? 30个字符就足够了吗?如果将其设置为50个字符,需要多少钱?还是100?它们不会占用磁盘上的任何额外空间。如果VARCHAR2(100 BYTE)列中存在“A234”,则磁盘上只有4个字节 。内存是一个不同的故事,因为当您在PL / SQL代码中使用这样的变量时,Oracle将预先分配空间,因此您最终可能会不必要地浪费空间。添加更多内存?当然,这是一种选择,但需要花钱。
因此,再一次 - 仔细设计您的数据模型,您应该没有问题,遵循支持的ALTER TABLE语法。
答案 1 :(得分:0)
alter table table2 add customer_id table1.CUSTOMER_ID%type;
%type
是一个PL / SQL结构。我们使用它来定义程序中基于表列的局部变量。它在SQL中不起作用。
"如果customerId的数据类型发生变化,我们必须在任何地方手动更改,如果是副本,我们只需要在一个地方进行更改,"
这不是Oracle(以及大多数其他(如果不是全部)数据库的工作方式。它们是用于存储和检索数据的引擎。他们通过强制执行强大的数据输入并使得不小心丢失数据变得容易。数据字典的严谨性可以保护我们免受懒惰自我的侵害。
作为一项思想实验,如果我们执行以下任何一项操作,请考虑对table2.customer_id
的影响:
alter table table1 modify customer_id not null;
alter table table1 modify customer_id number(6,0);
- 来自number(9,0)
alter table table1 modify customer_id number(6,0);
- 来自varchar2(6)
alter table table1 drop column customer_id;
所有这些都是可能的现实案例。对于其中任何一个,table2.customer_id
中的数据状态可能导致语句在table2
上失败(即使它们会在table1
上成功)。这是可取的吗?几乎肯定是的。但现在它意味着我们无法更改table1
,这大大降低了拥有模板列的效用。
"我认为这是一种很好的做法。"
最佳做法是第一次做到正确。显然,这并不总是可能的,因为情况会随着时间的推移而发展。我们需要接受将会有变化,处理变更的良好做法是进行影响评估:如果我们改变table1.customer_id
还有什么可能会受到影响?之后还需要改变什么呢?那些使用这些列的程序代码怎么样?
数据管理很难,但很难有充分的理由。与源代码不同,数据库具有状态。改变状态是昂贵的,并且恢复到以前的状态更是如此。更改列的数据类型意味着更改该列中所有数据的状态。这不是应该轻易做到的事情。
因此。做适当的分析。拥有一个不错的数据模型。了解您的数据结构。这些都是很好的做法。
答案 2 :(得分:0)
注意:使用警告。
只有在阅读完所有其他答案并仍然认为您希望这样做之后才能使用此功能。
使用DDL触发器。以下只是将customer_id
视为NUMBER
类型的示例。对于VARCHAR2
,DATE
等,您需要一种通用方法来构建DDL。请参阅Issue in dynamic table creation
CREATE OR REPLACE TRIGGER trg_alter_table1
AFTER ALTER
ON SCHEMA
WHEN (ORA_DICT_OBJ_TYPE = 'TABLE' AND ORA_DICT_OBJ_NAME = 'TABLE1')
DECLARE
v_ddl VARCHAR2 (200);
BEGIN
SELECT 'ALTER TABLE TABLE2 MODIFY '
|| column_name
|| ' '
|| data_type
|| '('
|| data_precision
|| ')'
INTO v_ddl
FROM user_tab_columns
WHERE table_name = 'TABLE1' AND column_name = 'CUSTOMER_ID';
EXECUTE IMMEDIATE v_ddl;
END;
/