Oracle 如何在使用列时修改列数据类型

Oracle 如何在使用列时修改列数据类型,oracle,function,plsql,Oracle,Function,Plsql,我在使用SELECT查询时遇到问题。不幸的是,ID被存储为VARCHAR,这是一个很大的错误,现在我在下面的函数中遇到了问题 FUNCTION GET_SUB_PROJECTS(p_currentUserId IN VARCHAR,p_projectId IN INT) RETURN SYS_REFCURSOR IS rc SYS_REFCURSOR; -- getSubProject BEGIN OPEN rc FOR SELECT p.*,

我在使用SELECT查询时遇到问题。不幸的是,
ID
被存储为
VARCHAR
,这是一个很大的错误,现在我在下面的函数中遇到了问题

FUNCTION GET_SUB_PROJECTS(p_currentUserId IN VARCHAR,p_projectId IN INT)
    RETURN SYS_REFCURSOR IS 
    rc  SYS_REFCURSOR;
    -- getSubProject
BEGIN
OPEN rc FOR
   SELECT
         p.*,
         a.number_ AS activityNumber,
         a.description AS activityDescription
   FROM
         projects p
   LEFT JOIN
         project_users_schedule_dates pusd
   ON
         pusd.ProjectID = p.ProjectID AND pusd.UserID = p_currentUserId
   LEFT JOIN
        activities a
   ON
        a.id = p.activity
   LEFT JOIN 
       responsible_persons rp
   ON 
       rp.ProjectID = p.ProjectID AND rp.UserID = p_currentUserId
   LEFT JOIN 
       users u
   ON 
      u.UserID = p_currentUserId
   WHERE
     (u.User_roleID = 1 AND
     p.CustomName LIKE CONCAT((SELECT CustomName FROM projects pr WHERE pr.ProjectID = p_projectId), '%') AND p.ProjectID <> p_projectId)
     OR 
   ((
      (p.Responsible_person_id = p_currentUserId OR p.Delivery_contact = p_currentUserId OR rp.UserID = p_currentUserId OR (pusd.UserID = p_currentUserId AND SYSTIMESTAMP BETWEEN TO_DATE(pusd.StartDate,'YYYY-MM-DD') AND TO_DATE(pusd.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY AND
       SYSTIMESTAMP BETWEEN TO_DATE(p.StartDate,'YYYY-MM-DD') AND TO_DATE(p.EndDate,'YYYY-MM-DD') + INTERVAL '1' DAY))
    )
     AND
         p.CustomName LIKE CONCAT((SELECT CustomName FROM projects pr WHERE pr.ProjectID = p_projectId), '%') AND p.ProjectID <> p_projectId)
         ORDER BY p.CustomName;      
RETURN rc;
END GET_SUB_PROJECTS;
我找到了一个可以修改的解决方案,但它给我带来了类似这样的错误

Error report -
ORA-01439: column to be modified must be empty to change datatype
01439. 00000 -  "column to be modified must be empty to change datatype"
在这种情况下该怎么办?解决此问题的最佳方法是什么?

您可以使用
dbms\u重新定义

create table t (
  c1 varchar2(10)
    primary key
);

create table t_new (
  c1 number(10, 0)
    primary key
);

insert into t values ( '1.0000' );
commit;

begin 
  dbms_redefinition.start_redef_table ( 
    user, 't', 't_new', 
    col_mapping => 'to_number ( c1 ) c1', 
    options_flag => dbms_redefinition.cons_use_rowid 
  );
end;
/
exec dbms_redefinition.sync_interim_table ( user, 't', 't_new' );
exec dbms_redefinition.finish_redef_table ( user, 't', 't_new' );

desc t

Name   Null?      Type         
C1     NOT NULL   NUMBER(10)

select * from t;

C1   
    1 
在此过程中,还可以选择自动复制约束、触发器、索引等。

您可以使用
dbms\u重新定义

create table t (
  c1 varchar2(10)
    primary key
);

create table t_new (
  c1 number(10, 0)
    primary key
);

insert into t values ( '1.0000' );
commit;

begin 
  dbms_redefinition.start_redef_table ( 
    user, 't', 't_new', 
    col_mapping => 'to_number ( c1 ) c1', 
    options_flag => dbms_redefinition.cons_use_rowid 
  );
end;
/
exec dbms_redefinition.sync_interim_table ( user, 't', 't_new' );
exec dbms_redefinition.finish_redef_table ( user, 't', 't_new' );

desc t

Name   Null?      Type         
C1     NOT NULL   NUMBER(10)

select * from t;

C1   
    1 

在此过程中,还可以选择自动复制约束、触发器、索引等。

只需使用CTAS语句重新创建表格:
创建表格t2作为ID,从t
,然后
将表格t2重命名为t
,如果您确定
ID
列中根本包含数值。对不起,我不明白你的意思。请你再描述一下好吗。TNX您想要的是更改ID列的数据类型,不是吗?通过这种建议的方式,您可以更改为数字数据类型,而不会出现
ORA-01439
错误。顺便说一句,将重命名语法替换为
RENAME t2 to t
Yes,从VARCHAR更改为NUMBER@BarbarosÖzhan你能根据我的问题给出答案吗。因此,负责人Id必须是数字(10,0)和送货联系人。我将非常感激。只要使用CTAS语句重新创建表:
创建表t2作为ID,从t
中选择数字(ID)作为ID,然后
将表t2重命名为t
,如果您确定
ID
列包含所有数值。对不起,我不明白您的意思。请你再描述一下好吗。TNX您想要的是更改ID列的数据类型,不是吗?通过这种建议的方式,您可以更改为数字数据类型,而不会出现
ORA-01439
错误。顺便说一句,将重命名语法替换为
RENAME t2 to t
Yes,从VARCHAR更改为NUMBER@BarbarosÖzhan你能根据我的问题给出答案吗。因此,负责人Id必须是数字(10,0)和送货联系人。我会非常感激的。