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

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/05

OBJETO SECUENCIA

PROBLEMA: Muchos o todos conocemos lo que es una columna con la propiedad autoincrementable, sin embargo, a veces requerimos de un variable que se pueda utilizar por toda la base de datos y que tenga la misma propiedad de ser autoincrementable al igual que una columna IDENTITY, sabemos que objeto utilizar?

SOLUCION: A partir de la versión 2012, SQL SERVER introdujo los objetos llamados SECUENCIA, dichos objetos pueden ser creados como cualquier otro, llámese una vista, una tabla, una función entre otros y con la particularidad que puede ser utilizado en cualquier lado de nuestra base de datos, veamos como crear uno y como utilizarlo.

Primero veamos la sintaxis que nos ofrece la MSDN
CREATE SEQUENCE [schema_name . ] sequence_name
    [ AS [ built_in_integer_type | user-defined_integer_type ] ]
    [ START WITH <constant> ]
    [ INCREMENT BY <constant> ]
    [ { MINVALUE [ <constant> ] } | { NO MINVALUE } ]
    [ { MAXVALUE [ <constant> ] } | { NO MAXVALUE } ]
    [ CYCLE | { NO CYCLE } ]
    [ { CACHE [ <constant> ] } | { NO CACHE } ]
    [ ; ]

No detallaré todas las opciones, solo lo que creo considerable. Para empezar, es necesario señalar que dicho objeto se crea utilizando tipos de datos numéricos (INT, SMALLINT, BIGINT, TINYINT, FLOAT, NUMERIC, entre otros ). Veamos algunos ejemplos ahora:
USE pruebas; 

CREATE SEQUENCE dbo.objSecuencia AS INT
 START WITH 50
 INCREMENT BY 3
 MINVALUE 50 MAXVALUE 60
 CYCLE; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO


USE pruebas; 

CREATE SEQUENCE dbo.objSecuencia AS INT
 START WITH 50
 INCREMENT BY 3
 MINVALUE 50 MAXVALUE 60
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO


Secuencia hacia atrás:
USE pruebas;

CREATE SEQUENCE dbo.objSecuencia AS INT
 START WITH 50
 INCREMENT BY -3
 MINVALUE 50 MAXVALUE 60
 CYCLE
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO


USE pruebas;

CREATE SEQUENCE dbo.objSecuencia AS INT
 START WITH 50
 INCREMENT BY -3
 MINVALUE 50 MAXVALUE 60
 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO

SELECT NEXT VALUE FOR dbo.objSecuencia; 
GO


Si al objeto le especificamos el tipo de dato, es necesario respetar los rangos que dicho tipo de dato puede almacenar, un ejemplo el siguiente:
CREATE SEQUENCE dbo.objSecuencia AS TINYINT
 START WITH 0
 INCREMENT BY 50
 MINVALUE 0 MAXVALUE  255
GO


USE pruebas;

CREATE SEQUENCE dbo.objSecuencia AS TINYINT
 START WITH 0
 INCREMENT BY 100
 MINVALUE 0 MAXVALUE  255
 CYCLE
GO

DECLARE @tab TABLE ( columna1 TINYINT, descripcion VARCHAR(100) ); 

INSERT INTO @tab
SELECT NEXT VALUE FOR dbo.objSecuencia , 'uno'; 

INSERT INTO @tab
SELECT NEXT VALUE FOR dbo.objSecuencia , 'dos'; 

INSERT INTO @tab
SELECT NEXT VALUE FOR dbo.objSecuencia , 'tres'; 

INSERT INTO @tab
SELECT NEXT VALUE FOR dbo.objSecuencia , 'cuatro';

INSERT INTO @tab
SELECT NEXT VALUE FOR dbo.objSecuencia , 'cinco';

INSERT INTO @tab
SELECT NEXT VALUE FOR dbo.objSecuencia , 'seis';

SELECT * FROM @tab; 

Un último ejemplo, como les comentaba podemos utilizarlos en muchas partes de nuestra base de datos, aquí lo utilizaremos en una consulta de la base de datos AdventureWorks2014 junto con la clausula OVER
SELECT 
NEXT VALUE FOR dbo.objSecuencia OVER ( ORDER BY BusinessEntityID ) AS col, 
*
FROM HumanResources.Employee


Espero que con estos ejemplos puedan implementar objetos secuencia con lo requieran.

SALUDOS!

2016/07/01

MODIFICANDO LA NUMERACION DE UN IDENTITY

PROBLEMA: En los foros de MSDN, muchas personas se preguntan como modificar el siguiente número que utilizará la propiedad IDENTITY al momento de realizar una inserción.

SOLUCION: Utilizando la sentencia DBCC CHECKIDENT podemos resolver esto de la siguiente manera.


Primero crearemos una tabla con algunos datos de prueba:
IF OBJECT_ID( 'dbo.tablaPruebasIdentity' ) IS NOT NULL
 DROP TABLE dbo.tablaPruebasIdentity; 

CREATE TABLE dbo.tablaPruebasIdentity( 
 columnaID SMALLINT IDENTITY( 1,1 ) 
 , descripcion VARCHAR(100) 
); 

INSERT INTO dbo.tablaPruebasIdentity( descripcion ) 
VALUES( 'uno' ) , ('dos'), ('tres'), ('cuatro') ;  
Ahora bien, podemos revisar cual es el último valor para nuestra columna con la propiedad IDENTITY de la siguiente manera:
DBCC CHECKIDENT('dbo.tablaPruebasIdentity', NORESEED )
Ejecutemos la siguiente instrucción para modificar el siguiente valor para nuestra columna IDENTITY
DBCC CHECKIDENT( 'dbo.tablaPruebasIdentity' , RESEED, 10 ); 
De esta manera podemos observar que el valor actual para la propiedad IDENTITY ( no es el ultimo valor que se encuentra en la columna) es de 10, lo que quiere decir que el siguiente valor para la columna será 11, ejecutemos nuevamente: 
DBCC CHECKIDENT('dbo.tablaPruebasIdentity', NORESEED )
El valor para la propiedad IDENTITY ya cambió, sin embargo no quiere decir que sea el ultimo IDENTITY ingresado en la columna que es de 4, ahora insertemos nuevamente algunos datos y revisemos el contenido de la tabla:
INSERT INTO dbo.tablaPruebasIdentity( descripcion ) 
VALUES( 'once' ) , ('doce'),('trece') ; 

SELECT * FROM dbo.tablaPruebasIdentity; 

Ejecutemos nuevamente la sentencia de verificación de IDENTITY: 
DBCC CHECKIDENT('dbo.tablaPruebasIdentity', NORESEED );
Los valores han cambiado nuevamente, ahora regresemos el valor de la columna IDENTITY para que inserte el número 5 y consultamos la propiedad nuevamente: 
DBCC CHECKIDENT( 'dbo.tablaPruebasIdentity' , RESEED, 4 ); 
DBCC CHECKIDENT('dbo.tablaPruebasIdentity', NORESEED ); 

Y una vez más insertemos algunos datos para verificar el contenido de la tabla: 
INSERT INTO dbo.tablaPruebasIdentity( descripcion ) 
VALUES( 'cinco' ) , ('seis'); 

SELECT * FROM dbo.tablaPruebasIdentity; 

Revisamos la propiedad IDENTITY
DBCC CHECKIDENT('dbo.tablaPruebasIdentity', NORESEED );
El primer valor subrayado con rojo recordemos que es el ultimo valor ingresado en cualquier operación por lo que el siguiente número que fuera ingresado ocupará el valor de 7, y el segundo valor subrayado es el valor más alto ingresado. Pero que pasaría si nosotros seguimos insertando valores hasta alcanzar el número 11, que pasará? Lo saltará automáticamente? La respuesta es NO, veamos:
INSERT INTO dbo.tablaPruebasIdentity( descripcion ) 
VALUES( 'siete' ) , ('ocho'), ( 'nueve' ) ,('diez'), ( 'once' ), ('doce');

SELECT * FROM dbo.tablaPruebasIdentity; 

Por última vez revisemos cual será el siguiente valor que se insertará:
DBCC CHECKIDENT('dbo.tablaPruebasIdentity', NORESEED );
Con esta información, ya podrán reiniciar o establecer el siguiente número en la columna que contenga dicha propiedad IDENTITY, podrán repetir los números siempre y cuando su columna no sea parte de la llave primaria.

SALUDOS!

2016/06/30

NOMBRES DE OBJETOS o IDENTIFICADORES

PROBLEMA: Los identificadores dentro SQL SERVER no son más que los nombres que se les asigna a cada objeto, con esto podemos hacer referencia a ellos de manera rápida, pero… sabías que puedes nombrar objetos con caracteres extraños? Veamos algunos ejemplos y las reglas que sugieren seguir para establecer nombres de objetos usando las mejores prácticas.

En primer lugar, los identificadores son requeridos para “casi” todos los objetos dentro de SQL SERVER como tablas, columnas, índices, vistas, triggers, procedimientos almacenados, entre algunos otros.

IDENTIFICADORES REGULARES

Cuales son estos objetos? Son aquellos que siguen algunas sencillas reglas

1.- El primer carácter del nombre debe comenzar con:
                - Una letra.
                - Cualquiera de los símbolos @  _   #   ( No se recomienda el uso de estos símbolos )
2.- Los caracteres posteriores pueden ser:
                - Letras
                - Números
                - Cualquiera de los símbolos @  _   #
3.- El nombre del identificador no debe ser una palabra reservada.
4.- No debe contener espacios

Veamos algunos ejemplos:
CREATE DATABASE _NombreBdNuevo; 
CREATE DATABASE #NombreBdNuevo; 
GO

USE _NombreBdNuevo; 

CREATE TABLE tablaNueva#@1( 
 columna1$ VARCHAR(10)
 , #columna2@ VARCHAR(10)
 , columna3 VARCHAR(10)
 , CONSTRAINT nombreRestriccion$ PRIMARY KEY ( columna1$ )
)

Aunque la documentación de Microsoft dice que podemos generar identificadores regulares iniciando con el símbolo @, no pude crear una BD de esa forma, de igual manera intenté crear algunos otros objetos iniciando con el mismo símbolo pero no me lo permitió, por lo que sugiero evitar el uso de dicho símbolo.

Ahora los siguientes ejemplos son para los identificadores considerados como no regulares, aunque no entiendo quien crearía objetos con la siguiente nomenclatura:
CREATE DATABASE [ nombre de BD ]; 

CREATE DATABASE [nombre  BD  "irregular"]; 
GO

USE [nombre  BD  "irregular"];

CREATE TABLE [nombre tabla irregular]
( 
 [columna 1 con espacios] VARCHAR(100)
 , [   espacios al inicio] VARCHAR(100)
) ;

Lo más común que se puede ver dentro de los desarrollos de Bases de datos es que se utilice el guión bajo _ , números y letras, sin embargo es bueno conocer que se pueden generar nombres de objetos utilizando otros caracteres, aunque los expertos no recomiendan utilizar caracteres extraños ni siquiera el $, nuevamente los dejo a su consideración al momento de generar los nombres de sus objetos, establezcan entre todo el equipo de desarrollo un estándar para los nombres y síganlo, el que sea más conveniente.


SALUDOS! 

2016/06/29

ALIAS: RENOMBRANDO TABLAS, COLUMNAS

PROBLEMA: Como parte de las buenas prácticas que se recomiendan para escribir consultas, es necesario el uso de ALIAS para los objetos, muchos de nosotros sabemos como renombrar nombres de columnas y tablas temporalmente en SQL SERVER, sabías que hay más de una manera de lograr esto?

SOLUCION: En el siguiente artículo veremos las formas más conocidas para renombrar objetos temporalmente en una consulta, y les dejaré a su consideración la mejor forma para escribir sus consultas:

1

La más conocida de todas es usando la palabra clave AS, veamos algunos ejemplos:
SELECT *
FROM HumanResources.Employee AS e
    INNER JOIN Person.Person AS p
    ON e.BusinessEntityID = p.BusinessEntityID
ORDER BY p.LastName

SELECT 
 e.BirthDate AS BirthDate
 , e.BusinessEntityID AS BusinessEntityIDemployee
 , e.CurrentFlag AS CurrentFlag
 , p.BusinessEntityID AS BusinessEntityIDperson
FROM HumanResources.Employee AS e
    INNER JOIN Person.Person AS p
    ON e.BusinessEntityID = p.BusinessEntityID
ORDER BY p.LastName

2

Escribiendo el nombre de la columna o tabla inmediatamente después del nombre al que hacemos referencia:
SELECT *
FROM HumanResources.Employee employee
    INNER JOIN Person.Person person
    ON employee.BusinessEntityID = person.BusinessEntityID
ORDER BY person.LastName

SELECT 
 employee.BirthDate BirthDate
 , employee.BusinessEntityID BusinessEntityIDemployee
 , employee.CurrentFlag CurrentFlag
 , person.BusinessEntityID BusinessEntityIDperson
FROM HumanResources.Employee employee
    INNER JOIN Person.Person person
    ON employee.BusinessEntityID = person.BusinessEntityID
ORDER BY person.LastName

3

Utilizando el símbolo = , esto solo para el caso de los nombres de las columnas, no funciona para los nombres de las tablas.
SELECT 
 BirthDate = e.BirthDate 
 , BusinessEntityIDemployee = e.BusinessEntityID 
 , CurrentFlag = e.CurrentFlag 
 , BusinessEntityIDperson = p.BusinessEntityID 
FROM HumanResources.Employee AS e
    INNER JOIN Person.Person AS p 
    ON e.BusinessEntityID = p.BusinessEntityID
ORDER BY p.LastName

Para la opción 2 es posible que exista un poco de confusión al momento de leer la consulta en caso de que no especifiquemos un alias para el nombre de la tabla, ejemplo:
SELECT 
BirthDate MaritalStatus , 
MaritalStatus BirthDate ,
*  
FROM HumanResources.Employee


Como podemos observar, ya existen las columnas MaritalStatus y BirthDate, y aun así SQL SERVER nos permite renombrar tablas con nombres de columnas ya existentes en la tabla original, una vez ejecutada la consulta podemos deducir que la columna es la de la izquierda y el ALIAS el de la derecha.

Sucede de la misma manera usando el símbolo =, ya una vez ejecutada la consulta podemos llegar a la conclusión que la tabla es la de la derecha que es asignada a un ALIAS de la izquierda del símbolo =
SELECT 
BirthDate = MaritalStatus , 
MaritalStatus = BirthDate ,
*  
FROM HumanResources.Employee

Usando la palabra reservada ya sabemos y tenemos la certeza que la columna es la de la izquierda a AS y el nuevo nombre es la derecha.

Espero que con estos pequeños consejos puedan decidir cual es la mejor opción para ustedes y tomarlas en cuenta al momento de realizar sus consultas.

SALUDOS!