Veamos la siguiente situación:
"Tienes una tabla en donde el tipo de dato definido para una columna específica, no corresponde con el modelaje que habías hecho. La tabla ya tiene tiempo en producción y la columna en cuestión, ya tiene datos.
Problema: Requieres cambiar el tipo de dato obligatoriamente, pero al ejecutar la modificación sobre la tabla, obtienes el siguiente error:"
SQL> ALTER TABLE CND_FACTURA MODIFY CODIGO_SEGURIDAD VARCHAR2(8 byte);
MODIFY CODIGO_SEGURIDAD VARCHAR2(8 byte)
*
ERROR at line 2:
ORA-01439: column to be modified must be empty to change datatype
Para resolver este inconveniente, puedes utilizar el siguiente método, para evitar cambiar el orden de las columnas en la tabla.
Pre-requisitos:
- La columna a modificar no posee un constraints de NOT NULL. Si fuera así, debe desactivarse inicialmente el mismo.
- La modificación en la tabla, puede ocasionar objetos inválidos en el esquema, por dependencias con el objeto. Si es posible, genere una ventana de mantenimiento para evitar errores con el usuario final.
Post-ejecución:
- Activar constraints en la tabla que hayan sido deshabilitados.
- Verifique que no existen objetos inválidos. Previamente sería adecuado validar las dependencias en el objecto y determinar, cuáles objetos podrían quedar inválidos con el cambio. Para obtener las dependencias en la tabla, puedes utilizar el paquete DBMS_UTILITY, como se detalla a continuación:
set serveroutput on;
exec dbms_utility.get_dependency('TABLE', '&Esquema','&TABLA');
Ahora si, vamos al problema. Nuestra tabla es la siguiente:
SQL> desc CND_FACTURA
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(38)
....
COD_MONEDA VARCHAR2(3)
IND_IMPRESA VARCHAR2(1)
COD_FONDO NUMBER(3)
NOM_INQUILINO VARCHAR2(150)
TERCERA_PERSONA VARCHAR2(150)
NUM_RECIBO_IMPRESO NUMBER(38)
IND_APROBACION VARCHAR2(1)
CODIGO_SEGURIDAD NUMBER(8)
NUM_FACTURA_ATV NUMBER(38)
Paso 1: Vamos a agregar una nueva columna con el tipo de dato que necesito migrar.
SQL> alter table CND_FACTURA add codigo_seguridad_original varchar2(8);
Table altered.
Paso 2: Vamos a actualizar los valores ya existentes en la columna que necesito modificar en la columna que hemos agregado.
SQL> update CND_FACTURA set codigo_seguridad_original=codigo_seguridad;
3315 rows updated.
Paso 3: Ahora actualizamos a NULL los valores para la columna que necesito migrar.
SQL> update cnd_factura set codigo_seguridad=null;
3315 rows updated.
Paso 4: Modificar a la nueva precisión o tipo de dato la columna con el problema.
SQL> ALTER TABLE CND_FACTURA MODIFY CODIGO_SEGURIDAD VARCHAR2(8 byte);
Table altered.
Paso 5: Actualizar la columna modificada, con los valores originales que contenía la misma.
SQL> update CND_FACTURA set codigo_seguridad=codigo_seguridad_original;
3315 rows updated.
SQL> commit;
Commit complete.
SQL> select count(*) from CND_FACTURA where codigo_seguridad is not null;
COUNT(*)
----------
132
Paso 6: Remover la columna que habíamos agregado al inicio del ejercicio.
SQL> alter table CND_FACTURA drop column codigo_seguridad_original;
Table altered.
SQL> desc CND_FACTURA
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(38)
ID_CUOTA_CONDOMINAL NOT NULL NUMBER(38)
FEC_FACTURA NOT NULL DATE
FEC_VENCIMIENTO NOT NULL DATE
FEC_CANCELACION DATE
IND_ESTADO NOT NULL VARCHAR2(1)
MON_FACTURA NOT NULL NUMBER(38,2)
SALDO_FACTURA NUMBER(38,2)
INT_MOROCIDAD NUMBER(38,2)
TIPO_FACTURA NOT NULL VARCHAR2(1)
NUM_RECIBO_CANCELACION NUMBER(38)
ID_USUARIO_MODIFICA NOT NULL VARCHAR2(35)
FEC_MODIFICACION NOT NULL DATE
IND_ENVIADO_CORREO NOT NULL VARCHAR2(1)
OBS_FACTURA VARCHAR2(255)
ID_INQUILINO NUMBER(38)
COD_MONEDA VARCHAR2(3)
IND_IMPRESA VARCHAR2(1)
COD_FONDO NUMBER(3)
NOM_INQUILINO VARCHAR2(150)
TERCERA_PERSONA VARCHAR2(150)
NUM_RECIBO_IMPRESO NUMBER(38)
IND_APROBACION VARCHAR2(1)
CODIGO_SEGURIDAD VARCHAR2(8)
NUM_FACTURA_ATV NUMBER(38)
SQL>
Excelente, justo tuve este problema y estaba entre esta misma opcion o crear otra tabla. Simple y efectivo!
ResponderEliminar