lunes, 8 de mayo de 2017

Listar desde SQL los archivos de un directorio


Para realizar esta tarea necesitamos ejecutar el procedimiento xp_cmdshell, el cual viene deshabilitado por defecto. Para habilitarlo ejectuamos el siguiente T-SQL antes de nada:

-- Primero permitimos que las opciones avanzadas puedan ser cambiadas.  
EXEC sp_configure 'show advanced options', 1;  
GO   
RECONFIGURE;  
GO  
-- Despues habilitamos el procedimiento.  
EXEC sp_configure 'xp_cmdshell', 1;  
GO   
RECONFIGURE;  
GO
-- OPCIONAL. Podemos volver a dejar las opciones avanzadas como estaban  
EXEC sp_configure 'show advanced options', 0;  
GO   
RECONFIGURE;  
GO  

El procedimiento xp_cmdshell devuelve el resultado de una shell de comandos como lineas de texto. Podemos almacenar dichas lineas en una tabla para su posterior consulta. Almacenaremos en una tabla el resultado de DIR *.xml /B. Posteriormente podremos recorrer esos datos para importar esos ficheros, por ejemplo.


DECLARE
@Path varchar(50),
@Files varchar(5),
@Cmd varchar(150)
SET @Path = 'C:\Results'
SET @Files='*.xml'

SET @Cmd =
'DIR "' +
@Path +
CASE WHEN RIGHT(@Path, 1) = '\' THEN ''
ELSE '\'
END
+ @Files
+ '"'
+ ' /B'

CREATE TABLE #tmpBuscaFiles(id int Identity, line varchar(255))
INSERT INTO #tmpBuscaFiles
EXEC master..xp_CmdShell @Cmd

select * from #tmpBuscaFiles

domingo, 7 de mayo de 2017

Importar y procesar datos en SQL Server desde un fichero XML

Fuente original: https://www.mssqltips.com/sqlservertip/2899/importing-and-processing-data-from-xml-files-into-sql-server-tables/

Importing and Processing data from XML files into SQL Server tables


There are different ways to achieve this task of importing data from an XML file into a SQL Server table, but I am going to demonstrate one of easiest ways to accomplish this task.
These are the steps I performed for importing data into SQL Server and then parsing the XML into a relational format.
  • Import XML data from an XML file into SQL Server table using the OPENROWSET function
  • Parse the XML data using the OPENXML function

Importing XML data from XML file using OPENROWSET

I have an XML file downloaded from my FTP location to a local folder and data in this XML file looks like this:
Importing XML data from XML file using OPENROWSET
Now in order to import data from the XML file to a table in SQL Server, I am using the OPENROWSET function as you can see below.
In the script below, I am first creating a table with a column of data type XML and then reading the XML data from the file using the OPENROWSET function by specifying the file location and name of the XML file as you can see below: 
CREATE DATABASE OPENXMLTesting
GO


USE OPENXMLTesting
GO


CREATE TABLE XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)


INSERT INTO XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn, 2) AS BulkColumn, GETDATE() 
FROM OPENROWSET(BULK 'D:\OpenXMLTesting.xml', SINGLE_BLOB) AS x;


SELECT * FROM XMLwithOpenXML
When I query the table in which I have imported the XML data, it looks like this. The XMLData column is an XML data type, it will output a hyperlink as shown below:
As XMLData column is of XML data type, it will give an hyperlink
Clicking on the hyperlink, in the above image, will open another tab within SSMS with the XML data displayed as shown below.
<ROOT>
<Customers>
<Customer CustomerID="C001" CustomerName="Arshad Ali">
<Orders>
<Order OrderID="10248" OrderDate="2012-07-04T00:00:00">
<OrderDetail ProductID="10" Quantity="5" />
<OrderDetail ProductID="11" Quantity="12" />
<OrderDetail ProductID="42" Quantity="10" />
</Order>
</Orders>
<Address> Address line 1, 2, 3</Address>
</Customer>
<Customer CustomerID="C002" CustomerName="Paul Henriot">
<Orders>
<Order OrderID="10245" OrderDate="2011-07-04T00:00:00">
<OrderDetail ProductID="11" Quantity="12" />
<OrderDetail ProductID="42" Quantity="10" />
</Order>
</Orders>
<Address> Address line 5, 6, 7</Address>
</Customer>
<Customer CustomerID="C003" CustomerName="Carlos Gonzlez">
<Orders>
<Order OrderID="10283" OrderDate="2012-08-16T00:00:00">
<OrderDetail ProductID="72" Quantity="3" />
</Order>
</Orders>
<Address> Address line 1, 4, 5</Address>
</Customer>
</Customers>
</ROOT>

Process XML data using OPENXML function

Now as I said before, XML data stored in a column of data type XML can be processed either by using XML functions available in SQL Server or by using the sp_xml_preparedocument stored procedure along with the OPENXML function.
We will first call the sp_xml_preparedocument stored procedure by specifying the XML data which will then output the handle of the XML data that it has prepared and stored in internal cache.
Then we will use the handle returned by the sp_xml_preparedocument stored procedure in the OPENXML function to open the XML data and read it.
Note: the sp_xml_preparedocument stored procedure stores the XML data in SQL Server's internal cache, it is essential to release this stored XML data from internal cache by calling the sp_xml_removedocument stored procedure. We should call the sp_xml_removedocument stored procedure as early possible, so that internal cache can be freed for other usage.
USE OPENXMLTesting
GO


DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)


SELECT @XML = XMLData FROM XMLwithOpenXML


EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML


SELECT CustomerID, CustomerName, Address
FROM OPENXML(@hDoc, 'ROOT/Customers/Customer')
WITH 
(
CustomerID [varchar](50) '@CustomerID',
CustomerName [varchar](100) '@CustomerName',
Address [varchar](100) 'Address'
)


EXEC sp_xml_removedocument @hDoc
GO
From the above XML data, I want to retrieve all the customer information and hence I am navigating to the Customer element and querying CustomerID and CustomerName (please note the use of "@" before the name of the attribute) attributes and Address element in the above SELECT statement using the OPENXML function.
The structure of the resultset can be determined with the "WITH" clause as shown above.
Process XML data using OPENXML function
From the above XML data, I now want to retrieve all the customer information along with OrderID and OrderDate placed by each individual customer and hence I am navigating to the Order element and then querying OrderID and OrderDate attributes.
If we want to navigate back to the parent or grand parent level and get data from there, we need to use "../" to read the parent's data and "../../" to read the grand parent's data and so on.
USE OPENXMLTesting
GO


DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)


SELECT @XML = XMLData FROM XMLwithOpenXML


EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML


SELECT CustomerID, CustomerName, Address, OrderID, OrderDate
FROM OPENXML(@hDoc, 'ROOT/Customers/Customer/Orders/Order')
WITH 
(
CustomerID [varchar](50) '../../@CustomerID',
CustomerName [varchar](100) '../../@CustomerName',
Address [varchar](100) '../../Address',
OrderID [varchar](1000) '@OrderID',
OrderDate datetime '@OrderDate'
)


EXEC sp_xml_removedocument @hDoc
GO
The result of the above query can be seen in the image below. You can see below all the customers and all the orders placed by each customer.
querying CustomerID and CustomerName
Now let's go one level deeper. This time from the above XML data, I want to retrieve all the customer information and their orders along with ProductID and Quantity from each order placed. And hence, as you can see below I am navigating to the OrderDetail and retrieving the ProductID and Quantity attributes' values. At the same time I am using "../" to reach the parent level to get Order information available at the parent level whereas I am using "../../../" to reach to the great grand parent level to grab Customer information as shown below:
USE OPENXMLTesting
GO


DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)


SELECT @XML = XMLData FROM XMLwithOpenXML


EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML


SELECT CustomerID, CustomerName, Address, OrderID, OrderDate, ProductID, Quantity
FROM OPENXML(@hDoc, 'ROOT/Customers/Customer/Orders/Order/OrderDetail')
WITH 
(
CustomerID [varchar](50) '../../../@CustomerID',
CustomerName [varchar](100) '../../../@CustomerName',
Address [varchar](100) '../../../Address',
OrderID [varchar](1000) '../@OrderID',
OrderDate datetime '../@OrderDate',
ProductID [varchar](50) '@ProductID',
Quantity int '@Quantity'
)


EXEC sp_xml_removedocument @hDoc
GO
The result of the above query can be seen in the image below. You can see all the customer information and their orders along with ProductID and Quantity from each order placed.
The result of the above query

domingo, 11 de septiembre de 2016

Gestor de arranque rEFIt para Mac

Cuando usamos Bootcamp para crear una segunda particion con Windows en nuestro mac, la manera de seleccionar dicha particion para arrancar es mantener pulsada la tecla ALT (Opción) durante el inicio.

Si queremos un un gestor de arranque al uso, como Grub, Lilo o el propio de Windows, la solución en Mac se llama rEFIt.

Además, con rEFIt podremos disponer de mas de dos particiones en el equipo (OS X, Linux y Windows, por ejemplo), ya que Bootcamp solo nos permitirá la instalacion de una partición con Windows.



Para instalar rEFIt simplemente hay que descargarlo de su pagina oficial y ejecutar el instalador:

Descargar rEFIt

Una vez descargado e instalado debemos proceder a activarlo. Para ello abrimos un terminal e introducimos lo siguiente:

cd /efi/refit
sudo ./enable-always.sh

Podemos configurar las opciones basicas, como el SO por defecto o el tiempo que tardará en cargar automaticamente el SO por defecto. Para ello hay que editar el archivo refit.conf que se encuentra en la carpeta /efi/refit.

Si queremos personalizar los iconos de los sistemas operativos instalados podemos hacerlo sustituyendo los originales que se encuentran en la carpeta /efi/refit/icons por otros de nuestro gusto. Solo hay que procurar que mantengan el mismo nombre.

domingo, 4 de septiembre de 2016

Instalar Windows desde USB en BootCamp El Capitan con equipos antiguos

La nueva version de BootCamp 6 que viene con El Capitan permite instalar Windows desde un CD, desde una memoria USB o directamente mediante una iso. Para esta ultima opcion, BootCamp creará una partición temporal para los archivos de instalación que borrará al terminar el proceso.

Sin embargo, en equipos anteriores a 2013 solo permitirá instalar Windows desde el DVD de instalación. Si, como yo, habéis eliminado la unidad optica de vuestro imac para instalar un SSD, o simplemente teneis un MacBook sin DVD, las opciones, a priori, pasan por usar un lector externo.




El siguiente metodo permitirá instalar Windows con BootCamp mediante USB en equipos antiguos con El Capitan. El metodo consiste en editar la configuración de BootCamp para que reconozca nuestro modelo como compatible. Los pasos serian los siguientes:

1 - Desactivar System Integrity Protection. Esta nueva característica de seguridad incorporada en El Capitan impedirá que se puedan modificar los archivos de BootCamp. Para desactivarla hay que entrar en el modo de recuperación (pulsar Command + R al arrancar) y abrir un terminal (Utilidades -> Terminal). Introducimos lo siguiente:

csrutil disable
reboot


2 - Editar archivo Info.plist. En el finder vamos al Asistente de BootCamp y abrimos el paquete (boton dcho -> Mostrar contenido del paquete). Editamos el archivo Info.plist modificando lo siguiente:

  • Añadir vuestra versión de la ROM de arranque (se saca de Acerca de este Mac -> Informe del sistema -> Información del hardware -> Versión de la ROM de arranque) debajo de la sección “DARequiredROMVersions“.
  • Añadir el “Identificador del modelo” (se saca de Acerca de este Mac -> Informe del sistema -> Información del hardware -> Identificador del modelo) debajo de la sección “PreUSBBootSupportedModels”.
  • Eliminar el prefijo “Pre” de “PreUSBBootSupportedModels” (la misma del punto anterior), la sección quedará como “USBBootSupportedModels”.

3 - Firmar BootCamp con el nuevo archivo info.plist. Desde un terminal introducimos el siguiente comando:

sudo codesign -fs – /Applications/Utilities/Boot\ Camp\ Assistant.app

Con esto, BootCamp debería tratar vuestro mac como cualquier modelo actual y permitiros instalar Windows desde un pendrive, desbloqueandose la opcion de crear medios.


Para completar la instalación de Windows simplemente creamos un pendrive booteable a partir de la iso de windows. En la segunda pantalla Bootcamp nos dará la opción para ello. Tambien podemos marcar la opcion de descargar el software de compatibilidad, es decir, los drivers de nuestro Mac para Windows.

Por ultimo, podemos marcar la opción de instalar Windows ahora, lo cual hará que el sistema se reinicie una vez termine los pasos anteriores y arranque automáticamente con el pendrive recién creado. Si queremos instalar windows mas adelante debemos dejar esta opcion sin marcar. Para arrancar más adelante desde el pendrive debemos pulsar la tecla ALT (opción) durante el inicio y seleccionar el usb como medio de arranque.




Fuentes:



Actualizado 12/09/2016:

Al particionar el disco con Bootcamp, es posible encontrarse con que la instalacion de Windows no permite hacerse sobre una particion MBR, ya que en sistemas EFI se requiere particion de tipo GPT:



Este error se debe a que, a pesar de que la tabla de particiones de El Capitan es GPT, Bootcamp crea un "MBR Hibrido", de manera que la particion de Bootcamp es vista por Windows como una particion MBR. Para solucionarlo es necesario eliminar esos datos hibridos de la tabla de particiones. Para ello podemos usar Gdisk, que se puede descargar de este enlace.

Nota: La característica "System Integration Protection" debe permanecer desactivada para poder utilizar Gdisk.

1º - Ejecutamos Gdisk desde un terminal seleccionando el disco de destino:

sudo gdisk /dev/disk0

Inmediatamente vemos la información sobre la tabla de particiones del disco seleccionado:


2º - Con "P" vemos la información sobre las particiones. Nos valdrá para asegurarnos que estamos trabajando sobre el disco correcto.

3º - Entramos en modo experto pulsando "X".

4º - Pulsamos "N" para que pase el MBR a modo "protective".

5º - Salvamos los cambios pulsando "W".

Reinciamos el equipo y arrancamos desde el pendrive con la instalación de Windows. Ya debería dejarnos instalar windows en la partición de Bootcamp sin problemas.

viernes, 15 de enero de 2016

Registrar un ping con fecha y hora

Si queremos comprobar microcortes de una red lo habitual es hacer un ping -t y enviar el resultado a un fichero de texto:

ping 192.168.0.1 -t > log.txt


Pero si además queremos que se registre la fecha y la hora de cada comprobación para saber en que momento se produce el microcorte, el siguiente script nos ayudará:


@echo off

::A la variable ip le asignamos la direccion que queremos comprobar
set ip=192.168.98.91

:bucle

::Se establecen las variables p1 y p2 con un valor inicial
set p1=.
set p2=.

::Hacemos ping al destino localizando exclusivamente la linea 
::con la respuesta
ping -n 1 %ip% -l 1000 | find "Respuesta" > p1.txt
ping -n 1 %ip% -l 1000 | find "Tiempo de espera agotado" > p2.txt
set /p p1=< p1.txt
set /p p2=< p2.txt

::Se muestra la info en pantalla y se guarda tambien en 
::un fichero log.txt
echo %date% %time% %p1% %p2%
echo %date% %time% %p1% %p2% >> log.txt

::Se borra el contenido de los archivos temporales
break >p1.txt
break >p2.txt

::con otro ping establecemos el tiempo de espera entra cada 
::comprobacion en milisegundos con -w
ping 127.0.0.1 -w 1000 -n 2 > NUL

::Volvemos al inicio del bucle

GOTO :bucle


El resultado es el siguiente:


Y la misma información se guardará en el fichero log.txt.

A tener en cuenta que si la máquina en cuestión tiene el SO en inglés, al hacer el ping deberemos localizar "Reply" y "Timed out" en lugar de "Respuesta" y "Tiempo de espera agotado".

Otra cuestión a tener en cuenta es que si el tiempo de respuesta es menor de 1 milisegundo (tiempo<1ms) el script no registrará ningún dato para esa comprobación. Una manera sencilla de solucionarlo es aumentar el tamaño del bucle del ping, que por defecto es 32 bytes. Poniendo valores altos el ping tardará algo más en responder (maximo 65500 bytes). Mientras el tiempo de respuesta sea de 1ms o mayor, la comprobación se registrará sin problemas.

El modificador para el tamaño del bufer es "-l" seguido del tamaño en bytes que queramos asignarle. Lo debeis modificar en las lineas 14 y 15 del script.



ACTUALIZACIÓN 30/06/2022

El siguiente comando consigue lo mismo pero usando Powershell:

ping.exe -t 192.168.98.91 -l 1000 | ForEach {"{0} - {1}" -f (Get-Date),$_} > log.txt


sábado, 4 de enero de 2014

Bluestack, o como emular android

BlueStacks App Player es una interesante aplicación que permite emular un sistema android en nuestro PC/Mac, permitiendonos instalar en el pc apps para android tales como Whatsapp, Line o vuestro juego favorito.

BlueStacks App Player está disponible gratuitamente en la web de su autor: www.bluestacks.com, y dispone de versión para Windows XP/Vista/7/8 y Mac OS X.

Para instalar aplicaciones podréis simplemente utilizar la App Store o descargar archivos .apk instalables. La instalación de estos paquetes en un entorno Windows es sencillo: doble clic sobre el fichero y se instalará automáticamente en nuestro android virtual.

En cambio, para instalar paquetes .apk en un entorno Mac tendremos que tirar de la terminal e introducir los siguientes comandos:

$ cd /Applications/BlueStacks.app/Contents/Runtime

Dentro de este directorio existe un comando llamado uHD-Adb que deberemos ejecutar con la siguiente sintaxis:

$ ./uHD-Adb install /mis_apks/aplicacion.apk

Debereis sustituir la ruta de destino por la ubicación donde se encuentre el fichero .apk que queráis instalar. Por ejemplo, si teneis un archivo app.apk descargado en el escritorio, la sintaxis correcta sería:

$ ./uHD-Adb install /$HOME/Desktop/app.apk

Doberk´s blog is coming!!! :)

Bienvenidos a mi blog. La intención de este blog es aprovechar un pequeño espacio en Internet para ir recopilando información útil de ámbito informático, en temas tanto a nivel de usuario como de administrador IT. Aunque por el momento me iré centrando más bien en lo primero :)

Soy consciente de que todo lo que encontréis aquí se puede encontrar fácilmente en otros sitios haciendo una sencilla búsqueda en Google. Pero el motivo de este blog no es aportar nada nuevo al mundo informático, pobre de mi. No no, nada de eso, esto es mucho mas simple: uno va para viejo, y acordarse de las cosas es cada vez mas difícil. Así que si las voy reuniendo todas en un sólo lugar me será más fácil volver a encontrarlas el día de mañana cuando las vuelva a necesitar. Y de paso quizá le resulte útil a alguien más.

Dicho esto, si te aburro con cosas que consideras desvaríos de lamer, lo siento, de verdad. Cierra el navegador y olvida que existo. Si por el contrario te he resuelto alguna dudilla que te estaba costando encontrar, de nada :)

Asi que vamos allá...