2016/11/24

CLAUSULA OUTPUT EN STORED PROCEDURES

 CLAUSULA OUTPUT EN STORED PROCEDURES

PROBLEMA: Alguna vez hemos regresado valores desde un procedimiento almacenado, regularmente lo utilizamos para devolver un conjunto de datos a través de la cláusula SELECT, pero sabíamos que existe la clausula OUTPUT para devolver valores también?

SOLUCION:  Sinceramente yo uso los procedimientos almacenados para devolver un conjunto de datos con mayor frecuencia que un solo valor, por lo tanto casi no uso esta cláusula pero es bueno que sepamos que existen otras opciones.

Algunas características?

  • Es posible devolver casi cualquier tipo, a excepción de TEXT, NTEXT, IMAGE, tipo de dato TABLA
  • Puedes utilizar las palabras reservadas OUT|OUTPUT

Algunos ejemplos de su funcionamiento?
USE AdventureWorks2014; 

GO

CREATE PROCEDURE dbo.ProcedimientoOutput
 @paramEntrada VARCHAR(20)
 , @paramSalidaDatetime DATETIME  OUT
 , @paramSalidaINT  INT    OUTPUT
 , @paramSalidaDECIMAL DECIMAL(5,2) OUT
 , @paramSalidaMoney  MONEY   OUTPUT
 , @paramSalidaUI  UNIQUEIDENTIFIER OUT
AS
 SET NOCOUNT ON;
 PRINT @paramEntrada; 
 SET @paramSalidaDatetime = GETDATE() 
 SET @paramSalidaINT = 1234567
 SET @paramSalidaDECIMAL = 123.45
 SET @paramSalidaMoney = 12345.678
 SET @paramSalidaUI = NEWID()
GO

--Declaramos las variables que se utilizarán para recibir los valores de salida
DECLARE @salidaDatetime DATETIME; 
DECLARE @salidaINT INT; 
DECLARE @salidaDecimal DECIMAL(5,2); 
DECLARE @salidaMoney MONEY; 
DECLARE @salidaUI UNIQUEIDENTIFIER; 

EXEC dbo.ProcedimientoOutput 'ENTRADA' , @salidaDateTime OUT, @salidaINT OUT, @salidaDecimal OUT, @salidaMoney OUT, @salidaUI OUT; 

SELECT @salidaDatetime, @salidaDatetime, @salidaINT, @salidaDecimal, @salidaMoney, @salidaUI ;

Ahora bien, si queremos devolver un tipo CURSOR también lo podemos hacer, ya que no podemos devolver un tipo de dato TABLA:
USE AdventureWorks2014; 

GO

CREATE PROCEDURE dbo.ProcedimientoOutputCursor
 @paramEntrada VARCHAR(20)
 , @paramCursor   CURSOR VARYING OUTPUT
AS
 SET NOCOUNT ON;
 PRINT @paramEntrada; 
 SET @paramCursor = CURSOR FOR
      SELECT ROW_NUMBER() OVER( ORDER BY CurrencyCode ) AS rn, CurrencyCode, Name
      FROM Sales.Currency;
    OPEN @paramCursor;
GO

DECLARE @cursor CURSOR;

EXEC dbo.ProcedimientoOutputCursor 'ENTRADA' , @cursor OUTPUT;

WHILE (@@FETCH_STATUS = 0)
BEGIN;
     FETCH NEXT FROM @cursor;
END;
CLOSE @cursor;
DEALLOCATE @cursor;
GO


Cualquier duda, ya saben como contactarme ;)

SALUDOS!

2016/11/22

NUEVA FUNCIONALIDAD: DROP IF EXISTS

PROBLEMA: Como creas tu script para generar tablas u objetos nuevos? Utilizando el clásico IF OBJECT_ID o el IF EXISTS? Sabías que con la versión 2016 fue introducida una nueva funcionalidad que nos evita escribir tanto código para preguntar si un objeto existe y en caso que así sea, procedas a realizar alguna acción(la más común es eliminar dicho objeto)?

SOLUCION: Apenas me doy cuenta que existe una cláusula que te ayuda a ahorrar algo de código al momento de generar tus scripts de manera manual xD, veamos como funciona DROP  IF EXISTS <nombreObjeto>

OBJETO: BASE DE DATOS

OBJETO: TABLA

OBJETO: SCHEMA

OBJETO: COLUMNA

OBJETO: FUNCION
Estos son algunos objetos en la que la cláusula DROP IF EXISTS funciona, sin embargo hay algunos otros como:

AGGREGATE
ASSEMBLY
DEFAULT
INDEX
PROCEDURE
ROLE
RULE
SECURITY POLICY
SEQUENCE
SYNONYM
TRIGGER
TYPE
USER
VIEW

Recuerden que si intentan eliminar un objeto que no existe, les generará un error, por lo tanto se recomienda hacer esto, les dejo los scripts aquí.

SALUDOS!

2016/11/16

EJECUTANDO UN SCRIPT USANDO SQLCMD

PROBLEMA: Tenemos que ejecutar un archivo *.sql de gran tamaño, sin embargo nos topamos con problemas de memoria insuficiente o que no podemos abrir el archivo como los que se muestran en las siguientes imágenes, que podemos hacer?
SOLUCION: Recordando nuestro artículo anterior en el que utilizábamos la utilería SQLCMD para exportar el resultado de una consulta hacia un archivo de texto plano, podemos utilizar esta misma utilería para poder ejecutar un archivo *.sql, veamos como podemos hacerlo.

Para empezar, primero generaré un archivo de creación de objetos y otro archivo para el contenido de algunas de las tablas de la base de datos Adventure Works que pueden descargar de este AQUI, si descomprimos el archivos podemos observar su tamaño:
En algunos equipos no es posible abrir el archivo para poder ejecutarlo, por la cantidad de memoria libre que tenemos al momento, es por ello que se recomienda usar la utilería SQLCMD y como hacemos esto, de la siguiente manera:

sqlcmd -S 192.168.15.3\SQLSERVER2014 -U sa -P pass%word0 -i C:\Users\Sergio\Documents\CHECKO\SQLSERVER\BLOG\posts\EjecutandoScriptConSQLCMD\script.sql -o C:\Users\Sergio\Documents\CHECKO\SQLSERVER\BLOG\posts\EjecutandoScriptConSQLCMD\resultadoScript.txt

Indicamos donde guardaremos los resultados de la ejecución de la consulta y vemos que el script crea una BD con el nombre PruebaCargaScript con algunas tablas y datos que carga en ellas
De esta manera, podemos observar que el script se ejecutó y tenemos los resultados en el archivo que indicamos y así es como podemos ejecutar un archivo de gran tamaño.

Espero que les sea de ayuda…

SALUDOS!

2016/11/09

EXPORTANDO RESULTADO DE CONSULTA A TXT CON SQLCMD

PROBLEMA: A muchos de nosotros nos han pedido volcar el resultado de una consulta a un archivo de texto plano, tal vez conozcamos BCP o SSIS para realizar estas tareas, pero… conocemos la utilería SQLCMD?

SOLUCION: Una de las posibles soluciones(como siempre, hay varias) para cumplir con esta actividad es la utilería SQLCMD, pero que es esta utilería? De donde la bajo? Como la instalo? Etc.

SQLCMD es una especie de línea de comandos con la capacidad de ejecutar código T-SQL, además de poder ejecutar archivos *.sql, que contengan una serie de instrucciones; dicha utilería ya viene con la instalación de SQL SERVER por lo tanto no requerimos de bajarlo de ninguna parte.

Veamos cómo podemos exportar el resultado de una consulta a un archivo de texto plano, la documentación de esta utilería la podemos encontrar aquí

1.- Debemos abrir una línea de comandos de Windows, WIN + R, escribimos CMD y luego presionamos ENTER.
2.- En la ventana de comandos, me conectare a mi servidor con el usuario y contraseña y después le indicaré mi consulta, de la siguiente manera:

sqlcmd -S 192.168.15.11\SQLSERVER2014 -U sa -P pass%word0 -Q "SELECT TOP 2 * FROM AdventureWorks2014.Production.Product;"
-S : Indica el nombre de servidor o IP y la instancia de SQL SERVER.
-U :  Credencial para conectarnos al servidor de base de datos.
-P : Contraseña
-Q : Instrucción que ejecutaremos y debe estar encerrada entre comillas dobles.

Este es el resultado de la ejecución:
Para exportarlo a un archivo hay que utilizar -o “C:\ruta\del\archivo\nombreDelArchivo.txt”

sqlcmd -S 192.168.15.11\SQLSERVER2014 -U sa -P pass%word0 -Q "SELECT TOP 2 * FROM AdventureWorks2014.Production.Product;" -o "C:\resultadoConsulta.txt"

Para mi ejemplo cambie la ruta:
Y otro ejemplo con todas las filas de la consulta:
Y eso es todo, más adelante profundizare más en la utilería como por ejemplo como ejecutar un archivo de sentencias T-SQL, espero que les sirva.

SALUDOS!

2016/10/30

PALABRAS RESERVADAS PARA NOMBRAR OBJETOS

PROBLEMA: Cuantos de nosotros no hemos nombrado una llave primaria como ID, o una tabla que utilizamos a para almacenar los usuarios del sistema como USER, aunque SQL SERVER permite usar dichas palabras reservadas como nombres de objetos, con el pasar de los días se vuelve un poco complejo estar utilizando los corchetes o brackets [ ] para hacer referencia los objetos que fueron nombrados de esta manera.

SOLUCION: Más que una solución, les comparto un poco de la experiencia que he tenido que vivir en los últimos días a causa de manipular una BD existente y que fuera creada utilizando estas palabras en los objetos, tal vez podrán decir ¨Naaaa no hay problema, no pasa nada si le ponemos los corchetes¨, pero créanme que se vuelve algo tedioso.

Intentemos ejecutar la siguiente consulta:
USE AdventureWorks2014;  
CREATE TABLE table ( 
 sequence INT IDENTITY(1,1)
 , user VARCHAR(100)
 , level SMALLINT 
 , date DATETIME
);
Pero que pasa si encerramos los nombres dentro de corchetes []
USE AdventureWorks2014;  
CREATE TABLE [table] ( 
 [sequence] INT IDENTITY(1,1)
 , [user] VARCHAR(100)
 , [level] SMALLINT 
 , [date] DATETIME
);
Ahora intentemos realizar una consulta sobre la tabla :
USE AdventureWorks2014;  
SELECT * FROM table; 
No es posible, tenemos que encerrar el nombre de la tabla dentro de corchetes [ ]
USE AdventureWorks2014;  
SELECT * FROM [table]; 
Aunque no tenemos datos en la tabla, si podemos realizar la consulta.

Ahora, esto es responsabilidad de las personas encargadas del diseño de la BD, sin embargo recuerden que debemos facilitar el mantenimiento y las consultas a todas las demás personas que vayan a requerir del acceso a la BD, por lo tanto es importante tomar todas estas consideraciones en cuenta, mi recomendación: No debemos usar palabras reservadas para nombras objetos.


Nos leemos después, SALUDOS!.

2016/07/24

DICCIONARIO DE DATOS

PROBLEMA: Como desarollador de BD, se requiere de la creación del diccionario de datos, he visto que muchos lo realizan en archivos de WORD o EXCEL, pero creo que es algo tedioso, ustedes como realizan el diccionario de datos?

SOLUCION: SQL SERVER tiene una propiedad para los objetos en la cual se puede almacenar la descripción de cada uno de ellos, veamos donde se encuentra:
Es aquí donde se debe agregar la propiedad MS_Description y su valor o la descripción. Sin embargo es algo complejo y laborioso; encontré otra forma que es utilizando el consejo del MVP Ken Simmons, un tip que el publicó en MSSQLTIPS, es utilizando un script creado por el mismo, veamoslo:
USE [AdventureWorks2014]
GO

--Script to add an Extended Property to the Table
EXEC sys.sp_addextendedproperty 
@name=N'MS_Description', 
@value=N'Lookup table containing the departments within the Adventure Works Cycles company.' ,
@level0type=N'SCHEMA', 
@level0name=N'HumanResources', --Schema Name
@level1type=N'TABLE', 
@level1name=N'Department' --Table Name
GO

--Script to add an Extended Property to a column
EXEC sys.sp_addextendedproperty 
@name=N'MS_Description', 
@value=N'Name of the department.' ,
@level0type=N'SCHEMA', 
@level0name=N'HumanResources', --Schema Name
@level1type=N'TABLE', 
@level1name=N'Department', --Table Name
@level2type=N'COLUMN', 
@level2name=N'Name'--Column Name
GO
Después de hacer esto para cada columna y tabla, es necesario ejecutar el script que el proporciona para obtener las descripciones capturadas en un formato HTML que el mismo creo.

Con el resultado en forma de texto, lo copiamos a un archivo y lo guardamos como HTML o HTM y el resultado es el siguiente:


Una opción más es la aplicación SQL DATADICTIONARY y en lo particular se me hace demasiado práctica y muy fácil de usar. Solo tenemos que conectarnos a nuestra BD y comenzar a capturar las descripciones por cada uno de los objetos.


Después damos click en EDIT y podemos movernos entre la descripción de la BD, tablas, columnas, procedimientos almacenados, vistas, funciones, índices, etc.

Con esto ya podemos generar nuestro diccionario de datos

Y este es el resultado:


Aun cuando es una versión demo, creo que genera un PDF muy aceptable, ya si quieren pueden comprar la licencia y puede generar en formato HTML como lo muestra la página.

Espero que les sirva para realizar sus diccionarios de datos.

SALUDOS!

2016/07/23

BUSCANDO PRIMARY KEYS Y FOREIGN KEYS?

PROBLEMA: Uno de los principales retos al que me tuve enfrentar era conocer las relaciones que existían entre las tablas y por ende, las columnas que componían cada una de las llaves primarias de las tablas, como lograr esto?

SOLUCION: Existen varias formas de poder conocerlos, en lo particular me adapté más a esta forma que es utilizando los procedimientos de catalogo, les explico:

Como ejemplo utilizaré algunas tablas de la BD AdventureWorks2014, las cuales son Person.Person , Person.BusinessEntityContact, Person.ContactType

Los procedimientos almacenados que utilizaremos son los siguientes: sp_pkeys , sp_fkeys

El script es el siguiente:
USE AdventureWorks2014;  
GO  
--nombre de la tabla
DECLARE @varTableName VARCHAR(100) = 'Person'  
DECLARE @varTableOwner VARCHAR(100) = 'Person'

EXEC sp_pkeys @table_name =  @varTableName   ,  @table_owner = @varTableOwner

EXEC sp_fkeys @pktable_name = @varTableName  , @pktable_owner = @varTableOwner

EXEC sp_fkeys @fktable_name = @varTableName , @fktable_owner = @varTableOwner


USE AdventureWorks2014;  
GO  
--nombre de la tabla
DECLARE @varTableName VARCHAR(100) = 'BusinessEntityContact'  
DECLARE @varTableOwner VARCHAR(100) = 'Person'

EXEC sp_pkeys @table_name =  @varTableName   ,  @table_owner = @varTableOwner

EXEC sp_fkeys @pktable_name = @varTableName  , @pktable_owner = @varTableOwner

EXEC sp_fkeys @fktable_name = @varTableName , @fktable_owner = @varTableOwner


USE AdventureWorks2014;  
GO  
--nombre de la tabla
DECLARE @varTableName VARCHAR(100) = 'ContactType'  
DECLARE @varTableOwner VARCHAR(100) = 'Person'

EXEC sp_pkeys @table_name =  @varTableName   ,  @table_owner = @varTableOwner

EXEC sp_fkeys @pktable_name = @varTableName  , @pktable_owner = @varTableOwner

EXEC sp_fkeys @fktable_name = @varTableName , @fktable_owner = @varTableOwner

Es un script muy sencillo pero que me ha ayudado bastante para conocer la información sobre una tabla, más adelante les mostraré como pueden buscar una columna o una tabla en toda la BD en caso que solo tenga una pequeña noción del nombre.


SALUDOS

2016/07/21

IIF, CHOOSE: FUNCIONES NUEVAS POSIBLEMENTE DESCONOCIDAS

PROBLEMA: Desde la versión 2012 tenemos nuevas funciones en muchos aspectos del motor de BD que nos ayudan a mejorar el rendimiento de nuestras o a optimizar las mismas, sabías sobre la inclusión de las funciones IIF y CHOOSE? Sabes para que sirven?

SOLUCION: Les explicaré de manera general el funcionamiento y algunos ejemplos de los mismos.

IIF
Muchas personas que hemos venido trabajando versiones anteriores a SQL SERVER 2012 hemos estado pidiendo a gritos una función similar; devuelve VERDADERO o FALSO para expresión de tipo booleana analizada dentro de la sintaxis.

En anteriores versiones usábamos la sintaxis CASE WHEN para tener un resultado similar a la función IIF, sin embargo la gran diferencia es que la primera función puede evaluar más de una expresión, la segunda solamente puede evaluar una.

Formato sencillo
CASE expresionBooleana
WHEN valorExpresionBooleana1 THEN valorDevueltoParaResultadoVerdadero1
WHEN valorExpresionBooleana2 THEN valorDevueltoParaResultadoVerdadero2

WHEN valorExpresionBooleanaN THEN valorDevueltoParaResultadoVerdaderoN
ELSE valorDevueltoParaELSE
END
USE AdventureWorks2014;  
GO  
SELECT   ProductNumber, ProductLine,  Category =  
      CASE ProductLine  
         WHEN 'R' THEN 'Road'  
         WHEN 'M' THEN 'Mountain'  
         WHEN 'T' THEN 'Touring'  
         WHEN 'S' THEN 'Other sale items'  
         ELSE 'Not for sale'  
      END,  
   Name  
FROM Production.Product  
ORDER BY ProductNumber;  
GO
Formato complejo
CASE
WHEN expresionBooleana1 THEN valorDevueltoParaResultadoVerdadero1
WHEN expresionBooleana2 THEN valorDevueltoParaResultadoVerdadero2
WHEN expresionBooleanaN THEN valorDevueltoParaResultadoVerdaderoN
ELSE valorDevueltoParaELSE

END
USE AdventureWorks2014;  
GO  
SELECT   ProductNumber, Name, [Price Range] =   
      CASE   
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'  
         WHEN ListPrice < 50 THEN 'Under $50'  
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'  
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'  
         ELSE 'Over $1000'  
      END  
FROM Production.Product  
ORDER BY ProductNumber ;  
GO  


Un ejemplo sencillo para IIF es el siguiente:
DECLARE @a int = 45, @b int = 40;  
SELECT IIF ( @a > @b, 'TRUE', 'FALSE' ) AS Result;  

Ahora bien, tratemos de aplicar la función IIF a los ejemplos utilizados para CASE
USE AdventureWorks2014;  
GO  
SELECT   ProductNumber, ProductLine,  Category =  
      CASE ProductLine  
         WHEN 'R' THEN 'Road'  
         WHEN 'M' THEN 'Mountain'  
         WHEN 'T' THEN 'Touring'  
         WHEN 'S' THEN 'Other sale items'  
         ELSE 'Not for sale'  
      END, 
   ResultadoIIF = 
   IIF( ProductLine = 'R' , 'Road' , 
  IIF( ProductLine = 'M' , 'Mountain' , 
   IIF( ProductLine = 'T' , 'Touring' ,
    IIF( ProductLine = 'S' , 'Other sale items' , 
     'Not for sale' ) ) ) )
   , Name  
FROM Production.Product  
ORDER BY ProductNumber;  
GO

USE AdventureWorks2014;  
GO  
SELECT   ProductNumber, Name, [Price Range] =   
      CASE   
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'  
         WHEN ListPrice < 50 THEN 'Under $50'  
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'  
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'  
         ELSE 'Over $1000'  
      END  
   , ResultadoIIF = 
   IIF( ListPrice = 0 , 'Mfg item - not for resale'  ,
  IIF( ListPrice < 50 , 'Under $50' ,
   IIF( ListPrice >= 50 and ListPrice < 250 , 'Under $250' , 
    IIF( ListPrice >= 250 and ListPrice < 1000 , 'Under $1000' ,
     'Over $1000'   ) ) ) ) 
FROM Production.Product  
ORDER BY ProductNumber ;  
GO 

CHOOSE
Esta función devuelve el valor contenido en una lista de valores dado una posición específica.

CHOOSE ( posición , valor1, valor2 , valor3[,  valorN ] ) 
SELECT CHOOSE ( 3, '1. UNO', '2. DOS', '3. TRES', '4. CUATRO' ) AS Resultado;  

USE AdventureWorks2014;  
GO  
SELECT ProductCategoryID, CHOOSE (ProductCategoryID, 'A','B','C','D','E') AS Expression1  
FROM Production.ProductCategory; 

USE AdventureWorks2014;  
GO  
SELECT JobTitle, HireDate
, CHOOSE(MONTH(HireDate),'Invierno','Invierno', 'Primavera','Primavera','Primavera','Verano','Verano', 'Verano','Otoño','Otoño','Otoño','Invierno') AS Estacion 
FROM HumanResources.Employee  

Espero que estos ejemplos les sirvan para comprender mejor el funcionamiento y además puedan aplicar dichas funciones si es que se requiere.

SALUDOS!

2016/07/12

SP, VERSIONES, HERRAMIENTAS DE SQL SERVER



Con la salida del SERVICE PACK 2 para SQL SERVER 2014, se me ocurrió hacer una recopilación de las versiones, herramientas y SP para las versiones que vengo utilizando, sé que no soy el primero que hace esto, sin embargo en una ocasión un MVP me dijo que hiciera un blog para escribir sobre las nuevas cosas que vaya aprendiendo, esto con la finalidad de cuando necesite recordar algo, ya sabré donde buscar en primera instancia, espero que también les sirva a ustedes.

SERVICE PACKS
SQL SERVER 2016




SQL SERVER 2014


SQL SERVER 2012


DATA TOOLS

EXPRESS EDITIONS

EVALUATION EDITIONS

EXTERNAL TOOLS
SQL DATA DICTIONARY Herramienta sencilla para realizar el diccionario de nuestra base de datos, con la versión demo creo que es suficiente, sin embargo el costo no es tan alto, ustedes deciden.

Con el tiempo iré actualizando este artículo con herramientas que yo en lo particular utilizo, espero que les sirva, porque seguramente a mi también me servirá.


SALUDOS!

2016/07/10

VERSIONES DE EVALUACION SQL SERVER 2016

Como muchos han de saber, hace algunas semanas se anunció que la versión SQL SERVER 2016 DEVELOPER sería gratuita, bien pues esta descarga la podemos hacer desde la siguiente liga:


Después nos pedirá que iniciemos sesión o en su caso registrarnos:

Nos pide cierta información para el registro

Después de dar click en continuar, se iniciará automáticamente la descarga, elegimos la opción deseada.

En mi caso elegí descargar la instalación, porque quiero conservar el ISO para futuras instalaciones:

Con esto ya tendremos el ISO para poder realizar la instalación:

Afortunadamente ahora en esta nueva versión ya trae las ligas para poder descargar e instalar las herramientas como SQL SERVER DATA TOOLS

Una vez seleccionada la opción de instalación de una nueva instancia, podremos darnos cuenta que nos da la opción de seleccionar alguna de las versiones de las evaluación, estas son  EVALUATION, DEVELOPER, EXPRESS. La primera nos da la opción de instalar todas las características de una versión completa de SQL SERVER sin embargo solo es por 180 días, DEVELOPER también nos permite instalar todas las características, sin embargo solo es para desarrollo, no está permitido su uso a nivel producción, y la EXPRESS es una versión más ligera.

Una gran opción para desarrollar y probar las nuevas características que nos trae esta versión.
SALUDOS!