Mostrando las entradas con la etiqueta SQL. Mostrar todas las entradas
Mostrando las entradas con la etiqueta SQL. Mostrar todas las entradas

Agrupando Registros con SQL Server 2008

Estaré habciendo mención en las próxima publicaciones de algunas de las nuevas funciones que nos trae SQL Server 2008, me he sentido motivado a escribir sobre los nuevos features de SQL Server 2008, debido al gran numero de preguntas que he recibido a mi correo personal, por lo cual estare listando las mas importantes.

Una característica nueva que tiene la nueva versión de SQL Server, es el nuevo operador GROUPING SETS, que ya existía en otros motores de base de datos tales como Oracle, el cual permite combinar consultas de agrupación distintas en una sola consulta.

Es bueno aclarar que el operador GROUPING SETS es una extensión de la cláusula estándar GROUP BY. Cuando no se requieren todas las agrupaciones posibles que se generan utilizando un operador ROLLUP o CUBE (que ya existían en SQL Server 2005), se debe utilizar GROUPING SETS para especificar sólo las agrupaciones que se deseen. O sea, gracias a GROUPING SETS obtenemos los niveles de agrupación deseados y además nos devuelve el subtotal para cada subconjunto de agrupación.


En pocas palabras podríamos decir que GROUPING SET es mas abarcativo y genérico que ROLLUP o CUBE. Generalmente consultas que usen este tipo de operadores están relacionadas con el análisis de datos, reporting y todo lo relacionado con el mundo la Intelegencias de Negocios.

Les recuero este nuevo operador no viene hacer magia y a solucionar un problema que no se podia solucionar, sino mas bien nos simplifica y optimiza nuestras consultas, por eso es lo importante del mismo, pero quiero aclarar que sin utilizar este operador podiamos generar o encontrar los mismos resultados en SQL Server, pero no con el performance que este nos brinda.


Probemos en una consulta, como siempre utilizare la base de datos de prueba de SQL Server AdventureWorks para realizar este ejemplo:


Lo primero que nos viene a la cabeza para resolver la parte de la agrupación casi siempre es hacer una consulta usando UNION ALL con tres consultas diferentes, una por cada agrupación, seria algo como esto:


Pero podríamos solucionarlo utilizando el operador GROUPING SET, seria algo como esto:



Ahora como podrán ver en este último ejemplo, además de usar el operador GROUPING SETS, hago uso de la función GROUPING en el ORDER BY, esto es para ordenar el resultado por Name y CountryRegionCode.

Esta función (que ya existía en SQL Server 2005), nos indica si una expresión de columna especificada en una lista GROUP BY es agregada o no. GROUPING devuelve 1 para agregado y 0 para no agregado, en el conjunto de resultados.

La ventaja del uso GROUPING SETS no está solo dada por simplificar sintácticamente las consultas, sino también en cuestiones de performance.

Hice unas pruebas para monitorear el uso de recursos (SET STATISTICS IO ON) con 90,000 registros en mi tabla y estos fueron los resultados:


Usando UNION ALL:Table ‘Sales.SalesTerritory’. Scan count 3, logical reads 1728, physical reads 6, read-ahead reads 590, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.


Usando GROUPING SETS:Table ‘Sales.SalesTerritory’. Scan count 1, logical reads 576, physical reads 6, read-ahead reads 590, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Como se puede ver, GROUPING SETS hace menor uso de recursos de I/O. Esto se debe a que usando la nueva característica de SQL Server, el motor necesita leer menos paginas de datos, ya que hace el cálculo de agregación de más alto nivel sobre las agregaciones de menor nivel.

Restaurando una Base de Datos SQL desde un Snapshot

En lo particular comenzare este articulo definiendo segun Books Online lo que es un Snapshot, que en lo particular lo considero como uno de los mas interesantes conceptos utilizados en la actualidad.

Snapshop: es una vista estática de sólo lectura de una base de datos denominada base de datos de origen. Pueden existir varias instantáneas en una base de datos de origen y residir siempre en la misma instancia de servidor que la base de datos. Una instantánea de base de datos es coherente en cuanto a las transacciones con la base de datos de origen tal como existía en el momento de la creación de la instantánea. Una instantánea se mantiene hasta que el propietario de la base de datos la quita explícitamente.

En resumen es una fuente de datos estatica de solo lectura, en la cual podemos consultar informacion de la misma e incluso hacer transacciones en la misma.

En esta ocacion procedere a crear una nueva base de datos la cual llamare OmarFrometa_DB, en el cual voy a crear una nueva tabla y le voy a insertar al menos 5 nuevos valores:



Luego procedere a Crear mi Snapshot en mi base de datos OmarFrometa_DB.


Despues de esto voy a realizarle un Select tanto a mi tabla como a al Snapshot creado, para que asi logren notar su comportamiento.

En otro capitulo seguire ampiando todo lo que podemos hacer con estas fotografias de la base de datos (Snapshot) y asi podremos explotar al maximo este concepto que existe desde la version 2005 de SQL pero que muy pocas personas aun lo estan utilizando.

Aqui les dejo todo el Codigo que Utilice.


USE master
GO

CREATE DATABASE OmarFrometa_DB
GO
USE OmarFrometa_DB
GO

CREATE TABLE Numeros (ID INT, Value VARCHAR(10))
INSERT INTO Numeros VALUES(1, 'Uno');
INSERT INTO Numeros VALUES(2, 'Dos');
INSERT INTO Numeros VALUES(3, 'Tres');
INSERT INTO Numeros VALUES(4, 'Cuatro');
INSERT INTO Numeros VALUES(5, 'Cinco');
GO

CREATE DATABASE SnapshotDB ON
(Name ='OmarFrometa_DB',
FileName='c:\SSOmarFrometa_DB.ss1')
AS SNAPSHOT OF OmarFrometa_DB;
GO

SELECT * FROM OmarFrometa_DB.dbo.Numeros;
SELECT * FROM OmarFrometa_DB.dbo.Numeros;
GO

Llamar un WebServices desde un Store Procedure

En una ocasión un viejo amigo, estaba programando unas aplicaciones con .Net y Sockets, y necesitaba poder invocar un WebServices desde un procedimiento almacenado.


En este articulo compartire esa experiencia, para que otros programadores puedan aprender a invocar un WebServices enviándole parámetros desde un Store Procedure.

1. Creamos Nuestro Proyecto WebServices en Visual Studio.

2. Luego procedemos a crear los métodos que vamos a utilizar en nuestro servicio, en mi caso cree 6 métodos que son: Saludar(string Param1) y este espera un String como parámetro, HelloWord() este no espera ningún parámetro, y los métodos Add, Substract, Proliferation y Divide (int Num1, int Num2) esperan 2 números enteros como parámetros.

3. Procedemos a crear nuestro procedimiento almacenado que tendrá todo el código para invocar el WebServices que acabamos de crear, como en todos mis artículos la base de datos que utilizo es AdventureWorks, que es la base de datos de prueba que trae SQL Server.



4. Luego Publicamos el Servicio Web en nuestro IIS


5. Procedemos a Codificar nuestro Store Procedure con los Datos de Nuestro Servicio Web.


6. En el procedimiento que Creamos, le pasamos un parámetro que es el Parámetro que esta esperando el Método Saludar(), si desean utilizar los otros métodos, deberán crear otro parámetro pues como les mencione anteriormente los otros métodos están esperando 2 parámetros tipo enteros.

Algo también que es muy importante cuando utilizando los procedimientos Almacenados SP_OAMethod este espera el método POST o GET, por defecto casi siempre le enviamos POST, pero si le enviamos este método, no podremos visualizar la lectura del XML que genera nuestro Servicio Web, por lo cual debemos utilizar el Método GET.



7. Procederemos a Probar Nuestro Servicio Web, a través de nuestro navegador, escribimos la dirección del IIS donde esta publicado nuestro Servicio Web. http://localhost/WebServices/Service1.asmx , en el mismo aparecerán todos los métodos que tengamos creados en nuestro Servicio Web.
8. Seleccionamos el Método que vamos a Utilizar e Invocar desde nuestro Procedimiento Almacenado, Saludar(). Luego procedemos a escribir el parámetro que deseamos pasarle al Servicio Web, luego de esto cliqueamos en Invoke.


9. Luego de esto se nos abrirá otra pagina de nuestro navegador, con la información contenida en XML y el parámetro que escribimos.

10. Procedemos a Ejecutar el Procedimiento Almacenado que acabamos de crear para invocar nuestro Servicio Web.


11. Luego de ejecutar nuestro procedimiento y enviarle nuestro parámetro obtendremos el mismo resultado que obtuvimos cuando lo ejecutamos a través de nuestro navegador.

Miren la comparación y notarón que es el mismo resultado.

Comparar Resultados en SQL Server

Se que a todos nos ha pasado un caso similar a este que voy a plantear, tenemos un banco de datos lleno de correos electronicos y por una razon el nombre del dominio cambia pero no los correos, por lo cual debemos actualizar nuestra base de datos y ponerle a los correos el nombre del nuevo dominio, un ejemplo de esto fue cuando en republica dominicana Codetel (Compañia Dominicana de Telefonos) vendio su sus acciones a Verizon International, los correos pasaron de ser @codetel.net.do a verizon.net.do, esto para mucho fue un dolor de cabeza, pero aqui les dejare el codigo que ustedes pueden utilizar para no solo resolver ese caso, sino casos similares a este.

En este ejemplo buscare utilizare varias funciones de SQL como lo son SUBSTRING & CHARINDEX, aqui definire las mismas:

SUBSTRING: es una función de subcadena en SQL se utiliza para tomar una parte de los datos almacenados.
CHARINDEX: Devuelve la posición inicial de la expresión especificada en una cadena de caracteres.


Este ejemplo lo ejecutare como siempre en la base de datos de Muestra que trae SQL Server Adventure-Works


Tal y Como vemos en la Imagen con la sintaxis SQL que corrimos seleccionamos todos los correos de la tabla Person.Contact, que pertenecieran al dominio @adventure-works.com, y lo creamos una columna para ver como quedarian si lo reemplazaramos por el dominio @omarfrometa.com.

Luego de verificado que es asi que queremos que queden los datos procedemos a reemplazarlos en nuestro banco de datos, utilizando la sentencia UPDATE, tal y como se muestra en la siguiente imagen.


Aqui les dejo todo el Codigo Que Utilice en este Ejemplo:

UPDATE
      Person.Contact
SET
      EmailAddress = SUBSTRING(EmailAddress, 1, CHARINDEX('@',EmailAddress)) + 'adventure-works.com' 
WHERE
      EmailAddress Like '%omarfrometa.com%'

Tablas Virtuales o En Memoria

Algunas Veces necesitamos disponer de ciertas tablas temporales en nuestros sistemas, particularmente yo trato de no utilizarlas, lo que mayormente utilizo con las Tablas Virtuales o En Memoria que puedo crear en SQL Server.

En este articulo creare una tabla virtual llamada EMPLEADOS la cual tendra 3 campos principales IDEMPLEADO, NOMBRECOMPLETO, IDSUPERVISOR, en estos campos almacenare datos que extraere de un select para luego insertarlos en la tabla virtual de empleados y posteriormente consultarlos.

Aqui les dejo una Muestra de esto...



Estas Tablas no hay que eliminarlas de memoria luego de utilizarlas, ya que se eliminan automaticamente, luego de ser utilizada!....

Aqui el Codigo Utilizado de Ejemplo:


DECLARE @Empleados TABLE (IDEmpleado INT PRIMARY KEY, NombreCompleto VARCHAR(100), IDSupervisor INT)


INSERT INTO @Empleados
SELECT 1, 'Omar', 3
UNION ALL
SELECT 2, 'Mayreni', 3
UNION ALL
SELECT 3, 'Franklin', 3
UNION ALL
SELECT 4, 'Mendez', Null
UNION ALL
SELECT 5, 'Minaya',2
UNION ALL
SELECT 7, 'Ronny',2


SELECT * FROM @Empleados

Listar el Numero de Registros Que Contiene una Tabla en SQL

Creo que a todos los programadores alguna vez han necesitado en algun programa listar el numero de registros que contiene una tabla en especifico, a mi me toco hacer algo similar, y fue desarrollar una rutina que me contara el numero de filas o registros que tenia en cada tabla, para esto, utilice las vistas predeterminadas de SQL Server que nos brindan toda esta informacion rapidamente.

Aqui les dejo las Imagenes de como funcionaria el Query...




Aqui el Codigo que Utilice en mi Consulta:

SELECT 
sc.name + '.' + tbl.name AS 'NOMBRE DE LA TABLA',
SUM(par.rows) AS 'NUMERO DE REGISTROS'
FROM 
sys.tables tbl
INNER JOIN 
sys.partitions par
ON 
par.OBJECT_ID = tbl.OBJECT_ID
INNER JOIN 
sys.schemas sc
ON 
tbl.SCHEMA_ID = sc.SCHEMA_ID
WHERE 
tbl.is_ms_shipped = 0 
AND 
par.index_id IN (1,0)
GROUP BY 
sc.name, 
tbl.name
ORDER BY 
SUM(par.rows) DESC

Borrar Todos Los Objectos de una Base de Datos

Hace un tiempo estaba desarrollando unos proyectos utilizando Hosting de Terceros (Godaddy, Brinkster, Etc.) los cuales utilizaba sus Bases de Datos, y siempre tenia un problema, a la hora de subir un proyecto, pues tenia que eliminar todos los objetos de la base de datos utilizada, para volverlos a crear con los nuevos cambios, ya que ellos no te permiten restaurar un Backup directamente en sus servidores, esto es por medida de seguridad.

Con este problema, decidi crearme un metodo que me eliminara todos los Objectos que yo tenia creado en mi base de datos, aqui les dejo el codigo de ejemplo, con el cual solucione el problema!...


declare @n char(1)
set @n = char(10)

declare @stmt nvarchar(max)

-- procedimientos almacenados
select @stmt = isnull( @stmt + @n, '' ) +
    'drop procedure [' + name + ']'
from sys.procedures

-- constraints (Restricciones)
select @stmt = isnull( @stmt + @n, '' ) +
    'alter table [' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
from sys.check_constraints

-- funciones
select @stmt = isnull( @stmt + @n, '' ) +
    'drop function [' + name + ']'
from sys.objects
where type in ( 'FN', 'IF', 'TF' )

-- vistas
select @stmt = isnull( @stmt + @n, '' ) +
    'drop view [' + name + ']'
from sys.views

-- llaves primarias
select @stmt = isnull( @stmt + @n, '' ) +
    'alter table [' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
from sys.foreign_keys

-- tablas
select @stmt = isnull( @stmt + @n, '' ) +
    'drop table [' + name + ']'
from sys.tables

-- tipos definidos por el usuario
select @stmt = isnull( @stmt + @n, '' ) +
    'drop type [' + name + ']'
from sys.types
where is_user_defined = 1

exec sp_executesql @stmt