xType en syscolumns

A diferencia de 'xType" en sysobjects, no es tan facil de encontrar que significan esos valores en la tabla syscolumns, teniendo en cuenta que en los Books online mencionan al xtype como "for internal purpose" (para uso interno).

La tabla que tiene esta info es sysTypes y podemos escribir un query tipo:

SELECT xtype, name [tipo] FROM systypes ORDER BY xType

y esto devuelve

XType tipo
----------------
34 image
35 text
36 uniqueidentifier
48 tinyint
52 smallint
56 int
58 smalldatetime
59 real
60 money
61 datetime
62 float
98 sql_variant
99 ntext
104 bit
106 decimal
108 numeric
122 smallmoney
127 bigint
165 varbinary
167 varchar
173 binary
175 char
189 timestamp
231 nvarchar
231 sysname
239 nchar
241 xml


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Abraham Silberschatz - Fundamentos de Bases de Datos

UNED Fundamentos de bases de datos



Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

SQL Injection Attacks

Un pequeño instructivo con algunas técnicas básicas de injection sql, interesante para empezar a entender estas técnicas de ataque a servidores de bases de datos:
El libro se encuentra en:

http://www.securitydocs.com/pdf/3348.PDF

Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Portqry - Monitor de estados de puertos TCP/IP

Portqry.exe es un utilitario que informa sobre el estado de un puerto TCP/IP.

Este utilitario se puede descargar desde:

Para línea de comandos:
http://www.microsoft.com/downloads
/details.aspx?FamilyID=89811747-C74B-4638-A2D5-AC828BDC6983&displaylang=en













Interfaz Gráfica:
http://download.microsoft.com/download/3/f/4/3f4c6a54-65f0-4164-bdec-a3411ba24d3a/portqryui.exe


















Este utilitario informa el estado de puertos de tres formas distintas:

  • Listening
    Hay un proceso a la escucha en el puerto del equipo seleccionado. Portqry.exe recibió una respuesta desde el puerto.

  • Not Listening
    No hay ningún proceso a la escucha en el puerto de destino del sistema de destino. Portqry.exe recibió el mensaje "Destino inalcanzable: Puerto inaccesible" de Protocolo de mensajes de control de Internet (ICMP) para el puerto UDP de destino. O bien, si el puerto de destino es un puerto TCP, Portqry recibió un paquete de confirmación TCP con el indicador Reset.

  • Filtered
    El puerto del equipo que seleccionó tiene activado un filtro. Portqry.exe no recibió una respuesta desde el puerto. Es posible que haya un proceso a la escucha en el puerto. De manera predeterminada, los puertos TCP se consultan tres veces y los puertos UDP una antes de que el informe indique que el puerto tiene activado un filtro.
Portqry.exe puede consultar un solo puerto, una lista ordenada de puertos o un intervalo secuencial de puertos.

Ejemplos
El comando siguiente intenta resolver "reskit.com" como una dirección IP y, a continuación, consulta el puerto TCP 25 en el host correspondiente:

portqry -n www.mundoeva.com -p tcp -e 25
El comando siguiente intenta resolver "169.254.0.11" como un nombre de host y después consulta los puertos TCP 143, 110 y 25 (en ese orden) en el host que seleccionó. Este comando también crea un archivo de registro (Portqry.log) que contiene un registro del comando que ejecutó y su resultado.

portqry -n 169.254.0.11 -p tcp -o 143,110,25 -l portqry.log

El comando siguiente intenta resolver miServidor como una dirección IP y después consulta el intervalo especificado de puertos UDP (135-139) en orden secuencial en el host correspondiente. Este comando también crea un archivo de registro (miServidor.txt) que contiene un registro del comando que ejecutó y su resultado.


portqry -n miServidor -p udp -r 135:139 -l miServidor.txt

Este utilitario es una herramienta de utilidad y que debemos tener siempre en cuenta al momento de monitorear estados de puertos remotos.


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

FAIL_VIRTUAL_RESERVE - Insuficiente memoria para ejecutar el query.

Este es un problema relativo al Virtual Address Space (VAS).

Este mensaje FAIL_VIRTUAL_RESERVE 589824 significa (al menos lo que yo se) que estamos fallando en asignar espacio contiguo de alocacion de 589824 bytes aprox.

Generalmente la solución es agregar el switch o parametro de startup -g 512 y reiniciar el servicio, tal como indica microsoft: http://msdn.microsoft.com/en-us/library/ms190737.aspx

If este seteo no funcionara existen algunos otros puntos a mirar:

1. Estrategia de indices para mejorar la performance de los queries y disminuir los bloqueos.
2. Minimum y Max memory size. Dejarle algo de memoria libre para el sistema operativo, al menos medio gb.
3. Aplicar los ultimos service pack y patchs, para lo cual pueden comparar su versión y patchs aplicados con respecto a la ultima en http://www.sqlteam.com/article/sql-server-versions
4. Permisos de Lock Pages in Memory Permissions para el user que ejecuta el servicio sql server
http://www.tipandtrick.net/2008/enable-lock-pages-in-memory-to-prevent-database-paging-to-disk/
5. Chequear si las estadisticas están des-actualizadas.

Una muy buena explicacion de estos temas: http://blogs.msdn.com/b/sqlserverfaq/archive/2010/02/16/how-to-find-who-is-using-eating-up-the-virtual-address-space-on-your-sql-server.aspx

Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

The Power of Cross Join

http://weblogs.sqlteam.com/jeffs/archive/2005/09/12/7755.aspx

Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Cual es la diferencia entre CROSS APPLY y CROSS JOIN

Traducido de:
http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/sql-server-cross-apply.aspx
Pienso que la manera mas fácil de pensar la sentencia CROSS APPLY es que es semejante a hacer un CROSS JOIN con un sub-select correlativo en vez de una tabla derivada.

Digamos, una tabla derivada es "auto-contenida" de modo que las tablas y columnas que referencia no son accesibles por el select principal, aunque variables y parámetros pueden ser referenciados.
Por ejemplo, veamos:

select A.*, b.X
from A
cross join (select B.X from B where B.Val=A.Val) b

Esta sentencia no es válida, porque A.Val está fuera del alcance al estar dentro de la tabla derivada. Esto es porque la tabla derivada es evaluada de manera independiente de las otras tablas en el Select.
Para limitar los registros en Tabla B de manera de cumplir la condición B.Val = A.Val, nosotros tenemos que hacerlo "fuera" de la tabla derivada por medio de un join o en el criterio.

select A.*, b.X
from A
cross join (select * from B) b
where A.Val = b.Val

(por supuesto, lo de arriba es equivalente a hacer un inner join en la tabla derivada o simplemente uniendo a la tabla B).

También, tengamos en cuenta que el alcance de las tablas derivadas no rige solamente para los CROSS JOINS sino que también se aplica a todos los otros JOINS (CROSS, INNER, OUTER) e incluso para UNION. Todas estas sentencias usan tablas derivadas "auto-contenidas".

Esto es diferente a un sub-select correlativo en donde el SELECT principal está en el alcance para el sub-query. El sub-select es evaluado por cada registro en el query, de manera que otras tablas y columnas en el SELECT están disponibles.

select A.*, (select B.X from B where B.Val=A.Val) as X
from A

(obviamente el subquery tiene que regresar solo un registro).

Esta es una manera facil de pensar las diferencia entre CROSS JOIN y CROSS APPLY. CROSS JOIN, tal como vimos, une a una tabla derivada, sin embargo, CROSS APPLY, a pesar de lucir como un JOIN en realidad es aplicado al subselect correlativo. Esto impone las ventajas de subselects correlativos y además tiene implicaciones a nivel de performance.

Ahora si, podemos reescribir nuestro primer ejemplo usando CROSS APPLY y quedaría de la siguiente forma:

select A.*, b.X
from A
cross apply (select B.X from B where B.Val=A.Val) b

Como ahora aplicamos un APPLY y no un JOIN, A.Val está en alcance y esto funciona ok.

Table Valued User Defined Functions

Las mismas reglas aplican cuando usamos Table-Valued User-Defined Functions:

select A.*, B.X
from A
cross join dbo.UDF(A.Val) B

Esto es no válido nuevamente. A.Val no está en alcance para ser usado por la UDF.

Lo mejor que podíamos hacer antes de SQL 2005 era usar un subselect correlativo:

select A.*, (select X from dbo.UDF(A.Val)) X
from A

Sin embargo esto no es funcionalmente equivalente. La UDF no regresa mas de un registro o eso sería un error.

Con SQL 2005 podemos también en este caso usar CROSS APPLY y todo funcionará perfectamente:

select A.*, b.X
from A
cross apply dbo.UDF(A.Val) b

Esta es una manera de pensar las diferencias entre JOIN y APPLY, JOIN combina dos resultsets separados, pero APPLY es mas que un loop que evalua un resultset una y otra vez por cada registro.
Esto significa que en general APPLY será menos eficiente que un JOIN, del mismo modo que sub-selects correlativos son menos eficientes que tablas derivadas.

Entonces, cual es la ventaja de usar CROSS APPLY en vez de un sub-select correlacionado?
Bueno, muchas ventajas, por empezar...es mucho mas poderoso !.


CROSS APPLY puede regresar múltiples registros.

Esto nos permite hacer cosas como "joinear" una tabla a una función que parsear una columna csv en esa misma tabla en multiples registros.

select A.ID, b.Val
from A
cross apply dbo.ParseCSV(A.CSV) b

Cuando la funcion ParseCSV regresa multiples registros, simplemente actua como si hubiesemos joineado una tabla, duplicando los registros en tabla A por cada registro en la tabla de join.
Esto no se puede hacer con un sub-select correlativo, porque tira error.


CROSS APPLY puede retornar múltiples columnas.

De nuevo, en un sub-select correlativo podemos devolver un solo valor.
Si escribimos un script que regrese una sumatoria, podemos usar un subselect como el siguiente:

select o.*,
(select sum(Amount) from Order o
where p.OrderDate <= o.OrderDate) as RunningSum
from Order o

Sin embargo, que pasa si queremos regresar sumas adicionales de pedidos basados en algún otro criterio (pedidos con el mismo "ordercode")?.
Necesitaríamos otro subselect correlacionado, reduciendo la eficacia de nuestro select.

select o.*,
(select sum(Amount) from Order o
where p.OrderDate <= o.OrderDate) as RunningSum,
(select sum(Amount) from Order o
where p.OrderCode = o.OrderCode and p.OrderDate <= o.OrderDate) as SameCode
from Order o

Pero con un CROSS-APPLY seria mucho mas sencillo.

select o.*, rs.RunningSum, rs.SameCode
from Order o
cross apply
(
select
sum(Amount) as RunningSum,
sum(case when p.OrderCode = o.OrderCode then Amount else 0 end) as SameCode
from Order P
where P.OrderDate <= O.OrderDate
) rs


Entonces, tenemos el beneficio de regresar multiples columnas como si fuese una tabla derivada, y también tenemos la habilidad de referenciar valores en nuestro select.
Bastante poderoso.

Con CROSS APPLY podemos facilmente recuperar columnas del registro anterior en una tabla.

select o.*, prev.*
from Order o
cross apply
(
select top 1 *
from Order P where P.OrderDate < O.OrderDate
order by OrderDate DESC
) prev

Note que el script anterior no regresará pedidos que no tengan un pedido anterior, debemos usar OUTER APPLY para asegurarnos que todos los pedidos serán regresados, incluso si no existen pedidos previos.

select o.*, prev.*
from Order o
outer apply
(
select top 1 *
from Order P where P.OrderDate < O.OrderDate
order by OrderDate DESC
) prev


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Como encontrar un texto dentro de todos los stored procedures en SQL Server 2005

SELECT ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%foobar%'
AND ROUTINE_TYPE='PROCEDURE'

Nos valemos de la función ROUTINE_DEFINITION que nos devuelve la definición o codificación de cualquier objeto dentro una base de datos.


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...