jueves, 16 de septiembre de 2010

SQL. Recorrer y actualizar ciertos registros de una tabla. Cursores.

A veces, mi ignorancia en el lenguaje SQL que hace verme forzado a trabajar en horas intempestivas como hoy (terminar a las 02:00 para reiniciar a las 06:00).

El problema es que tengo una tabla de cientos de miles de registros con un campo expediente que tiene que ser único. Es decir, que no admita duplicados. Y en dicho campo, 290 mil registros tienen un valor que es vacio, es cero o es directamente null.

El quid del asunto es localizar dichos registros y actualizarme el campo expediente con una id construido.

Después de demasiadas horas perdidas, la madrugada y un reparador mini sueño, me trajo la respuesta en forma de Cursores.

Primero declaremos las variables que voy a utilizar en las operaciones.

-- Id del registro
-- Campo expediente a modificar
-- Contador, campo numérico autoincremental que vamos a almacenar en el campo expediente
declare @id as nvarchar(16)
declare @expediente as varchar(30)
declare @contador as int

A continuación declaramos el cursor, para manipular los datos solamente sobre los expedientes que cumplen la condición, en vez de sobre los cientos de miles de toda la tabla.

declare CURSORVC cursor for
  select id, expediente  from Tabla
  Where
  expediente = '0'
  OR expediente = ''
  OR expediente = null
  OR expediente IS NULL
  Order by id

Inicializamos el contador.

SET @contador = 10

Y abrimos el cursor, recuperando la primera fila. Aquí lo único que hay que tener cuidado es que las variables en las que cargamos los datos del cursor sean correspondientes a los campos obtenidos en la select de la declaración del cursor.

open CURSORVC
  fetch next from CURSORVC into @id, @expediente

A continuación iniciamos el bucle

while @@fetch_status = 0
    begin

Actualizamos los datos del campo expediente cuando el id sea el del registro que nos ha traido el cursor

update Tabla set expediente =  CAST(@contador As varchar(10)) + ' -2010'
    where id=@id
    -- Avanzamos otro registro
    fetch next from CURSORVC into @id, @expediente

-- Avanzamos el contador en uno
    set @contador = @contador + 1
   end

Y fínalmente cerramos el cursor y lo eliminamos de memoria

      close CURSORVC
deallocate CURSORVC

Y así, lo que por código tardaba horrores, pero horrores de los malos, ahora he actualizado los casi trescientos mil registros en menos de tres minutos.

P.D. Besitos al Borjus que me recordó que con experiencia un cursor como este se hace en unos 10 minutos, contra las cinco horas que me ha costado el primero mío :)

miércoles, 15 de septiembre de 2010

Listado de registros duplicados de una tabla. SQL.

Tengo una tabla que estoy migrando de base de datos que contiene un registro que contiene un id de expediente que debe ser único para poder ponerle la clave  principal.
Y la verdad que el lenguaje SQL puede conmigo… pero tengo un equipo que vale oro y en una mini reunión me llevaron de la mano al siguiente código:
SELECT expediente, count(expediente)
FROM [tabla]
group by expediente
having count(expediente)  > 1


El cual me devuelve un listado de todos los expedientes que, al menos, estén duplicados.

Y después de corregir la tabla, ya puedo hacer clave primaria este campo.

martes, 7 de septiembre de 2010

Patron Factory

Hoy es un día de alegría para mí. He puesto en código de producción mi segundo patrón aprendido y aprehendido (como decía mi profesora de inglés).

Tengamos una clase que representa a un número tal cual así:
public class Numero
{
    private int _cifra;
    public int cifra
    {
        get { return _cifra; }
        set{ _cifra = value; }
    }
}
Esta clase lo único que hace es almacenar una cifra numérica en una propiedad pública llamada cifra. Y tiene un constructor (absolutamente prescindible) vacio. Osea que no hace más que construir una instancia de nuestro número.

Ahora voy a llamar a otra clase, muy simple, llamada GestionDeNumeros que tiene un solo método que recupera un número y hace “algo” con él. Osea que de forma tradicional instancio la clase número e introduzco un valor en su propiedad cifra.
public class GestionNumeros
{
    public void RecuperaNumero()
    {
        NumeroobjetoNumero = newNumero();
        int resultado = objetoNumero.cifra + 1;
    }
}
Pero, si quiero delimitar de forma más estricta el número que me quiero traer tengo la opción de hacer un nuevo constructor que tenga como parámetro de entrada la cifra que quiero obtener,
    public class Numero
  
{
        private int _cifra;
        public int cifra
        {
            get { return _cifra; }
            set{ _cifra = value; }
        }

        public Numero(int pCifra)
        { _cifra = pCifra; }

    }

    public class GestionNumeros
  
{
        public void RecuperaNumero()
        {
            NumeroobjNumero = newNumero(5);
            int suma = objNumero.cifra + 1;
        }
    }
}
Pero ¿si quiero recuperar un número que sea distinto al que le quiero pasar? o si quiero un numero que esté entre otros dos números? o que sea el primer número par mayor que el número que le paso por parámetro? o que sea el número que le paso por parámetro multiplicado por si mismo?

Como ves si lo quisiera hacer por constructores sobrecargados me acababa de meter en un berenjenal de narices. Pero gracias al patrón Factory y a quien lo halla descubierto y explicado, es tan simple como el crear métodos estáticos de la clase que realicen la construcción y que  me devuelvan la instancia. Vamos a hacer el último requisito, para que se vea lo sencillo que es y la potencialidad, construyendo el método estático que me va a construir el objeto número que deseamos,
public class Numero
{
    private int _cifra;
    public int cifra
    {
        get { return _cifra; }
        set{ _cifra = value; }
    }

    public Numero()
    { }

    public static Numero CreaNumeroMultiplicadoPorSiMismo(int numero)
    {
        Numero objetoNumero = new Numero();
        objetoNumero.cifra = numero * numero;
        return objetoNumero;
    }

}
Y ahora lo vamos a invocar, que es donde está la magia,
public class GestionNumeros
{
public void RecuperaNumero()
{ 
Numero resultado = Numero.CreaNumeroMultiplicadoPorSiMismo(5);
}
}


Teniendo en cuenta que con este patrón le puedo pasar cualquier tipo de información al constructor, es de indudable potencia y utilidad una vez que el escurridizo concepto se entiende.


P.D. Siguiente objetivo: Utilizar una interface…

Actualización 09/09/2010 Muy buen documento sobre patrones de fabrica

jueves, 2 de septiembre de 2010

Agile-Madrid. Septiembre 2010.

De forma sorpresiva me vi con el tiempo libre para ir a la reunión de principio de mes del grupo Agile de Madrid el pasado uno de septiembre. He de reconocer que el saber que, nada menos,  tres MVP de Microsoft iban a asistir a la reunión me despejaron la pereza que siempre me embarga en el último momento y en el sofá de mi casa.
IMAG0160 
La esquina del “lado oscuro”… :)

Los asistentes nos quedamos sorprendidos también al comprobar que nos habíamos juntando un montón (19 personas) y empezamos con las presentaciones justo antes de iniciar el primer tema que trataba sobre “El contrato Agile en la Administración pública”.
Como muy bien reflejó uno de los compañeros, existen dos tipos de contrato:  por Servicios y por Obras. Y el contrato Agile al que nos estábamos referenciando se podría considerar como un contrato por Obra pero con la particularidad de que su alcance y prioridad pueden cambiar.
Yo creo que es impepinable lo de hacer un documento de alcance/tiempo inicial para sentar las bases de la colaboración. Aunque muchos opinen que eso no es una práctica Agile.
También estuvimos de acuerdo en que es necesario un “suelo” de gastos para que las empresas pequeñas y medianas puedan asumir el riesgo de conformar un equipo y no quedarse en perdidas directas por ser paralizado el proyecto en una o dos de las primeras iteraciones.
El debate ha seguido en el foro De Agile-Spain, y está siendo muy interesante.

IMAG0161 
Escogiendo los temas de la próxima reunión.
A continuación entramos a debatir “Cómo vender TDD a los jefes”. Lo cual llevó a la primera conclusión: cuanto menos técnico más fácil de venderlo. Lo cual llevo a la siguiente conclusión, ¿porqué debes venderlo si es una práctica puramente técnica?
Como llevo ya bastante tiempo dubitativo con TDD, pregunté si había alguna mejora en el desarrollo de un proyecto por usar TDD y solamente JMB habló de una cierta métrica que indicaba que los desarrollos con esta técnica son más predecibles. Ante mi pregunta de cuantos utilizaban TDD actualmente, levantaron la mano solamente cinco de las diecinueve personas asistentes (tres de ellos mis “ídolos” de .NET). Por último, las respuestas a las preguntas de David sobre argumentos para convencer a los desarrolladores que utilicen TDD, me llevan a mi conclusión personal:

La Fe es el mejor argumento para pasarse al TDD

Es decir, el saber que gente del nivel de Alfredo o Luís Fraile utilizan TDD, es lo que me puede motivar a utilizar esta técnica. Porque, sin haberla utilizado, la argumentación que la promueva es, a mi entender, poco motivadora ante el enorme esfuerzo que implica el cambio de paradigma.
 IMAG0156 IMAG0158

A continuación, y finalizada la reunión, nos fuimos a beber cervecitas al bareto de al lado, y a eso de las once de la noche cogí mi vehículo para volver a mi casa, henchido de conocimiento y con ganas de ir a la próxima.