oracle 更改列数据类型

esyap4oy  于 2023-10-16  发布在  Oracle
关注(0)|答案(2)|浏览(124)

如何将一列数字转换为一列数字。
在myTable中,m_no是一个整数。现在我希望将m_no列更改为整数列表,而不会丢失当前存储的值。

CREATE TABLE myTable (
    m_id,
    m_no
);
hpcdzsge

hpcdzsge1#

不要尝试在列中存储一列数字(尤其不要以逗号分隔值的形式)。
你应该做的是创建一个新的表:

CREATE TABLE myTable (
    m_id NUMBER PRIMARY KEY
);

CREATE TABLE myTable_numbers (
    m_id REFERENCES mytable(m_id),
    m_no NUMBER(10,0)
);

然后,当你想获取一个id的数字列表时,你可以使用JOIN

SELECT mt.m_id,
       mtn.m_no
FROM   mytable mt
       LEFT OUTER JOIN mytable_numbers mtn
       ON (mt.m_id = mtn.m_id)

其中,对于样本数据:

INSERT ALL
  INTO myTable (m_id) VALUES (1)
  INTO myTable (m_id) VALUES (2)
  INTO myTable (m_id) VALUES (3)
  INTO myTable_numbers (m_id, m_no) VALUES (1, 1)
  INTO myTable_numbers (m_id, m_no) VALUES (1, 2)
  INTO myTable_numbers (m_id, m_no) VALUES (1, 3)
  INTO myTable_numbers (m_id, m_no) VALUES (3, 2)
  INTO myTable_numbers (m_id, m_no) VALUES (3, 4)
SELECT 1 FROM DUAL;

输出:
| M_ID| M_NO|
| --|--|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 3 | 2 |
| 3 | 4 |
| 2 |* 空 *|
或者,如果你想要一个逗号分隔的数字列表(出于显示目的),那么JOIN和aggregate:

SELECT mt.m_id,
       LISTAGG(mtn.m_no, ',') WITHIN GROUP (ORDER BY mtn.m_no) AS m_nos
FROM   mytable mt
       LEFT OUTER JOIN mytable_numbers mtn
       ON (mt.m_id = mtn.m_id)
GROUP BY mt.m_id;

其输出:
| M_ID| M_NOS|
| --|--|
| 1 |一二三|
| 2 |* 空 *|
| 3 |二、四|
如果要修改现有表以使用两个表,则:
1.使用上面的reference语句创建myTable_numbers表(没有引用约束)。
1.使用INSERT INTO mytable_numbers (m_id, m_no) SELECT m_id, m_no FROM my_table;复制数据
1.从mytable删除m_no列。
1.从myTable中删除重复的m_id值。
1.在mytable.m_id上添加主键或唯一约束。
1.将mytable_numbers.m_id上的引用约束添加到mytable.m_id
如果你真的想要一列数字列表(不要),那么使用嵌套表:

CREATE TYPE int_list IS TABLE OF NUMBER(10,0);

CREATE TABLE myTable (
  m_id  NUMBER,
  m_nos int_list
)
STORE m_nos AS mytable_numbers;

然后,您可以插入相同的数据:

INSERT ALL
  INTO mytable (m_id, m_nos) VALUES (1, int_list(1,2,3))
  INTO mytable (m_id, m_nos) VALUES (2, int_list())
  INTO mytable (m_id, m_nos) VALUES (3, int_list(2,4))
SELECT 1 FROM DUAL;

并使用查询:

SELECT mt.m_id,
       mtn.COLUMN_VALUE
FROM   mytable mt
       LEFT OUTER JOIN TABLE(mt.m_nos) mtn
       ON 1 = 1;

SELECT mt.m_id,
       LISTAGG(mtn.COLUMN_VALUE, ',') WITHIN GROUP (ORDER BY mtn.COLUMN_VALUE)
         AS m_nos
FROM   mytable mt
       LEFT OUTER JOIN TABLE(mt.m_nos) mtn
       ON 1 = 1
GROUP BY mt.m_id;

给出与上面相同的输出。
fiddle

rlcwz9us

rlcwz9us2#

这不是一个简单的任务,因为如果列不是空的(而你的不是),你不能改变列的数据类型。
而且,它取决于你所说的“整数列表”;一个简单的选项是它是否表示具有逗号分隔的整数值的字符串。基本上,varchar2数据类型列。或者,您是想使用嵌套表吗?
假设它是一个简单的 string,下面是一个演练:
原始表格与一些值:

SQL> create table mytable (m_id number, m_no number);

Table created.

SQL> insert into mytable values (1, 100);

1 row created.

如果你只是尝试改变m_no列的数据类型,它不会工作:

SQL> alter table mytable modify m_no varchar2(50);
alter table mytable modify m_no varchar2(50)
                           *
ERROR at line 1:
ORA-01439: column to be modified must be empty to change datatype

因此,添加一个新列(以存储“原始”值):

SQL> alter table mytable add m_no_old number;

Table altered.

SQL> update mytable set m_no_old = m_no;

1 row updated.

清空原始列:

SQL> update mytable set m_no = null;

1 row updated.

更改其数据类型:

SQL> alter table mytable modify m_no varchar2(50);

Table altered.

将原始值移回:

SQL> update mytable set m_no = m_no_old;

1 row updated.

删除新添加的列:

SQL> alter table mytable drop column m_no_old;

Table altered.

添加更多 integers

SQL> update mytable set m_no = m_no || ', 200, 300';

1 row updated.

测试结果:

SQL> select * from mytable;

      M_ID M_NO
---------- --------------------------------------------------
         1 100, 200, 300

相关问题