如何在Oracle中更改表,同时添加与不同表中的列类型相同的列

8cdiaqws  于 2023-10-16  发布在  Oracle
关注(0)|答案(4)|浏览(139)

我有两张table:表1和表2。
表2中有一个数据类型为Varchar2(30)的customerId字段,如何使用%type更改表1以添加与表2相同数据类型的customerId字段。
我试了下面的代码,但没有运气。

alter table table2
add  customer_id table1.CUSTOMER_ID%type;

是否可以使用%type修改?这将工作。请告知

如果不起作用,我是否应该手动说明

alter table table2
add  customer_id varchar2(30);
oymdgrw7

oymdgrw71#

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,还有什么会受到影响?在那之后还有什么需要改变的?那么使用这些列的所有程序代码呢?
数据管理很难,但这是有原因的。与源代码不同,数据库有状态。改变状态是昂贵的,恢复到以前的状态更是如此。更改列的数据类型意味着更改该列中所有数据的状态。这不是一件轻而易举的事。
所以。好好分析一下。有一个好的数据模型。了解您的数据结构。这些都是良好的做法。

tkqqtvp1

tkqqtvp12#

--第1步:解密与table2.customerId数据类型相同的变量

DECLARE
  v_customerId table2.customerId%TYPE;

BEGIN
  -- This block is used to declare the variable.
  NULL;
END;

--步骤2:使用变量向table 1添加新列

ALTER TABLE table1
ADD (new_customerId VARCHAR2(30)); -- Use the same data type as table2.customerId

--可选:使用来自table2.customerId的数据更新table 1中的新列--如果需要,可以使用UPDATE语句将数据从table 2复制到table 1。--例如:

UPDATE table1
SET new_customerId = (SELECT customerId FROM table2 WHERE ...);
oaxa6hgo

oaxa6hgo3#

这不是一个答案(mathguy已经告诉过你了),但是一个评论对于我想说的话来说有点“简短”。
在参加HrOUG会议时,我看到一个穿T恤的人说,
感谢您花了几个月的时间编写代码,为我们节省了几天的规划时间
换句话说,仔细选择CUSTOMERID数据类型。如果你今天向13个客户销售产品,不要将其设置为NUMBER(2),因为(如果你的公司发展并变得繁荣),你很快就会向成千上万的客户销售产品。您是否会首先将它(及其所有依赖列数据类型,以及它在应用程序中的所有外观)更改为NUMBER(3),然后更改为NUMBER(4),等等?想想未来吧!
同样,在同一次会议上,有人说他们有570列的表。天啊!5-7-0!他们用这样的table做什么?他们的回答是:“我们付给甲骨文很多钱。它允许我们创建包含1000列的表,我们将使用其中的每一列。”观众有点困惑(提示:正常化?),但是嘿-这是他们的选择。
是的,我注意到您为该ID列选择了VARCHAR 2数据类型。(我并不是说这是错误的,但是我更喜欢数字而不是字符串)那么,你觉得呢?30个字够吗?如果设置为50个字符,需要多少钱?或者100?它们不会占用磁盘上的任何额外空间。如果在VARCHAR 2(100 BYTE)列中有'A234',它将在磁盘上只占用4个字节。内存是另一回事,因为当你在PL/SQL代码中使用这样的变量时,Oracle会预先分配空间,所以你可能会不必要地浪费空间。增加更多RAM?当然,这是一种选择,但它需要钱。
因此,请再次仔细设计您的数据模型,并遵循受支持的ALTER TABLE语法。

cqoc49vn

cqoc49vn4#

注意:请谨慎使用

只有在你读过所有其他答案,仍然认为你想要这样做之后,才使用这个方法。
要使用触发器,请执行以下操作。下面只是一个将customer_id视为NUMBER类型的示例。对于VARCHAR2DATE等,您需要一种通用的方法来构造customer_id。在动态表创建中引用问题

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;
/

相关问题