Sidebar

Una de las causas por las que extraemos información de un a tabla por medio de un BCP es para eliminar la fragmentación que puede tener una tabla, pero debemos de tener en cuenta que el hacer esto para después volver a insertar la información con otro BCP puede alterar nuestros datos.

En la mayoría de los casos no se altera la información al ser extraída por un BCP y después insertarla por medio de otro BCP. Pero existen casos en los que si pueden verse afectadas. Veamos el siguiente ejemplo:

Creamos una tabla en donde ponemos un default de 99 para la columna b.

create table t (a char(8), b int default 99 NULL)
go

insert t values ("uno", 1)
insert t values ("dos", NULL)
go

select * from t
go
a b
-------- -----------
uno 1
dos NULL

Extraemos la información por medio de un BCP out

bcp dbtest..t out t.bcp -Usa -Ppswd -SSERVIDOR –c


Vaciamos la tabla por medio de un truncate

truncate table t
go


Insertamos nuevamente la información

bcp dbtest..t in t.bcp -Usa -Ppswd -SSERVIDOR –c

Hacemos un select de los datos, y vamos a ver que la columna b del segundo registro es diferente.

select * from t
go
a b
-------- -----------
uno 1
dos 99


El problema se a la columna que tiene un default, ya que al extraer los datos por medio de un BCP las columnas con valores nulos quedan como columnas vacías, por lo que a la hora de insertarlos por medio de un BCP funcionan como un insert sin tener un valor especificado, por lo que se les aplica el default de 99.

Esto es como si se aplicara el siguiente insert:

insert t(a) values ("dos")

Este problema no puede ser cambiado por medio del BCP, por lo que se debe de tener cuidado con las tablas que contengas valores por default y que contengan nulos ya que puede volverse un verdadero problema.

La forma de solucionar esto es muy simple, debemos de remover la propiedad de default antes de hacer el BCP-in, después de cargar los registros volver a ponerla.
Si existe un valor de default definido, podría también ser cambiado a un valor nulo temporalmente.

alter table t replace b default null

Después de haber restaurado la tabla se vuelve a dejar como originalmente estaba.

alter table t replace b default 99

En caso de que el default se haya creado como un objeto y ligado a la columna por medio del commando sp_bindefault, puede usarse el commando unbindefault, cargar los datos y posteriormente volver a usa el commando sp_bindefault.

Para encontrar las columnas donde este problema puede ocurrir (columnas que tengan definido un default y acepten nulos”, se puede ejecutar el siguiente query:

select object_name(id) + "." + name "Table.Column",
object_name(cdefault) "Default"
from syscolumns
where cdefault > 0 and status & 8 = 8

Este otro query nos va a ayudar a generar los queries necesarios para revisar que los datos no contengan valores nulos.

select "select '" + object_name(id) + "." + name + "',
count(*) '#null values' from " + object_name(id) +
" where " + name + " = NULL"
from syscolumns
where cdefault > 0 and status & 8 = 8


Conclusión
No use un BCP-in a menos de que se haya verificado que no existan columnas con un valor por default definido y acepte nulos y que los datos no contengan los valores nulos para esa columna.


Tips BD