martes, 19 de enero de 2016

SQL Server - Restaurar una base de datos en una ubicación nueva y con un nombre nuevo (Transact-SQL)

-- -- --
-- -- Restaurar una base de datos en una ubicación nueva y con un nombre
-- -- nuevo (Transact-SQL)
--
USE master
GO
-- Primero habría que determinar (si no se sabe) los nombres lógicos de los
-- archivos de la copia de seguridad que se desea restaurar.
RESTORE FILELISTONLY
   FROM DISK = 'D:\MSSQL\Backup\bkp_DB_Sistema'


-- Luego, con los nombres lógicos de los datos (.mdf) y de registro (.ldf)
-- se puede hacer una restauración a una nueva ubicación con la opción MOVE.
RESTORE DATABASE DB_Nueva
   FROM DISK = 'D:\MSSQL\Backup\bkp_DB_Sistema'
WITH REPLACE,
   MOVE 'DB_Sistema_Data' TO 'D:\MSSQL\Data\DB_Nueva_Data.mdf',
   MOVE 'DB_Sistema_Log' TO 'D:\MSSQL\Data\DB_Nueva_Log.ldf'
GO


-- Usar REPLACE, de ser necesario. Si es que se tiene que
-- sobreescribir por ser diferente los nombres lógicos.

SQL Server - Usos no deseados de la operación UNION

Hace pocos días me topé en el trabajo con código SQL embebido, escrito por otro programador tiempo atrás, en donde hacía un uso indebido de la operación UNION. En el ejemplo en cuestión, se quería realizar el promedio de los valores de una columna TOTAL y, si bien todos los valores eran positivos, al sumarlos había que tener en cuenta la columna TIPO para sumarlos o restarlos al resultado, puesto que dependían de esta columna, para saber si eran de tipo créditos o débitos. Es decir, éstos valores dependían de una condición que los separaban en negativos y positivos.

Cuando veo como estaba escrito el código SQL me doy cuenta que el resultado no iba a ser el esperado porque se estaba separando la condición con una operación UNION 
Escribo la consulta en cuestión:


SELECT CantidadCasos = COUNT(*)
      ,Promedio = SUM(Total) / COUNT(*)
FROM Pedidos
UNION ALL
SELECT CantidadCasos = COUNT(*)
      ,Promedio = SUM(Total * (-1)) / COUNT(*)
FROM FACT0003
GO




El conjunto de resultados sería el siguiente:


Como se ve, esto nos da un registro por cada consulta (SELECT) en el caso que se den ambas condiciones (en el caso que la unión sea válida para ambos casos) y por ende, el promedio tampoco va a ser el correcto.

La forma correcta sería tratarlo con una expresión del tipo condicional, CASE o IF, teniendo en cuenta como se hace uso de las consultas de agregado (SUM(), COUNT(), etc) que es en donde muchos se equivocan o creen que no se puede realizar este tipo de consultas. Si prestan atención, el condicional siempre está dentro del agregado (en este caso el CASE dentro del SUM():


SELECT CantidadCasos = COUNT(*)
      ,Importe = SUM(CASE Tipo WHEN 'N' THEN Total * (-1) ELSE Total END) / COUNT(*)
FROM Pedidos
GO



El conjunto de resultados, para la consulta anterior, sería el siguiente:



Ahora sí, el resultado es el esperado.

SQL Server - Operaciones con Fechas y Horas II

Hace unos años publiqué (En el 2010... muchos ya.. tengo que publicar más seguido me parece :D) un primer post sobre operaciones con fechas y horas en SQL Server. Hoy, en el trabajo, se presentó una situación, que podría presentarse alguna otra vez en el futuro, y es bueno documentarlo para no estar pensando como resolverlo y/o googleando al cuete de nuevo.

Teníamos que averiguar el período (osea el intervalo de tiempo), en días, entre dos fechas para después usar los días para sumarlo a una fecha. Solo los días, manteniendo la hora como estaba. Combinando DATEDIFF() y DATEADD() lo podemos hacer.

Si tenemos dos parámetros de tipo DATETIME, @FechaDesde y @FechaHasta. Para averiguar la diferencia en días entre los dos hacemos:


SELECT DATEDIFF(DAY, @Fecha, @FechaLimite)

-- Si esto nos da una diferencia de 40 días, supongamos,
-- podemos luego, ir recorriendo todos los registros de la tabla 
-- que necesitabamos con las distintas fechas e ir sumando 40 a la variable @Fecha

SELECT DATEADD(DAY, 40, @Fecha)


Lo bueno cuando trabajamos con la funciones es que, si no las formateamos con CAST() y CONVERT(), no perdemos la hora que tenga grabada nuestra fecha de inicio (si viene de un campo DATETIME con hora y todo). Al sumarle días, nos va a mantener la hora como estaba.

viernes, 2 de octubre de 2015

Encendiendo el PT-6020 luego de un reemplazo de batería

Para encender el colector de la línea Hasar PT-Series luego de un reemplazo de baterías o una carga full por agotamiento de la misma hay que apretar el botón de reset y el botón de power simultanamente.


martes, 15 de septiembre de 2015

Solución a problemas comunes en colectores win CE series

Las baterías principal y auxiliar se agotan.

  1. Revisar los archivos de la aplicación que se quiere ejecutar. (fbcolect por ejemplo)
  2. Enviar el acceso directo de la aplicación.-
  3. Instalar el .NET Compact Framework.-
  4. Cambiar la configuración regional a Spanish y revisar los formatos de Number, Date, etc.

Error "can't find pinvoke dll 'dbnetlib.dll'."

Si da el error al tratar de hacer una consulta SQL es porque le falta esa librería. Probar instalando uno de los dos .cab. que están en:

C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Devices\Client\wce500\armv4i\

Creo que es el 2do. pero probar con el otro (tienen las mismas librerías adentro).

Siempre copiar el archivo de instalación .cab en el directorio del dispositivo a instalar. Nunca ejecutar directamente desde acá porque al instalarse se borra el .cab. 



miércoles, 19 de noviembre de 2014

Error al abrir Clarion 8 luego de un mal cierre de sesión de windows

Ayer cuando se me quedó sin batería la UPS luego de un corte de luz, justo estaba cerrando el Clarion 8 y se me apagó la PC. Cuando volvió la energía eléctrica, mi Clarion no iniciaba. Daba una lista sábana de errores de inicilización en un .xml que no encontraba. Tras reinstalar Clarion, Framework .NET, y demás seguía dando el mismo error.

El problema, tras googlear, se debe a que, como todo .NET Framework, al iniciar y cerrar el IDE, lee y escribe unos archivos XML de configuración de pantalla y del estado del IDE al cerrar. Se ve que al justo apagarse la PC se dañaron esos archivos.

La solución? Hay que resetear las preferencias nuevamente.




























Con lo que hay que poner el usuario y contraseña de registro, y registrar los templates nuevamente.

Otra cosa que hay que hacer el borrar las soluciones y proyectos (*.sln y *.cwproj) de la carpeta de trabajo para que se puedan  crear de nuevo al abrir un .app nuevamente.

Saludos y hasta la próxima!!

viernes, 21 de marzo de 2014

SQL Server - Listar Nombres de Columnas de Tablas Temporales

De vez en cuando, tenemos que trabajar con tablas temporales, ya sea que estamos en medio de cursores, trabajando con los nuevos operadores PIVOT y UNPIVOT, etc. para insertar, recuperar o transformar datos.

Si tenemos que hacer nada más que consultas de los datos de la tabla temporal, y suponiendo que mi tabla temporal se llama "temptable", solo hay que hacer


SELECT * FROM [tempdb].[dbo].[temptable]



Ahora bien, hay veces que necesitamos listar los nombres de las columnas de nuestra tabla temporal. Si fuera una tabla de nuestra base de datos, llamada "MiTablita", eso lo podríamos saber haciendo:


SELECT COLUMN_NAME
FROM information_schema.columns
INNER JOIN information_schema.tables ON (information_schema.columns.TABLE_NAME = information_schema.tables.TABLE_NAME)
INNER JOIN sysobjects ON (information_schema.tables.TABLE_NAME = sysobjects.name)
WHERE sysobjects.xtype = 'u' AND information_schema.columns.TABLE_NAME = 'Tablita'



Pero si es una tabla temporal no la vamos a encontrar en "information_schema" sino en "tempdb.information_schema" así:


SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'temptable'