Buscar este blog

31 mayo 2011

Cambiar precisión de columnas decimal

No les pasó alguna vez que subestimaron el tamaño de una columna tipo decimal? y despues no sabían por qué empezaron a desbordarse por doquier!?. Bueno les hice un pequeño script t-sql que les va a solucionar la vida.

En mi caso quería cambiar todas las columnas de precisión (10,4) a (18,4) ya que en realidad SQL Server utiliza la misma cantidad de bytes (9 bytes) para almacenar cualquiera de estas dos configuraciones del tipo decimal, con lo cual en estos casos conviene utilizar la máxima precisión posible dentro de cada rango especificado en este enlace donde podrán ver la tabla que muestra la relación precisión - tamaño en bytes.

También en el enlace anterior se explica para los que no saben, que la precisión es la cantidad total de dígitos a almacenar y la escala, que es opcional, indica la cantidad de posiciones decimales.
Por ejemplo 10,2 significa 10 dígitos en total de los cuales 8 son enteros y 2 decimales.

El sript convierte todos los campos decimal de la base de datos que este en uso al momento de su ejecución a su máxima precisión para el numero de bytes actual que esta ocupando, también incrementa los lugares decimales de 2 a 4 dígitos. Se puede modificar fácilmente este script para que por ejemplo aumente todos los campos decimal a una precisión deseada o cualquier otra condición que sea necesaria, la base está... a meterle mano sin miedo (previo backup y en ambiente de testing)

-- VARIABLES
DECLARE @tblName0 NVARCHAR(150)
DECLARE @tblName NVARCHAR(150)
DECLARE @colName NVARCHAR(150)
DECLARE @colDataType NVARCHAR(50)
DECLARE @colNumericPrecision NUMERIC
DECLARE @colNumericScale NUMERIC
DECLARE @colIsNullable CHAR(3)
DECLARE @cont int
-- CURSOR
DECLARE cur_tables CURSOR FOR
select t.table_name, column_name, data_type,
numeric_precision, numeric_scale, is_nullable
from information_schema.columns c
inner join information_schema.tables t
on c.table_name=t.table_name
and table_type='BASE TABLE'
and data_type='decimal'
OPEN cur_tables
FETCH NEXT FROM cur_tables INTO @tblName, @colName, @colDataType,
@colNumericPrecision, @colNumericScale, @colIsNullable
SET @tblName0=''
SET @cont=0
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @Precision VARCHAR(2)
DECLARE @Scale VARCHAR(2)
DECLARE @Nulls VARCHAR(10)

-- Máxima precisión posible sin aumentar
-- la cantidad de bytes necesarios.
IF @colNumericPrecision <= 9
SET @Precision = '9'
ELSE IF @colNumericPrecision <= 19
SET @Precision = '19'
ELSE IF @colNumericPrecision <= 28
SET @Precision = '28'
ELSE IF @colNumericPrecision <= 38
SET @Precision = '38'
-- Incrementar a 4 decimales
IF @colNumericScale < 4
SET @Scale = '4'
ELSE
SET @Scale = CAST(@colNumericScale as VARCHAR(2))

-- ES NECESARIO CAMBIAR LA COLUMNA?
IF (@colNumericPrecision <> CAST(@Precision as NUMERIC) OR
@colNumericScale <> CAST(@Scale as NUMERIC))
BEGIN
IF @colIsNullable='YES'
SET @Nulls = 'null'
ELSE
SET @Nulls = 'not null'

EXEC('alter table ' + @tblName +
' alter column ' + @colName + ' decimal(' + @Precision + ',' + @Scale + ') ' + @Nulls)
SET @cont=@cont+1
IF @tblName<>@tblName0
BEGIN
SET @tblName0=@tblName
PRINT '--------------------'
PRINT @tblName
PRINT '--------------------'
END
PRINT char(9) + @colName + ' se ha cambiado de: ' + @colDataType +
'('+ cast(@colNumericPrecision as nvarchar(50)) + ',' +
cast(@colNumericScale as nvarchar(50)) + ')' +
' a decimal(' + @Precision + ',' + @Scale + ') '
END --IF
-- OBTENER SIGUIENTE COLUMNA A TRATAR
FETCH NEXT FROM cur_tables INTO @tblName, @colName, @colDataType,
@colNumericPrecision, @colNumericScale, @colIsNullable
END
PRINT '----------------------------------------------------------'
PRINT cast(@cont as nvarchar(10)) + ' columnas afectadas.'
CLOSE cur_tables
DEALLOCATE cur_tables

Si sos principiante aquí vimos varias cosas que te recomiendo leer antes de intentar cualquier cosa: manejo de cursores, estructuras condicionales, consultas a las vistas de información de esquema y la instrucción EXEC[UTE].
Hasta la próxima!

27 mayo 2011

Información sobre un objeto

Para los que usamos alguna vez Oracle sabemos que con el comando DESC[RIBE] obtenemos información acerca de una tabla en particular, ahora bien para SQL Server, no existe tal comando con lo cual buscando encontré un pequeño pero útil procedimiento almacenado que cumple dicha función, este es sp_help.
¿Cómo lo usamos?

exec sp_help ó simplemente sp_help

Lo interesante es que no solo brinda información sobre tablas sino que también sobre stored procedures (muy util para ver que parámetros recibe de que tipo y que resultado devuelve), vistas, triggers, funciones, y cualquier otro objeto de nuestra base de datos.

Probar sp_help sp_help
...y como es de esperar sp_help nos brindará información sobre sí mismo ya que es un procedimiento almacenado más...

Es una pavada pero a alguien le podría servir. Hasta la próxima.