viernes, 10 de noviembre de 2006

SQL - Medir el tiempo de ejecución de sentencias sql

Algo muy útil para cuando tenemos diversas formas de solucionar un problema en SQL y desconocemos cual de ellas será la más rápida (no necesariamente la más optima) es medir el tiempo de ejecución de cada una de ellas y de esa forma poder seleccionar la solución más rápida.

--Declaracion de la variable que nos permitira medir el tiempo DECLARE @TiempoInicial DATETIME SET @TiempoInicial = GETDATE() -- ------------------------------- SETENCIAS ------------------------------- SELECT * FROM Persona WHERE DATEDIFF(day, FechaRegistro, DATEADD(DAY,-15,GETDATE())) <= 0 -- ------------------------------- SETENCIAS ------------------------------- -- Realizar la diferencia entre el tiempo inicial y final de la ejecución de las sentencias PRINT 'Operacion completada en: ' + RTRIM(CAST(DATEDIFF(ms,@TiempoInicial, GETDATE()) AS VARCHAR(10))) + ' milisegundos'

martes, 7 de noviembre de 2006

SQL - Crear un procedimiento almacenado

En el presente articulo veremos como crear tres tipos de procedimientos almacenados:
  1. Procedimento sin parametros.
  2. Procedimiento con parámetros de entrada.
  3. Procedimiento con parámetros de entrada y de salida. 

Nota: Los procedimientos almacenados definidos por el usuario son creados en la base de datos actual.
Procedimiento sin parámetros.

/* --------------------------------------------------------------------------------
   Autor: Mario Alberto Sanchez Gamboa
   Fecha:
   Descripcion: Procedimiento que realiza la suma de dos numeros y regresa
   el resultado mediante el uso de la sentencia SELECT.
      **Emplea declaracion de variables.
      **Asigacion de valores a variables.
      **Uso de ISNULL.- Remplaza el nulo por el valor especificado.
      **Uso de CAST.- Convierte explicitamente una expresion de un tipo de dato a otro.
      **Concatenacion de cadenas.
   -------------------------------------------------------------------------------- */
CREATE PROCEDURE spSumaSinParametros
AS
   --Declaracion de variables
   DECLARE @Numero1 FLOAT,
      @Numero2 FLOAT,
      @Resultado FLOAT,
      @Operacion NVARCHAR(25)


   --Asignacion de valores iniciales
   SET @Numero1 = 5.55
   SET @Numero2 = 15


   --Operacion.
   --Nota: Se puede hacer uso de SELECT y/o SET para la asignacion de valores a las variables.
   SELECT @Resultado = ISNULL(@Numero1, 0) + ISNULL(@Numero2, 0)
   SET @Operacion = CAST(@Numero1 AS VARCHAR) + ' + ' + CAST(@Numero2 AS VARCHAR) + ' = ' + CAST(@Resultado AS VARCHAR)


   --Realizar un select con el resultado de la operacion.
   SELECT @Numero1 AS Numero1, @Numero2 AS Numero2, @Resultado AS Resultado, @Operacion AS Operacion

GO
Para ejecutar el procedimiento almacenado empleamos la siguiente sentencia:

   EXECUTE spSumaSinParametros

Resultado:

Numero1 Numero2 Resultado Operacion
-------------------- ---------- --------------------- --------------------
5.5499999999999998 15.0 20.550000000000001 5.55 + 15 = 20.55

(1 row(s) affected)
Procedimiento con parámetros de entrada.

/* --------------------------------------------------------------------------------
   Autor: Mario Alberto Sanchez Gamboa
   Fecha:
   Descripcion: Procedimiento que realiza la suma de dos numeros
      los cuales recibe mediante parametros de entrada
      y regresa el resultado mediante el uso de la sentencia SELECT.
      **Emplea declaracion de variables.
      **Asigacion de valores a variables.
      **Uso de ISNULL.- Remplaza el nulo por el valor especificado.
      **Uso de CAST.- Convierte explicitamente una expresion de un tipo de dato a otro.
      **Concatenacion de cadenas.
   -------------------------------------------------------------------------------- */
CREATE PROCEDURE spSumaConParametros
      @Numero1 FLOAT,
      @Numero2 FLOAT
AS
   --Declaracion de variables
   DECLARE
      @Resultado FLOAT,
      @Operacion NVARCHAR(25)


   --Operacion.
   --Nota: Se puede hacer uso de SELECT y/o SET para la asignacion de valores a las variables.
   SELECT @Resultado = ISNULL(@Numero1, 0) + ISNULL(@Numero2, 0)
   SET @Operacion = CAST(@Numero1 AS VARCHAR) + ' + ' + CAST(@Numero2 AS VARCHAR) + ' = ' + CAST(@Resultado AS VARCHAR)


   --Realizar un select con el resultado de la operacion.
   SELECT @Numero1 AS Numero1, @Numero2 AS Numero2, @Resultado AS Resultado, @Operacion AS Operacion
GO
Para ejecutar el procedimiento almacenado empleamos la siguiente sentencia:

   EXECUTE spSumaConParametros 5.55, 15

Resultado:

Numero1 Numero2 Resultado Operacion
-------------------- ---------- --------------------- --------------------
5.5499999999999998 15.0 20.550000000000001 5.55 + 15 = 20.55

(1 row(s) affected)
Procedimiento con parámetros de entrada y salida.

/* --------------------------------------------------------------------------------
   Autor: Mario Alberto Sanchez Gamboa
   Fecha:
   Descripcion: Procedimiento que realiza la suma de dos numeros y regresa
      el resultado mediante el uso un parametro de salida y una sentencia SELECT.
      El valor son recibidos con parametros de entrada, y el resultado es regresado
      mediante un parametro de salida, asi como de una sentencia SELECT.
      **Emplea declaracion de variables.
      **Asigacion de valores a variables.
      **Uso de ISNULL.- Remplaza el nulo por el valor especificado.
      **Uso de CAST.- Convierte explicitamente una expresion de un tipo de dato a otro.
      **Concatenacion de cadenas.
   -------------------------------------------------------------------------------- */
CREATE PROCEDURE spSumaConParametroDeSalida
      @Numero1 FLOAT,
      @Numero2 FLOAT,
      @Resultado FLOAT OUTPUT

AS
   --Declaracion de variables
   DECLARE @Operacion NVARCHAR(25)


   --Operacion.
   --Nota: Se puede hacer uso de SELECT y/o SET para la asignacion de valores a las variables.
   SELECT @Resultado = ISNULL(@Numero1, 0) + ISNULL(@Numero2, 0)
   SET @Operacion = CAST(@Numero1 AS VARCHAR) + ' + ' + CAST(@Numero2 AS VARCHAR) + ' = ' + CAST(@Resultado AS VARCHAR)


   --Realizar un select con el resultado de la operacion.
   SELECT @Numero1 AS Numero1, @Numero2 AS Numero2, @Operacion AS Operacion
GO
Para ejecutar el procedimiento almacenado empleamos la siguiente sentencia:

   DECLARE @ParamResultado FLOAT    DECLARE @EjecucionParametro INT    EXECUTE @EjecucionParametro = spSumaConParametroDeSalida 5.55, 15, @ParamResultado OUTPUT    SELECT @ParamResultado AS Resultado, @EjecucionParametro AS EjecucionParametro

Resultado:

Numero1 Numero2 Resultado Operacion
-------------------- ---------- --------------------- --------------------
5.5499999999999998 15.0 20.550000000000001 5.55 + 15 = 20.55

(1 row(s) affected)

Resultado EjecucionParametro
--------------------- --------------------
20.550000000000001 0

(1 row(s) affected)
Si se desea comprobar la existencia de un procediento se puede hacer uso de las siguientes sentencias.

--Verificamos si el procedimiento que vamos a crear existe en la base de datos,
--en caso de que exista se procede a eliminar dicho procedimiento.
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'spSumaSinParametros' AND type = 'P')
   DROP PROCEDURE spSumaSinParametros
GO
En este ejemplo verificamos si ya existe el procedimiento spSumaSinParametros, en caso de que exista se procede a eliminarlo.

SQL - Conocer si un procedimiento, tabla, etc. existe en la base de datos

Para conocer si un objeto (procedimiento almacenado, constraint, llave foranea, etc.) existe en nuestra base de datos, podemos hacer uso de la tabla del sistema de la base de datos sysobjects en la cual se registran todos los objetos que hemos creados.
A continuación se detalla el diseño de la tabla sysobjects. 
   
Nombre de la columnaTipo de DatoDescripción
namesysnameNombre del objeto.
IdintNúmero de identificación del objeto.
xtypechar(2)Tipo de objeto. Puede ser alguno de los siguientes:

C = CHECK constraint
D = Default or DEFAULT constraint
F = FOREIGN KEY constraint
L = Log
FN = Scalar function
IF = Inlined table-function
P = Stored procedure
PK = PRIMARY KEY constraint (type is K)
RF = Replication filter stored procedure
S = System table
TF = Table function
TR = Trigger
U = User table
UQ = UNIQUE constraint (type is K)
V = View
X = Extended stored procedure

uidsmallintIdentificador del usuario propietario del objeto.
infosmallintReservado. Para uso interno solamente.
statusintReservado. Para uso interno solamente.
base_schema_
ver
intReservado. Para uso interno solamente.
replinfointReservado. Para uso por replicación.
parent_objintNúmero de identificación del objeto padre.
crdatedatetimeFecha en que el objeto fue crado.
ftcatidsmallintIdentifier of the full-text catalog for all user tables registered for full-text indexing, and 0 for all user tables not registered.
schema_verintNúmero de Version la cual es incrementada cada vez que cambia el esquema para un tabla.
stats_schema_
ver
intReservado. Para uso interno solamente.
typechar(2)Tipo de objeto. Puede ser alguno de los siguientes valores:

C = CHECK constraint
D = Default or DEFAULT constraint
F = FOREIGN KEY constraint
FN = Scalar function
IF = Inlined table-function
K = PRIMARY KEY or UNIQUE constraint
L = Log
P = Stored procedure
R = Rule
RF = Replication filter stored procedure
S = System table
TF = Table function
TR = Trigger
U = User table
V = View
X = Extended stored procedure

userstatsmallintReservado.
sysstatsmallintInternal status information.
indexdelsmallintReservado.
refdatedatetimeReservado para uso futuro.
versionintReservado para uso futuro.
deltrigintReservado.
instrigintReservado.
updtrigintReservado.
seltrigintReservado.
categoryintUsado para publicación, identitis (identity) y constraints.
cachesmallintReservado.
 
Ejemplo de uso:

--Verificamos si el procedimiento que vamos a crear existe en la base de datos,
--en caso de que exista se procede a eliminarlo.

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'spProcedimientoABuscar' AND type = 'P' < /FONT > )
   DROP PROCEDURE spProcedimientoABuscar

SQL - Devolver errores y advertencias desde un procedimiento almacenado de SQL Server

En diversas situaciones requerimos poder regresar advertencias o errores personalizados desde un procedimiento almacenado, en el presente articulo veremos como lograrlo.
Si se genera un error en SQL donde su gravedad sea igual o menor a 10 solo se lanza una advertencia sin generar una excepción, sin embargo, si la gravedad fue igual o mayor a 11 es lanzada una excepción y es probable que el procedimiento almacenado sea anulado. Es importante contar también con un manejo de transacciones para que se ejecute o no completo nuestro stored.


/* --------------------------------------------------------------------------------
   Autor: Mario Alberto Sanchez Gamboa
   Fecha:
   Descripcion: Procedimiento que lanza un error personalizado.
   Actualizacion:
   -------------------------------------------------------------------------------- */
ALTER PROCEDURE spTemporal
   @param1 BIT
AS
BEGIN

   IF @param1 = 1
   BEGIN
      RETURN 0
   END
   ELSE
   BEGIN
      RAISERROR ('Error personalizado al momento de ejecutar el procedimiento.', 11, 1)
      RETURN -1
   END

END

Si ejecutamos el stored anterior con un valor de diferente a 1 será lanzado el error personalizado.

EXEC spTemporal 0

Resultado:
Server: Msg 50000, Level 11, State 1, Procedure spTemporal, Line 18
Error personalizado al momento de ejecutar el procedimiento.

SQL - Generar números de filas haciendo uso de Tablas Temporales

En el presente ejemplo veremos como enumerar el resultado de un consulta, la cual normalmente difiere de nuestros identificadores o claves internas en la base de datos. Esto lo podemos lograr haciendo uso de la función IDENTITY y de Tablas temporales.

IDENTITY

Nos permite generar valores secuenciales, con base en los parámetros que se establezcan SELECT IDENTITY(TipoDato, ValorInicial, Incremento) AS ID_Num

  • TipoDato .- puede ser cualquiera de la categoría de los enteros (excepto BIT).
  • ValorInicial .- indica el valor inicial del cual se generarán los valores.
  • Incremento.- define el incremento que habrá entre los valores generados.

Esta sentencia la podemos utilizar solo cuando SELECT contiene la clausula INTO.

Tablas Temporales

Para hacer uso de la clausula INTO creamos una tabla temporal de la siguiente forma:

SELECT IDENTITY(INT, 1, 1) AS ID, CustomerID, CompanyName, ContactName, Country INTO #TMP_CUSTOMER FROM Customers ORDER BY Country SELECT * FROM #TMP_CUSTOMER DROP TABLE #TMP_CUSTOMER

En este ejemplo obtenemos los clientes de la tabla Customers ordenados por su campo Country de la base de datos Northwind y parte del resultado obtenido es:

IDCustomerIDCompanyNameContactNameCountry
1CACTUCactus Comidas para llevarPatricio SimpsonArgentina
2OCEANOcéano Atlántico Ltda.Yvonne MoncadaArgentina
3RANCHRancho grandeSergio GutiérrezArgentina
4PICCOPiccolo und mehrGeorg PippsAustria
5ERNSHErnst HandelRoland MendelAustria
6MAISDMaison DeweyCatherine DeweyBelgium
7SUPRDSuprêmes délicesPascale CartrainBelgium
8RICARRicardo AdocicadosJanete LimeiraBrazil
9TRADHTradição HipermercadosAnabela DominguesBrazil

Ahora, si la tabla de la cual vamos a obtener la información contiene una columna IDENTITY, el motor encontrará que hay 2 columnas INDENTITY en la tabla a generar, produciendo un error.

Para solucionar este problema es necesario convertir la columna IDENTITY de la tabla que causa el problema al mismo tipo de dato (lo que hacemos es quitarle el IDENTITY)

Por ejemplo, la tabla Products de la base de datos Northwind tiene definida la propiedad IDENTITY en la columna ProductID.

SELECT IDENTITY(INT, 1, 1) AS ID, CAST(ProductID AS INT) AS ProductID, ProductName INTO #TMP_PRODUCTS FROM Products SELECT * FROM #TMP_PRODUCTS DROP TABLE #TMP_PRODUCTS

Parte del resultado de este ejemplo es el siguiente:

IDProductIDProductName
117Alice Mutton
23Aniseed Syrup
340Boston Crab Meat
460Camembert Pierrot
518Carnarvon Tigers
61Chai
72Chang
839Chartreuse verte
94Chef Anton's Cajun Seasoning
105Chef Anton's Gumbo Mix

Información técnica en español - MSDN

El MSDN es un recurso esencial para aquellos desarrolladores que utilizan las herramientas de desarrollo y las tecnologías de Microsoft, ya que cuenta con una gran cantidad de información técnica acerca de la programación e incluye código de ejemplo, documentación, artículos técnicos y guías de referencia A continuación se listan las direcciones donde podran encontrar documentación de SQL Server, VisualSource Safe y Visual Studio 2005. MSDN en españolhttp://msdn2.microsoft.com/es-es/library/default.aspx Documentación de SQL Server 2005 en español - MSDNhttp://msdn2.microsoft.com/es-es/library/ms203721.aspx Documentación de Visual SourceSafe 2005 en español - MSDNhttp://msdn2.microsoft.com/es-es/library/ms299291(VS.80).aspx Documentación de Visual Studio en español - MSDNhttp://msdn2.microsoft.com/es-es/library/ms269115(VS.80).aspx