Вы находитесь на странице: 1из 140

/*---------------------------------------

Profesor: Ing. F. Erick Tamayo


E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 2 TSQL
---------------------------------------*/

/*

Repasar...

___.___ ~ _____________
\ \\ \ ,, ??? | '\\\\\\
\ \\ \ /< ? | ' ____|_
--\//,- \_. /_____ | '||::::::
o- / \_/ '\ | '||_____|
| \ ' o \'________|_____|
| )- # < ___/____|___\___
`_/'------------| _ ' <<<:|
/________\| |_________'___o_o|

*/

--Crear la Base de Datos Empresa7

CREATE DATABASE Empresa7


ON PRIMARY(
NAME=Empresa7_data,
FILENAME='C:\Datos\Empresa7.mdf',
SIZE=10 MB,
MAXSIZE=30 MB,
FILEGROWTH=2 mb
)

LOG ON(
NAME=Empresa7_log,
FILENAME='C:\Datos\Empresa7.ldf',
SIZE=4 MB,
MAXSIZE=12 MB,
FILEGROWTH=1 mb
)
GO

--Usar la Base de Datos Empresa7


Use Empresa7
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

/*Creaci�n de Constraints (Restricciones)


1- Primary Key (PK)
2- Unique (UN)
3- Foreign Key (FK)
4- Check (CK)
5- Default (DF)
*/

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

------------------------------------------------
-- (1) Restricci�n: PRIMARY KEY
------------------------------------------------

-- Creaci�n de la Tabla Cliente


CREATE TABLE Cliente(
IdCliente CHAR(5) NOT NULL,
Nombre VARCHAR(40) NOT NULL,
Ruc CHAR(11) NOT NULL,
)
GO

-- Creaci�n de la Restricci�n de Clave Primaria en la Tabla Cliente


ALTER TABLE Cliente
ADD CONSTRAINT PK_Cliente_IdCliente
PRIMARY KEY (IdCliente)
GO

-- Utilizar el procedimiento del sistema Sp_HelpConstraint


EXECUTE Sp_Helpconstraint Cliente
GO

-- Crear la Tabla Producto y crear la Clave Primaria directamente


CREATE TABLE Producto(
IDProducto CHAR(5) NOT NULL PRIMARY KEY,
Nombre VARCHAR(20) NOT NULL,
Precio DECIMAL (8,2) NOT NULL
)
GO

-- Utilizar el procedimiento del sistema Sp_HelpConstraint.


-- Observe el nombre del Constraint
EXEC Sp_HelpConstraint Producto
GO

--Ingresar registros a la Tabla Cliente.


--No dejar� ingresar repetidos al Campo IDCliente ya que es PK
--Pero s� deja ingresar repetidos en el resto de columnas
--Note adem�s las tres maneras que utilizo para ingresar registros

INSERT INTO Cliente(IdCliente, Nombre, Ruc)


VALUES ('C0001', 'Comercial Alpha', '12345678901')
GO

INSERT Cliente(IdCliente, Nombre, Ruc)


VALUES ('C0002', 'Comercial Alpha', '12345678901')
GO
INSERT Cliente
VALUES ('C0003', 'Comercial Alpha', '12345678901')
GO

SELECT * FROM Cliente


GO

--Borremos el segundo y tercer registro


DELETE FROM Cliente
WHERE IDCliente='C0002' OR IDCliente='C0003'
GO

--No te olvides de poner el Where en el Delete From!

SELECT * FROM Cliente


GO

------------------------------------------------
-- (2) Restricci�n: UNIQUE
------------------------------------------------

/*Crear la Restricci�n UNIQUE en la Tabla Cliente


Se desea que el nombre del cliente no se repita*/

ALTER TABLE Cliente


ADD CONSTRAINT UN_Cliente_Nombre
UNIQUE (Nombre)
GO

-- Veo los constraints de la Tabla Cliente


Sp_HelpConstraint Cliente
GO

-- Pruebo el error
INSERT Cliente(IdCliente, Nombre, Ruc)
VALUES ('C0002', 'Comercial Alpha', '12345678902')
GO

-- Inserto registro v�lido


INSERT Cliente(IdCliente, Nombre, Ruc)
VALUES ('C0002', 'Comercial Beta', '12345678902')
GO

SELECT * FROM Cliente


GO

-- Crear ahora una restricci�n para el RUC


ALTER TABLE Cliente
ADD CONSTRAINT UN_Cliente_Ruc
UNIQUE (Ruc)
GO

-- Veo los constraints de la Tabla Cliente


Sp_HelpConstraint Cliente
GO
-- Pruebo el error
INSERT Cliente(IDCliente, Nombre, Ruc)
VALUES ('C0003', 'Comercial Gamma', '12345678902')
GO

-- Inserto registro v�lido


INSERT Cliente(IDCliente, Nombre, Ruc)
VALUES ('C0003', 'Comercial Gamma', '12345678903')
GO

SELECT * FROM Cliente


GO

-- Crear la Tabla L�nea


-- El c�digo de la L�nea (IdLinea) se debe autogenerar
-- Para ello utilizo la propiedad IDENTITY

CREATE TABLE Linea(


IDLinea INT NOT NULL IDENTITY,
Nombre VARCHAR(30) NOT NULL
)
GO

ALTER TABLE Linea


ADD CONSTRAINT PK_Linea_IdLinea
PRIMARY KEY (IdLinea)
GO

-- Insertando 4 registros
INSERT Linea (Nombre)
VALUES ('Frutas')

INSERT Linea (Nombre)


VALUES ('Bebidas')

INSERT Linea (Nombre)


VALUES ('L�cteos')

INSERT Linea (Nombre)


VALUES ('Embutidos')
GO

-- Veo los constraints de la Tabla Linea


Sp_HelpConstraint Linea
GO

SELECT * FROM Linea


GO

------------------------------------------------
-- (3) Restricci�n: FOREIGN KEY
------------------------------------------------
-- A�adiremos el Campo Linea a la Tabla PRODUCTO
ALTER TABLE Producto
ADD Linea INT NOT NULL
GO

SELECT * FROM Producto


GO

-- Creaci�n de la Clave For�nea en la Tabla PRODUCTO


-- El campo elegido como FK es Linea
-- Dicho campo har� referencia al PK de la Tabla LINEA (IdLinea)

ALTER TABLE Producto


ADD CONSTRAINT FK_Producto_Linea
FOREIGN KEY (Linea)
REFERENCES Linea (IdLinea)
GO

-- Comprobamos si la conexi�n fue realizada


Sp_HelpConstraint Linea
GO

-- Insertar filas a la Tabla Producto

-- �xito
INSERT Producto(IDProducto, Nombre, Precio, Linea)
VALUES ('P0001', 'Sand�a', 3, 1)
GO

SELECT * FROM Producto


GO

-- Error, debido a que la L�nea de tipo 5 no existe


INSERT Producto(IDProducto, Nombre, Precio, Linea)
VALUES ('P0002', 'Jamonada', 2, 5)
GO

-- �xito
INSERT Producto(IDProducto, Nombre, Precio, Linea)
VALUES ('P0002', 'Jamonada', 2, 4)
GO

SELECT * FROM PRODUCTO


GO

------------------------------------------------
-- (4) Restricci�n: CHECK
------------------------------------------------

-- Creaci�n de la Restricci�n CHECK


-- IDProducto debe estar en el rango P0001-P9999 y no puede ser de c�digo P0000

ALTER TABLE Producto


ADD CONSTRAINT CK_Producto_IdProducto
CHECK(IDProducto LIKE 'P[0-9][0-9][0-9][0-9]' AND IdProducto<>'P0000')
GO

-- Veo los constraints de la Tabla Producto


Sp_HelpConstraint Producto
GO

-- Error
INSERT Producto(IdProducto, Nombre, Precio, Linea)
VALUES ('A', 'Yogurt', 7, 3)
GO

-- Error
INSERT Producto(IdProducto, Nombre, Precio, Linea)
VALUES ('P0000', 'Yogurt', 7, 3)
GO

-- �xito
INSERT Producto(IdProducto, Nombre, Precio, Linea)
VALUES ('P0003', 'Yogurt', 7, 3)
GO

SELECT * FROM Producto


GO

-- Las cantidades no pueden ser negativas


INSERT Producto(IdProducto, Nombre, Precio, Linea)
VALUES ('P0004', 'Fanta', -5, 2)
GO

-- Permiti� ingresar el registro, lo cual nunca debi� suceder


SELECT * FROM Producto
GO

-- Borremos el producto P0004


DELETE FROM Producto
WHERE IdProducto='P0004'
GO

SELECT * FROM PRODUCTO


GO

-- Creando la restricci�n CHECK que no admitir� cantidades negativas ni cero


ALTER TABLE Producto
ADD CONSTRAINT CK_Producto_Precio
CHECK (Precio>0)
GO

-- Error
INSERT Producto(IdProducto, Nombre, Precio, Linea)
VALUES ('P0004', 'Fanta', -5, 2)
GO

-- �xito
INSERT Producto(IdProducto, Nombre, Precio, Linea)
VALUES ('P0004', 'Fanta', 5, 2)
GO
SELECT * FROM Producto
GO

-- Crear la Tabla Pedido con las FK al paso


CREATE TABLE Pedido(
IdPedido CHAR(7) NOT NULL PRIMARY KEY,
Cliente CHAR(5) NOT NULL REFERENCES Cliente(IdCliente),
Producto CHAR (5) NOT NULL REFERENCES Producto(IdProducto),
Cantidad INT,
Fecha_Pedido DATE NOT NULL,
Fecha_Entrega DATE,
)
GO

SELECT * FROM Pedido


GO

-- Recordemos los registros tenemos en Producto y Cliente


SELECT * FROM Producto
SELECT * FROM Cliente
GO

--Si su Sql Server no se lo permite (versi�n en ingl�s)


--puede configurar el ingreso de fechas como D/M/Y (D�a/Mes/A�o)
SET DATEFORMAT DMY
GO

--Probando la Integridad Referencial

--Falla el FK con la Tabla Cliente debido a que no existe el Cliente C0009


INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00001', 'C0009', 'P0009', 200, '25-03-2017', '28-03-2017')
GO

--Falla el FK con la Tabla Producto debido a que no existe el Producto P0009


INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00001', 'C0001', 'P0009', 200, '25-03-2017', '28-03-2017')
GO

-- �xito
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00001', 'C0001', 'P0003', 200, '25-03-2017', '28-03-2017')
GO

SELECT * FROM Pedido


GO

--En el caso de Fechas existe la norma ISO 8601


--"Data elements and interchange formats � Information interchange � Representation
of dates and times"
--Indica especificar en orden primeramente los per�odos de tiempo m�s largos y
posteriormente los m�s cortos.
--Para una fecha ir�a primero el a�o, luego el mes y a continuaci�n el d�a.
--Ejemplo, para 30 de mayo de 2017 la notaci�n ser�a 2017-05-30.
-- Si ingreso como Fecha_Entrega una fecha anterior a Fecha_Pedido, me permite
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00002', 'C0003', 'P0004', 30, '28-03-2017', '30-03-2000')
GO

--Eso jam�s debi� suceder, pero en la Tabla Pedido ya figura como un registro
v�lido.
SELECT * FROM Pedido
GO

-- Borrar el segundo pedido y crear la restricci�n respectiva


DELETE FROM Pedido
WHERE IdPedido='PX00002'
GO

SELECT * FROM Pedido


GO

-- Crear la restricci�n que prohiba que una Fecha_Entrega sea anterior a


Fecha_Pedido
ALTER TABLE Pedido
ADD CONSTRAINT CK_Pedido_Fecha_Entrega
CHECK(Fecha_Pedido<Fecha_Entrega)
GO

-- Error
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00002', 'C0003', 'P0004', 30, '28-03-2017', '30-03-2000')
GO

-- �xito
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00002', 'C0003', 'P0004', 30, '28-03-2017', '30-03-2017')
GO

SELECT * FROM Pedido


GO

-- Modificar la restricci�n. Que permita que la Fecha_Entrega


-- tambi�n pueda ser el mismo d�a que Fecha_Pedido

-- Una restricci�n no se puede editar.


-- Se borra y se vuelve a crear.

ALTER TABLE Pedido


DROP CONSTRAINT CK_Pedido_Fecha_Entrega
GO

-- Comprobamos que dicho constraint fue eliminado


Sp_HelpConstraint Pedido
GO

-- Creamos el nuevo constraint


ALTER TABLE Pedido
ADD CONSTRAINT CK_Pedido_Fecha_Entrega
CHECK(Fecha_Pedido<=Fecha_Entrega)
GO

-- Creamos el nuevo constraint


Sp_HelpConstraint Pedido
GO

-- �xito
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00003', 'C0002', 'P0002', 7, '01-04-2017', '01-04-2017')
GO

SELECT * FROM Pedido


GO

-- Nota: Las fechas pueden ingresarse como 01-04-2017, 01/04/2017 � 01.04.2017


-- es decir, usando como separadores: - (gui�n) / (barra) . (punto)

--Para cualquier pedido, la cantidad debe ser positiva y no puede pasar de 300

ALTER TABLE Pedido


ADD CONSTRAINT CK_Pedido_Cantidad
CHECK (Cantidad BETWEEN 1 AND 300)
GO

Sp_HelpConstraint Pedido
GO

-- Error
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00004', 'C0003', 'P0001', 800, '02/04/2017', '04/04/2017')
GO

-- Error
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00004', 'C0003', 'P0001', 0, '02/04/2017', '04/04/2017')
GO

-- �xito
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00004', 'C0003', 'P0001', 250, '02/04/2017', '04/04/2017')
GO

SELECT * FROM Pedido


GO

-- Fecha_pedido tiene que ser el d�a de hoy o antes, nunca despu�s


--La Funci�n GETTDATE() representa la fecha actual del sistema, la fecha de HOY
ALTER TABLE Pedido
ADD CONSTRAINT CK_Pedido_Fecha_Pedido
CHECK (Fecha_Pedido<=GETDATE())
GO

Sp_HelpConstraint Pedido
GO
-- Error
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00005', 'C0001', 'P0004', 19, '03.04.2020', '05.04.2017')
GO

-- �xito
INSERT Pedido(IDPedido, Cliente, Producto, Cantidad, Fecha_Pedido, Fecha_Entrega)
VALUES('PX00005', 'C0001', 'P0004', 19, '03.04.2017', '05.04.2017')
GO

SELECT * FROM Pedido


GO

------------------------------------------------
-- (5) Restricci�n: DEFAULT
------------------------------------------------

-- Crear la Tabla Empleado


-- El PK debe ser IDENTITY e ir de 3 en 3 a partir de 10

CREATE TABLE Empleado(


IdEmpleado INT IDENTITY(10, 3) NOT NULL PRIMARY KEY,
Nombre VARCHAR(30) NOT NULL,
Ubicacion VARCHAR(30) NOT NULL
)
GO

Sp_HelpConstraint Empleado
GO

SELECT * FROM Empleado


GO

-- Ingresando un par de registros


INSERT Empleado(Nombre, Ubicacion)
VALUES ('Juan', 'Lima')

INSERT Empleado
VALUES ('Rosa', 'Cuzco')
GO

SELECT * FROM Empleado


GO

-- A�adiendo la restricci�n DEFAULT


ALTER TABLE Empleado
ADD CONSTRAINT DF_Empleado_Ubicacion
DEFAULT 'Lima' FOR Ubicacion
GO

Sp_HelpConstraint Empleado
GO

-- Insertando 4 registros m�s


INSERT Empleado (Nombre)
VALUES ('Pamela')
INSERT Empleado (Nombre)
VALUES ('Luis')

INSERT Empleado (Nombre)


VALUES ('Brenda')

INSERT Empleado (Nombre)


VALUES ('Aaron')
GO

SELECT * FROM Empleado


GO

-- Modifique la ubicaci�n de Aaron a Tacna


UPDATE Empleado
SET Ubicacion='Tacna'
WHERE IdEmpleado='25'
GO

SELECT * FROM Empleado


GO

--Si deseo insertar a un Empleado con una ubicaci�n diferente


--a la ubicaci�n por defecto
INSERT Empleado (Nombre, Ubicacion)
VALUES ('Kathy', 'Arequipa')
GO

SELECT * FROM Empleado


GO

-- Notas

-- Nota 1: Es MUY recomendable no crear PK's y FK's "al paso", es decir, al lado de
la columna.
-- Es mejor crear la tabla en un primer paso.
-- Luego con un ALTER se agregan los Pk's y FK's necesarios.
-- Nota 2: IDENTITY para PK tiene ventajas/desventajas. Abierto a debate e
investigaci�n.
-- Nota 3: Us� el tipo de dato Date en lugar de Datetime para tener s�lo fechas y
no fechas con horas.
-- Nota 4: Siempre es bueno nombrar restricciones con prefijos adecuados
-- PK, UN, FK, CK, DF
-- Nota 5: Los constraints no se modifican, se borran y se vuelven a crear.

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 3 TSQL
---------------------------------------*/

/*

___.___ ~ _____________
\ \\ \ ,, ??? | '\\\\\\
\ \\ \ /< ? | ' ____|_
--\//,- \_. /_____ | '||::::::
o- / \_/ '\ | '||_____|
| \ ' o \'________|_____|
| )- # < ___/____|___\___
`_/'------------| _ ' <<<:|
/________\| |_________'___o_o|

*/

--01 Ver todas las Bases de Datos alojadas en nuestro servidor

sp_helpdb
GO

--02 Usar la Base de Datos Northwind y dar un listado de todos los Clientes

USE Northwind
GO

SELECT * FROM Customers


GO

--03 Con el listado de todos los clientes, mostrar s�lo


-- las columnas CustomerID, CompanyName y Country

SELECT CustomerID, CompanyName, Country


FROM Customers
GO

--04 La Consulta anterior, pero usando un Alias para cada Columna

--Usando AS
SELECT CustomerID AS C�digo, CompanyName AS Empresa, Country AS 'Pa�s de Origen'
FROM Customers
GO

--Sin usar AS
SELECT CustomerID C�digo, CompanyName Empresa, Country 'Pa�s de Origen'
FROM Customers
GO

--Algunos prefieren usar siempre '' con los Alias para que SSMS asigne un color
distintivo
SELECT CustomerID 'C�digo', CompanyName 'Empresa', Country 'Pa�s de Origen'
FROM Customers
GO

--05 Listado de todas las �rdenes (Pedidos)


SELECT * FROM Orders --830 filas
GO

--06 Listado de todos los Detalles de �rdenes

SELECT * FROM [Order Details] --2155 filas


GO

/*
Campo calculado:
---------------
Es un campo virtual, no existe f�sicamente en una Tabla.
Se obtiene como resultado de una expresi�n y est� basado
en otros campos almacenados f�sicamente en una o varias tablas.
*/

--07 Hallar el Precio con IGV (18%) en Products

SELECT ProductID, ProductName, UnitPrice FROM Products


GO

SELECT ProductID, ProductName, UnitPrice,


UnitPrice*1.18 AS 'Precio con IGV'
FROM Products
GO

--08 Hallar el Subtotal (por fila) en Order Details

SELECT * FROM [Order Details]


GO

-- Subtotal: Precio * Cantidad


SELECT *, UnitPrice*Quantity AS 'Subtotal'
FROM [Order Details]
GO

-- 09 Hallar el Monto del Descuento.

-- Tenga en cuenta que no se puede crear un campo calculado


-- en base a otro campo calculado.

/* La columna Discount son porcentajes expresados en decimales


0.80 = 80%
0.37 = 37%
0.15 = 15%
0.05 = 5%
...etc
*/

-- Monto del Dscto: Subtotal * Descuento


-- Monto del Dscto: (Precio*Cantidad)*Descuento
SELECT *,
UnitPrice*Quantity AS 'Subtotal',
UnitPrice*Quantity*Discount AS 'Monto del Dscto'
FROM [Order Details]
GO

--10 Trabajando con la Consulta 09, agregar el Neto


-- (Factorizar, si es necesario)

-- Neto: Subtotal - Monto del Dscto


-- Neto: (Precio*Cantidad) - (Precio*Cantidad)*Descuento
-- Neto: Precio*Cantidad*(1-Descuento)

SELECT *,
UnitPrice*Quantity AS 'Subtotal',
UnitPrice*Quantity*Discount AS 'Monto del Dscto' ,
UnitPrice*Quantity*(1-Discount) AS 'Neto'
FROM [Order Details]
GO

--11 Realizar la Consulta 10 considerando el IGV y el Neto con IGV


-- LLame a las dos nuevas columnas IGV y Monto Total (para el c�lculo final)

-- IGV: Neto * 0.18


-- Monto Total: Neto * 1.18 (ya que es el Neto + IGV)

SELECT *,
UnitPrice*Quantity AS 'Subtotal',
UnitPrice*Quantity*Discount AS 'Monto del Dscto' ,
UnitPrice*Quantity*(1-Discount) AS 'Neto',
UnitPrice*Quantity*(1-Discount)*0.18 AS 'IGV',
UnitPrice*Quantity*(1-Discount)*1.18 AS 'Monto Total'
FROM [Order Details]
GO

-- CL�USULA WHERE
--------------

--12 Listado de Clientes de M�xico

SELECT * FROM Customers


WHERE Country='Mexico'
GO

--13 Listado de Productos con Precio Unitario Mayor a 30

SELECT * FROM Products


WHERE UnitPrice>30
GO
-- OPERADOR AND
------------

--14 Listado de Productos con Precio Unitario de 20 a 30

SELECT * FROM Products


WHERE UnitPrice>=20 AND UnitPrice<=30
GO

--15 Listado de Proveedores de Reino Unido (Uk) que operen en Londres (London)

SELECT * FROM Suppliers


WHERE Country = 'Uk' AND City = 'London'
GO

-- OPERADOR OR
-----------

--16 Listado de Clientes de M�xico, Argentina y Suecia

SELECT * FROM Customers


WHERE Country='Mexico' OR Country='Argentina' OR Country='Sweden'
GO

--17 Listado de Productos con precio menor a 5 y mayor a 100


SELECT * FROM Products
WHERE Unitprice <=5 OR Unitprice >=100
GO

-- Usando AND y OR al mismo tiempo


-------------------------------

--18 Listar aquellos clientes con los cuales el trato es directo con el due�o
-- para los pa�ses de Venezuela o Francia (France)

SELECT * FROM Customers


WHERE ContactTitle='Owner' AND (Country='Venezuela' OR Country='France')
GO

-- OPERADOR BETWEEN
----------------

--19 Listado de Productos con Precio Unitario entre 20 y 30


SELECT * FROM Products
WHERE UnitPrice BETWEEN 20 and 30
GO

-- Nota: BETWEEN incluye los extremos


-- OPERADOR IN
-----------

--20 Listado de Productos que pertenezcan a la Categor�a 1, 2, 3 y 4

-- Forma 1
SELECT * FROM Products
WHERE CategoryID='1' OR CategoryID='2' OR CategoryID='3' OR CategoryID='4'
GO

-- Forma 2
SELECT * FROM Products
WHERE CategoryID BETWEEN 1 and 4
GO

-- Forma 3
SELECT * FROM Products
WHERE CategoryID IN (1,2,3,4)
GO

--�Cu�l es la ventaja del IN frente a BETWEEN?


-- Rpta: Con IN puedo elegir elementos que no necesariamente
-- sean consecutivos

-- WILDCARDS
-----------
-- (Manejando b�squedas de registros mediante caracteres)

--21 Crear la sgte Tabla Temporal


CREATE TABLE #PRODUCTOS(
ID INT IDENTITY NOT NULL,
NOMBRE VARCHAR(50)
)
GO

-- Comprobamos su creaci�n
SELECT * FROM #PRODUCTOS
GO

-- Insertamos 4 productos
INSERT #PRODUCTOS
VALUES
('HELADO NESTLE'),
('LECHE NESTLE'),
('YOGURT NESTLE 1 LITRO'),
('NESTLE PACK (HELADO, LECHE, YOGURT)')
GO

--Revisando los registros


SELECT * FROM #PRODUCTOS
GO

-- a) Registro que exactamente diga NESTLE


SELECT * FROM #PRODUCTOS
WHERE NOMBRE LIKE 'NESTLE' --0 filas
GO

-- b) Registro que diga NESTLE al inicio


SELECT * FROM #PRODUCTOS
WHERE NOMBRE LIKE 'NESTLE%' --1 fila
GO

-- c) Registro que diga NESTLE al final


SELECT * FROM #PRODUCTOS
WHERE NOMBRE LIKE '%NESTLE' --2 filas
GO

-- d) Registro que diga NESTLE en cualquier posici�n


SELECT * FROM #PRODUCTOS
WHERE NOMBRE LIKE '%NESTLE%' --4 filas
GO

/*TABLA DE COMODINES (Wildcards)


------------------
% CERO O M�S CARACTERES
_ UN �NICO CARACTER
[LISTA] CUALQUIER CARACTER INCLUIDO EN LA LISTA
[^LISTA] o [!LISTA] CUALQUIER CARACTER NO INCLUIDO EN LA LISTA
[X1-XN] CUALQUIER CARACTER INCLUIDO EN DICHA SUCESI�N

*/

--22 Listado de Clientes que tengan como Primer Caracter la Letra A en el Nombre

SELECT * FROM Customers


WHERE CompanyName LIKE 'A%'
GO

--23 Listado de Clientes que tengan como �ltimo Caracter la Letra A en el Nombre

SELECT * FROM Customers


WHERE CompanyName LIKE '%A'
GO

--24 Listado de Clientes que tengan como Primer y �ltimo Caracter


-- la letra A en el Nombre

SELECT * FROM Customers


WHERE CompanyName LIKE 'A%A'
GO

--25 Listado de Clientes que tengan como Tercer caracter la Letra A en el Nombre

SELECT * FROM Customers


WHERE CompanyName LIKE '__A%'
GO

--26 Listado de Clientes que tengan como Primer caracter en el Nombre


-- las letras A,B,C,E,F

SELECT * FROM Customers


WHERE CompanyName LIKE '[ABCEF]%'
GO

--27 Listado de Clientes que tengan como Primer caracter en el Nombre


-- las letras A,B,C,D,E,F

SELECT * FROM Customers


WHERE CompanyName LIKE '[A-F]%'
GO

--28 Listado de Clientes que NO tengan como Primer caracter en el Nombre


-- las letras A,B,C,E,F

SELECT * FROM Customers


WHERE CompanyName LIKE'[^ABCEF]%'
GO

--29 Listado de Clientes que NO tengan como Primer caracter en el Nombre


-- las letras A,B,C,D,E,F

SELECT * FROM Customers


WHERE CompanyName LIKE'[^A-F]%'
GO

--30 Listado de Clientes con Primer Caracter la letra H y termine en Vocal

SELECT * FROM Customers


WHERE CompanyName LIKE'H%[AEIOU]'
GO

-- CONCATENANDO CAMPOS
-------------------

--31 Listado de Empleados.


-- Mostrar el C�digo de Empleado,
-- el Nombre y el Apellido (como una sola columna),
-- la Fecha de Nacimiento y la Fecha de Contrato

SELECT
EmployeeID,
FirstName+' '+LastName AS 'Nombre Completo',
BirthDate, HireDate
FROM Employees
GO

-- CL�USULA ORDER BY
-----------------

--32 Listar los productos empezando por los m�s baratos

SELECT * FROM Products


ORDER BY UnitPrice ASC
GO

-- ORDER BY por defecto trabaja ascendentemente y no es necesario ASC


SELECT * FROM Products
ORDER BY UnitPrice
GO

--33 Listar los productos empezando por los m�s caros


-- Agrego DESC para obtener un orden descendente en dicha columna
SELECT * FROM Products
ORDER BY UnitPrice DESC
GO

-- CL�USULA TOP
------------

--34 Ver s�lo las 10 primeras �rdenes

SELECT * FROM Orders


GO

SELECT TOP 10 * FROM Orders


GO

--35 Ver los 3 productos m�s caros

SELECT TOP 3 * FROM Products


ORDER BY UnitPrice DESC
GO

--36 Mostrar los 2 productos m�s baratos

SELECT TOP 2 * FROM Products


ORDER BY UnitPrice
GO -- Los precios son 2.50 y 4.50
--37 Caso:
-----
-- �Qu� pasar�a si el 2do lugar fuera ocupado por varios registros?
-- Veamos primero las 5 primeras posiciones

SELECT TOP 5 * FROM Products


ORDER BY UnitPrice
GO

-- Haremos que el 3er, 4to y 5to resultado tengan el


-- mismo precio que el 2do resultado
UPDATE Products
SET UnitPrice=4.5
WHERE ProductID IN (13,52,54)
GO

-- Si ejecuto un TOP 2 para los 2 precios m�s bajos


SELECT TOP 2 * FROM Products
ORDER BY UnitPrice
GO

-- Sabemos que 4 registros comparten el segundo lugar y que todos ellos no han sido
mostrados.
-- Hag�moslo con empates

-- USANDO WITH TIES


----------------

SELECT TOP 2 WITH TIES * FROM Products


ORDER BY UnitPrice
GO

-- Reestableciendo los valores originales en la Tabla Products


UPDATE Products
SET UnitPrice=6
WHERE ProductID=13

UPDATE Products
SET UnitPrice=7
WHERE ProductID=52

UPDATE Products
SET UnitPrice=7.45
WHERE ProductID=54
GO

SELECT TOP 5 * FROM Products


ORDER BY UnitPrice
GO

----------------------------
-- CL�USULA SELECT DISTINCT
----------------------------
-- 38 Usando Distinct (muestra valores sin repeticiones)
-- Mostrar la lista �nica de Pa�ses de todos nuestros Clientes

SELECT DISTINCT Country FROM Customers --21 filas/21 Pa�ses


GO

--39 Mostrar la lista �nica de Pa�ses con Ciudades de todos nuestros Clientes

SELECT * FROM Customers --91 filas


GO

SELECT Country, City --91 filas


FROM Customers
ORDER BY Country
GO

SELECT DISTINCT Country, City --69 filas


FROM Customers
GO

----------------------------------
-- FUNCIONES MATEM�TICAS --
----------------------------------

----------------------
-- Funci�n ROUND
----------------------

-- 40 Funci�n ROUND (Redondea)

SELECT ROUND(120.549,2) --Redondea a 2 decimales


GO

SELECT ROUND(120.549,0) --Redondea a 0 decimales


GO

SELECT ROUND(3.14159265,4) --Redondea a 4 decimales


GO

------------------------------
-- Funciones CEILING y FLOOR
------------------------------

-- 41 Funci�n Ceiling
-- (Aproxima forzosamente al entero m�s pr�ximo, mayor)

SELECT CEILING(2.11) --Ser�a 3


GO

SELECT CEILING(7.03) --Ser�a 8


GO
--42 Funci�n Floor
-- (Aproxima forzosamente al entero m�s proximo, menor)

SELECT FLOOR(15.98) --Ser�a 15


GO

SELECT FLOOR(4.79) --Ser�a 4


GO

----------------------
-- Funci�n RAND
----------------------

--43 Funci�n RAND


SELECT RAND() --N�mero aleatorio entre 0 y 1
GO

SELECT RAND()*10 --N�mero aleatorio entre 0 y 10


GO

SELECT RAND()*500 --N�mero aleatorio entre 0 y 500


GO

--44 N�mero aleatorio entero entre 1 y 5


SELECT FLOOR(RAND()*5+1)
GO

--45 N�mero aleatorio entero entre 1 y 70


SELECT FLOOR(RAND()*70+1)
GO

-------------------
-- Funci�n ABS
-------------------

--46 Funci�n ABS (Valor Absoluto)

SELECT ABS(4-6) --Ser�a 2


GO

----------------------
-- Funci�n POWER
----------------------

--47 Funci�n POWER (Eleva a una potencia)


SELECT POWER(3,5) --Ser�a 243
GO

----------------------
-- Funci�n SQRT
----------------------

--48 Funci�n SQRT (Ra�z Cuadrada)

SELECT SQRT(16) --Ser�a 4


GO

----------------------
-- Funci�n SIGN
----------------------

--49 Funci�n SIGN (Muestra el Signo de un n�mero)

SELECT SIGN(30) --Resultado es 1, por ser un n�mero de signo positivo


GO

SELECT SIGN(0) --Resultado es 0, por ser el n�mero cero


GO

SELECT SIGN(-7) --Resultado es -1, por ser un n�mero de signo negativo


GO

-------------------------------
-- Funciones LOG, LOG10 y PI
-------------------------------

--50 Funci�n LOG


-- (Obtiene el Logaritmo Neperiano)
SELECT LOG(100) AS 'Log. Neperiano'
GO

--51 Funci�n LOG10


-- (Obtiene el Logaritmo Decimal)
SELECT LOG10(100) AS 'Log. Decimal'
GO

--52 Funci�n PI
SELECT PI() AS 'Valor de PI'
GO

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 4 TSQL
---------------------------------------*/

/*

___.___ ~ _____________
\ \\ \ ,, ??? | '\\\\\\
\ \\ \ /< ? | ' ____|_
--\//,- \_. /_____ | '||::::::
o- / \_/ '\ | '||_____|
| \ ' o \'________|_____|
| )- # < ___/____|___\___
`_/'------------| _ ' <<<:|
/________\| |_________'___o_o|

*/

--1 Probando Char vs Varchar


CREATE TABLE #Tabla (
A VARCHAR(10),
B CHAR(10)
)
GO

INSERT #Tabla
VALUES ('Hola', 'Unac')
GO

SELECT A+'*' AS 'Con Varchar',


B+'*' AS 'Con Char'
FROM #Tabla
GO -- Note la diferencia

--2 Crear la sgte Tabla Temporal

CREATE TABLE #Venta(


ID INT IDENTITY,
Cliente VARCHAR(40),
Producto VARCHAR(40),
Fecha DATE,
Accesorio VARCHAR(40)
)
GO

--Vemos el Idioma de nuestro Sql Server


Select @@Language
GO
--De no estar en Espa�ol
SET LANGUAGE Spanish
GO

--Al estar en Espa�ol ya podemos ingresar fechas en formato D�a/Mes/A�o

--Tambi�n se puede establecer el ingreso de fechas como D�a/Mes/A�o


SET DATEFORMAT DMY
GO

--Insertamos 7 ventas
INSERT #Venta
VALUES
('Carla', 'Dvd', '11/04/2017', 'Adaptador'),
('David', 'Equipo', '12/04/2017', 'Cd'),
('Sandra', 'Equipo', '12/04/2017', NULL),
('Jenny', 'Laptop', '12/04/2017', 'Cargador'),
('Alberto', 'Dvd', '13/04/2017', NULL),
('Carla', 'Impresora', '13/04/2017', NULL),
('Sandra', 'Web-cam', '14/04/2017', NULL)
GO

--Verificamos
SELECT * FROM #Venta
GO

-------------------------------------
-- B�squedas de Nulos y No Nulos
-------------------------------------

--3 Busquemos aquellos productos que no tienen accesorios.


SELECT * FROM #Venta
WHERE Accesorio = NULL --Incorrecto!
GO

--Tenga en cuenta que NULL no significa Vac�o

-- NULL es un estado
-- NULL significa que el valor de los datos de la columna no se conoce

-- Adem�s, un NULL es diferente a otro NULL


-- Por esa raz�n un NULL no se compara
-- No tendremos por ejemplo si Precio=Null

SELECT * FROM #Venta


WHERE Accesorio IS NULL --Correcta b�squeda de valores Null
GO

-- Los Null nunca se comparan, s�lo se pregunta si es Null o no es Null

SELECT * FROM #Venta


WHERE Accesorio is NOT NULL --Correcta b�squeda de valores No Null
GO
--------------------------------------
-- FUNCIONES DE CONVERSI�N --
--------------------------------------

--------------------------
-- Funci�n CONVERT y CAST
--------------------------

--4 Insertando Fechas en cadenas de Texto


-- Uso de CONVERT y CAST

-- Intento
SELECT 'Fecha Venta: ' + Fecha
FROM #Venta
GO

-- �xito
SELECT
'Fecha Venta: ' + CONVERT(CHAR (10), Fecha) AS 'Usando Convert',
'Fecha Venta: ' + CAST(Fecha AS CHAR (10)) AS 'Usando Cast'
FROM #Venta
GO

--5 Usando Convert con el par�metro Style

--Fecha Actual
SELECT CONVERT(CHAR(10), GetDate(), 103)
GO

--Columna Fecha
SELECT
'Fecha Venta: ' + CONVERT(CHAR (10), Fecha, 103) AS 'Convert con Style 103'
FROM #Venta
GO

-- 103 es el valor del par�metro "Style" de la funci�n CONVERT

-- 103 para dd/mm/aaaa


-- 104 para dd.mm.aaaa
-- 105 para dd-mm-aaaa

--------------------------------
-- FUNCIONES DE FECHA --
--------------------------------

---------------------
-- Funci�n GETDATE
---------------------
--6 Devuelve la fecha actual
SELECT GETDATE()
GO

PRINT GETDATE()
GO

-----------------------------
-- Funci�n YEAR, MONTH, DAY
-----------------------------

--7 Devuelve el A�o actual


PRINT YEAR(GETDATE())
GO

--8 Devuelve el Mes actual


PRINT MONTH(GETDATE())
GO

--9 Devuelve el D�a actual


PRINT DAY(GETDATE())
GO

--Ejecute su c�digo de creaci�n de Northwind nuevamente


--para anular cambios realizados con anterioridad

--Active Northwind
USE Northwind
GO

--10 Listar �rdenes realizadas en el A�o 1997

SELECT * FROM Orders


WHERE YEAR(OrderDate)=1997
GO

--11 Listado de �rdenes realizadas en el mes de Agosto del a�o 1997

SELECT * FROM Orders


WHERE YEAR(OrderDate)=1997 AND MONTH(OrderDate)=08
GO

--12 Listado de �rdenes efectuadas en la Primera Quincena


-- del mes de Enero del a�o 1998 con excepci�n de los
-- tres primeros d�as del mes
SELECT * FROM Orders
WHERE YEAR(OrderDate)=1998
AND MONTH(OrderDate)=01
AND DAY(OrderDate) BETWEEN 4 AND 15
GO

--13 Veamos la lista de Idiomas de SQL Server


Sp_HelpLanguage
GO

-- Configuraci�n Ingl�s:
-- Ingreso de Fechas MDY
-- Inicio de D�as de Semana: Domingos=1, Lunes=2, ... S�bado=7

-- Configuraci�n Espa�ol:
-- Ingreso de Fechas DMY
-- Inicio de D�as de Semana: Lunes=1, Martes=2, ... Domingos=7

---------------------
-- Funci�n DATEPART
---------------------

--14 Usar DATEPART

-- D�a Actual
PRINT DATEPART(DAY, GETDATE())
GO

-- Mes Actual
PRINT DATEPART(MONTH, GETDATE())
GO

-- A�o Actual
PRINT DATEPART(YEAR, GETDATE())
GO

-- D�a de Semana Actual


PRINT DATEPART(WEEKDAY, GETDATE())
GO

-- D�a del A�o


PRINT DATEPART(DAYOFYEAR, GETDATE())
GO

-- Semana del A�o


PRINT DATEPART(WEEK, GETDATE())
GO

-- Trimestre
PRINT DATEPART (QUARTER, GETDATE())
GO

--15 Seleccionar los pedidos del 3er trimestre de 1997


-- que fueron realizados un d�a Jueves

SELECT * FROM Orders


WHERE YEAR(OrderDate) = 1997
AND DATEPART(QUARTER, OrderDate) = 3
AND DATEPART(WEEKDAY, OrderDate) = 4
GO

---------------------
-- Funci�n DATENAME
---------------------

--16 Devuelve el nombre del Mes actual

PRINT DATENAME(MONTH, GETDATE())


GO

--17 Listado de �rdenes emitidas un Martes 13 o un Domingo 7

SELECT * FROM Orders


WHERE (DAY(OrderDate)=13 AND DATENAME(WEEKDAY,OrderDate)='Martes')
OR (DAY(OrderDate)=7 AND DATENAME(WEEKDAY,OrderDate)='Domingo')
GO

--Como no hay resultados para Domingo, cambie por Lunes

SELECT * FROM Orders


WHERE (DAY(OrderDate)=13 AND DATENAME(WEEKDAY,OrderDate)='Martes')
OR (DAY(OrderDate)=7 AND DATENAME(WEEKDAY,OrderDate)='Lunes')
GO

---------------------
-- Funci�n DATEDIFF
---------------------

--18 Dadas dos fechas


-- (Por ejemplo, 28 de Julio del 2017 y 31 de Diciembre del 2018)

-- Diferencia en D�as
SELECT DATEDIFF(DAY,'28/07/2017','31/12/2018')
GO

-- Diferencia en Meses
SELECT DATEDIFF(MONTH,'28/07/2017','31/12/2018')
GO
-- Diferencia en A�os
SELECT DATEDIFF(YEAR,'28/07/2017','31/12/2018')
GO

-- Diferencia en Semanas
SELECT DATEDIFF(WEEK,'28/07/2017','31/12/2018')
GO

-- Diferencia en Trimestres
SELECT DATEDIFF(QUARTER,'28/07/2017','31/12/2018')
GO

-- Crear la siguiente Tabla Temporal


CREATE TABLE #ABC(
Nombre VARCHAR(50),
Apellido VARCHAR (50),
Fecha DATE
)
GO

INSERT #ABC
VALUES
('Juan', 'L�pez', '08/08/2008'),
('Jos�', 'Acevedo', '05/05/2005'),
('Mar�a', 'Sosa', '23/09/1999'),
('Jes�s', 'Montes', '31/07/2007'),
('Karla', 'Rosasco', '24/11/2004')
GO

SELECT * FROM #ABC


GO

--19
-- Liste Nombres y Apellidos indicando su Antig�edad

--Jes�s aparece con 10 a�os, pero a�n no cumple los 10 a�os


SELECT Nombre, Apellido, Fecha,
DATEDIFF(YEAR, Fecha, GETDATE()) AS 'Antig�edad'
FROM #ABC

-- Para hacerlo exacto tome en cuenta los d�as


SELECT Nombre, Apellido,
FLOOR(DATEDIFF(DAY, Fecha, GETDATE())/365.25) AS 'Antig�edad'
FROM #ABC
GO

--A�o Solar:
-- Tiempo que tarda la Tierra en hacer un giro completo alrededor del Sol
-- referido al tiempo entre dos equinoccios.
-- Dura 365 d�as, 5 horas 48 minutos y 45.6 segundos.
--20
-- Modifique la consulta anterior para seleccionar usuarios
-- cuya antig�edad sea mayor a 10 a�os
SELECT Nombre, Apellido,
FLOOR(DATEDIFF(DAY, Fecha, GETDATE())/365.25) AS 'Antig�edad'
FROM #ABC
WHERE FLOOR(DATEDIFF(DAY, Fecha, GETDATE())/365.25)>10
GO

--21 Mostrar Nombre, Apellido, Fecha y Antig�edad de


-- usuarios registrados en la segunda quincena de cualquier mes
-- del segundo semestre (excepto Agosto) del Siglo XXI
SELECT Nombre, Apellido, Fecha,
DATEDIFF(YEAR, Fecha, GETDATE()) AS 'Antig�edad'
FROM #ABC
WHERE
YEAR(Fecha)>=2001
AND (MONTH(Fecha)>=7 AND MONTH(Fecha)<>8)
AND DAY(Fecha)>=16
GO

---------------------
-- Funci�n DATEADD
---------------------

--22 Obtener el d�a resultante si adiciono 15 d�as a la Fecha Actual


SELECT DATEADD(DAY, 15, Getdate())
GO

-- Obtener s�lo la parte del d�a de dicha fecha


SELECT DATEPART(DAY,DATEADD(DAY, 15, Getdate()))
GO

-- Obtener el nombre del d�a de la semana de dicha fecha


SELECT DATENAME(WEEKDAY,DATEADD(DAY, 15, Getdate()))
GO

-- Obtener qu� n�mero de d�a del a�o ser� dicha fecha


-- Seg�n la secuencia 1 - 365/366
SELECT DATEPART(DAYOFYEAR,DATEADD(DAY, 15, Getdate()))
GO

-----------------------------------
-- Trabajando con la Fecha Actual
-----------------------------------

--23 �Qu� d�a es hoy?


-- Mostrar en cuatro columnas separadas: D�a de Semana, D�a, Mes y A�o

SELECT DATENAME(WEEKDAY,Getdate()),
DAY(Getdate()),
DATENAME(MONTH, Getdate()),
YEAR(GetDate())
GO

--24 �Qu� d�a es hoy? [Versi�n Mejorada]


-- Modelo del resultado: Hoy es Mi�rcoles 3 de Mayo de 2017

SELECT
'Hoy es ' + DATENAME(WEEKDAY,GetDate())
+' ' + CAST(DAY(GetDate()) AS VARCHAR(2))
+' de ' + DATENAME(MONTH, GetDate())
+' de ' + CAST(YEAR(GetDate()) AS CHAR(4))
AS 'Fecha Actual'
GO

--25 Cambie la consulta anterior para su Fecha de Nacimiento


-- Por ejemplo, usar� como fecha 09/09/1999
-- Modelo del resultado: Naciste un d�a Jueves 9 de Septiembre de 1999

SELECT
'Naciste un dia ' + DATENAME(WEEKDAY,'09/09/1999')
+' ' + CAST(DAY('09/09/1999') AS CHAR(2))
+' de ' + DATENAME(MONTH, '09/09/1999')
+' de ' + CAST(YEAR('09/09/1999') AS CHAR(4))
AS 'D�a de Nacimiento'
GO

--------------------------------
-- FUNCIONES DE CADENA --
--------------------------------

---------------------
-- Funci�n LEN
---------------------

--26 Mostrar la Longitud de cada Nombre

SELECT Nombre, LEN(Nombre) AS 'Longitud'


FROM #ABC
GO

--27 Mostrar los Apellidos con m�s de 5 letras

SELECT Apellido FROM #ABC


WHERE LEN(Apellido) > 5
GO
---------------------
-- Funci�n LEFT
---------------------

--28 La Inicial del Nombre con el Apellido


-- Modelo del resultado: J. L�pez, M. Sosa, etc.

SELECT LEFT(Nombre,1)+ '. ' +Apellido AS 'Usuario'


FROM #ABC
GO

--29 Modificar la consulta anterior


-- para Usuarios cuya 1ra letra del Nombre empiece con J

SELECT LEFT(Nombre,1)+ '. ' +Apellido AS 'Usuario'


FROM #ABC
WHERE LEFT(Nombre,1)= 'J'
GO

---------------------
-- Funci�n RIGHT
---------------------

--30 Dos �ltimas letras de los Apellidos

SELECT RIGHT(Apellido,2)
FROM #ABC
GO

--31 Nombres que NO empiecen con K y Apellidos que terminen en A, O , S

SELECT Nombre, Apellido


FROM #ABC
WHERE LEFT(Nombre,1)<>'K' AND RIGHT(Apellido,1) IN ('A','O','S')
GO

---------------------
-- Funci�n SUBSTRING
---------------------

/*

Extrae una porci�n de texto indicando la posici�n inicial


y el n�mero de caracteres a extraer.

Sintaxis:
SUBSTRING(Texto a trabajar, Posici�n Inicial , Nro. Caracteres a extraer)

*/

--32 Listar los Apellidos cuyo 3er y 4to


-- caracter tengan la cadena 'EV'

SELECT Apellido
FROM #ABC
WHERE SUBSTRING(Apellido,3,2)='EV'
GO

--33 Apellidos en cuyo 4to, 5to y 6to


-- caracter figure la cadena 'TES'

SELECT Apellido
FROM #ABC
WHERE SUBSTRING(Apellido,4,3)='TES'
GO

--34 Seleccione los clientes en cuyo Nombre o Apellido


-- el 2do y 3er caracter coincidan con
-- la cadena 'OS'

SELECT * FROM #ABC


WHERE SUBSTRING(Nombre,2,2)='OS' OR SUBSTRING(Apellido,2,2)='OS'
GO

---------------------
-- Funci�n LOWER
-- Funci�n UPPER
---------------------

--35
-- Nombre en min�sculas y Apellido en may�sculas

SELECT LOWER(Nombre),UPPER(Apellido)
FROM #ABC
GO

---------------------
-- Autogenerado
---------------------

--36
/* Ejercicio
Generar el c�digo para cada usuario

Regla:
UNAC
GUION
2 PRIMERAS LETRAS NOMBRE
2 ULTIMOS DIGITOS A�O
3RA LETRA APELLIDO
TODO EN MAYUSCULAS

*/
SELECT
'UNAC-'+
UPPER(LEFT(Nombre,2) +
RIGHT(YEAR(Fecha),2) +
SUBSTRING(Apellido,3,1))
FROM #ABC
GO

-----------------------
-- Funci�n CHARINDEX
-----------------------

/*

Retorna la posici�n inicial de una cadena de caracteres.

Sintaxis:
CHARINDEX(Cadena_b�squeda, Texto_origen ,Inicio)

Si el tercer argumento no se coloca, la b�squeda se da desde el inicio del texto.


Si no encuentra la cadena indicada, retorna 0.

*/

--37 Funci�n CHARINDEX

--Buscar or empezando del inicio del texto


SELECT CHARINDEX('or','Jorge Luis Borges') -- Retorna 2
GO

--Buscar or empezando desde el 4to caracter del texto


SELECT CHARINDEX('or','Jorge Luis Borges',3) -- Retorna 13
GO

---------------------
-- Funci�n REPLACE
---------------------

/*
Reemplaza una porci�n de texto por otra.

Sintaxis:
REPLACE(Texto_origen, Texto Antiguo, Texto Nuevo)

*/

--38 Funci�n Replace


SELECT REPLACE('Per� campe�n','Per�','Vamos bien') --Vamos bien campe�n
GO

SELECT REPLACE('sql asp c# asp','asp','php') --sql php c# php


GO

---------------------
-- Funci�n STUFF
---------------------

/*
Elimina una longitud espec�fica de caracteres de un texto
e inserta otra cadena de caracteres especificando la posici�n de inicio.

Sintaxis:
STUFF (Texto_Original , Inicio , Longitud_Reemplazo , Cadena)

*/

--39 Funci�n Stuff


SELECT STUFF('abcdefg',3,2,'1234') -- Se obtiene ab1234efg
GO

SELECT STUFF('UNIVERSO',5,4,'UNAC2017') --Se obtiene UNIVUNAC2017


GO --Note que ERSO fue eliminado
--Esto no hubiera sucedido con REPLACE

-----------------------------
-- Funciones LTRIM y RTRIM
-----------------------------

--40 Funci�n LTRIM


-- (Quita espacios en blanco por la izquierda)

SELECT LTRIM(' Tuve 5 espacios en blanco al inicio')


GO

--41 Funci�n RTRIM


-- (Quita espacios en blanco por la derecha)

SELECT RTRIM('Tuve 5 espacios en blanco al final ')


GO

--42 Retire los espacios en blanco al inicio y al final del siguiente texto
SELECT ' TEXTO '
GO

SELECT LTRIM(RTRIM(' TEXTO '))


GO

--Cuenta la cantidad de caracteres para verificar s�lo tenga cinco


SELECT LEN(LTRIM(RTRIM(' TEXTO ')))
GO

-----------------------
-- Funci�n SPACE
-----------------------

--43 Funci�n Space


SELECT 'Lima'+ SPACE(15) +'est� nublada'
GO

---------------------
-- Funci�n REVERSE
---------------------

--44 Funci�n REVERSE


SELECT REVERSE('canu')
GO

SELECT REVERSE('reconocer') --Pal�ndromo


GO

-----------------------
-- Funci�n REPLICATE
-----------------------

--45 Funci�n Replicate


SELECT REPLICATE('UNAC',3)
GO

SELECT REPLICATE('=',40)
GO

----------------------------------
-- Funciones ASCII y CHARACTER
----------------------------------

--46 Funci�n ASCII


SELECT ASCII('@'), ASCII('\'), ASCII('n')
GO

--47 Funci�n CHAR


SELECT CHAR(64), CHAR(92), CHAR(110)
GO

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 5 TSQL
---------------------------------------*/

/*

__.............__
.--""``` ```""--.
':--..___ ___..--:'
\ ```"""""""``` /
.-` ___.....-----.....___ '-.
.:-""`` ~ ~ ``""-:.
/`-..___ ~ ~ ~___..-'\
/ ~ '`""---.........---""` \
; ;
; '::. ' ~ .:' _. ;
| '::: ' .:' ~ |
|~ .:' . _ ':. |
| .:' ':.~ |
| ':. . ~ . _ .: |
; '::. _ /|| .;' ;
; ': ( } \||D ;
\.:'.:':. | /\__,=_[_] /
\ ':. ~ |_\__ |----| ` /
'. '::.. _ | |/ |--. |_ ~ .'
'-._':' | /_ | | `'-_.-'
(``''--..._____...--''``)
`"--...__ __...--"`
`````
*/

-- Usaremos la BD Ventas
-- Importe la BD Ventas, por favor

USE Ventas
GO

-- Conozcamos algunas de sus Tablas


SELECT * FROM Tb_Cliente
GO

SELECT * FROM Tb_Vendedor


GO

SELECT * FROM Tb_Producto


GO

SELECT * FROM Tb_Factura


GO

SELECT * FROM Tb_Detalle_Factura


GO

-- 1 Seleccionar C�digo, Descuento, Precio y Stock Actual de productos.


-- Ordenar Descendente por Precio y Descendente por Stock.
SELECT Cod_pro, Des_pro, Pre_pro, Stk_act
FROM Tb_Producto
ORDER BY Pre_pro DESC, Stk_act DESC
GO

-- 2 Vemos que las columnas fec_fac y fec_can son de Tipo Datetime


SELECT fec_fac, fec_can
FROM Tb_Factura
GO

-- Podemos convertir ambas columnas en DATE


ALTER TABLE Tb_Factura
ALTER COLUMN Fec_fac DATE
GO

ALTER TABLE Tb_Factura


ALTER COLUMN Fec_can DATE
GO

SELECT fec_fac AS 'F. Fact',


fec_can AS 'F. Canc'
FROM Tb_Factura
GO

-- Y si queremos ver con estilo d�a/mes/a�o


SELECT
CONVERT(VARCHAR(10), Fec_fac, 103) AS 'F. Fact',
CONVERT(VARCHAR(10), Fec_can, 103) AS 'F. Canc'
FROM Tb_Factura
GO

-- 3 Facturas emitidas un S�bado del Primer Semestre del 2010

SET LANGUAGE Spanish


GO

SELECT * FROM Tb_Factura


WHERE YEAR(Fec_fac)=2010 AND
MONTH(Fec_fac)<=6 AND
DATENAME(WEEKDAY,Fec_fac) ='S�bado'
GO

-- 4 Vendedores que ingresaron a la empresa un Lunes o un Viernes

-- Opci�n 1
SELECT * FROM Tb_Vendedor
WHERE DATENAME(WEEKDAY, Fec_ing) = 'Lunes'
OR DATENAME(WEEKDAY, Fec_ing) = 'Viernes'
GO

-- Opci�n 2
SELECT * FROM Tb_Vendedor
WHERE DATENAME(WEEKDAY, Fec_ing)
IN ('Lunes','Viernes')
GO

-- 5 Cantidad de d�as transcurridos para la cancelaci�n de una factura

--Versi�n 30, 70, 50, ...


SELECT Num_fac, Fec_fac, Fec_Can,
DATEDIFF(DAY,Fec_Fac,Fec_can) AS 'Tiempo Transcurrido'
FROM TB_Factura
GO

--Versi�n 30 d�as, 50 d�as, 70 d�as, ...


SELECT Num_fac, Fec_fac, Fec_Can,
CAST(DATEDIFF(DAY,Fec_Fac,Fec_can) AS VARCHAR(3)) +' d�as' AS 'Tiempo Transcurrido'
FROM TB_Factura
GO

-- 6 Crear una tabla llamada "Vend" con los datos de


-- la Tabla Vendedor

-- Viendo el contenido de la Tabla Vendedor


SELECT * FROM Tb_Vendedor
GO

-- Traslado de datos
SELECT * INTO Vend FROM Tb_Vendedor
GO

-- Viendo los datos de la Tabla Vend


SELECT * FROM Vend
GO

-- Revisando la estructura de la Tabla Vend


sp_help Vend
GO

-- 7 Crear una Tabla llamada ClientesEspeciales


-- para los clientes de los distritos D04, D05 y D26

-- Viendo el contenido de la Tabla Vendedor


SELECT * FROM Tb_Cliente
GO

-- Traslado de datos
SELECT * INTO ClientesEspeciales FROM Tb_Cliente
WHERE Cod_dis IN ('D04','D05','D26')
GO

-- Viendo los datos de la Tabla ClientesEspeciales


SELECT * FROM ClientesEspeciales
GO

-- Revisando la estructura de la Tabla ClientesEspeciales


sp_help ClientesEspeciales
GO

-- 8 El c�digo del cliente es del tipo C001, teniendo 4 caracteres en total.


-- Hacer la secuencia con 10 caracteres
-- C001 -> C000000001

SELECT 'C'+REPLICATE('0', 6)+RIGHT(Cod_cli,3) AS 'Nuevo C�digo'


FROM Tb_Cliente
GO

-- 9 Encontrar la 1ra y 2da vez que se repita la letra A


-- en los Apellidos de los Vendedores

SELECT ape_ven AS 'Apellidos',


CHARINDEX('A',Ape_ven,1) AS 'Primera Busqueda',
CHARINDEX('A',Ape_ven,CHARINDEX('A',Ape_ven,1)+1) AS 'Segunda B�squeda'
FROM Tb_Vendedor
WHERE ape_ven LIKE '%A%'
GO

-- 10 Separar el Contacto (Tabla Cliente) en Nombre y Apellido


SELECT Contacto FROM TB_CLIENTE
GO

-- 10a. Nombre
SELECT LEFT(Contacto, CHARINDEX(' ',Contacto)-1) AS 'Nombre'
FROM Tb_Cliente
GO

-- 10b. Apellido
SELECT RIGHT(Contacto, LEN(Contacto)-CHARINDEX(' ', Contacto)) AS 'Apellido'
FROM Tb_Cliente
GO

/*
Notas:
- Es m�s f�cil juntar que separar
Por eso tenga un nombre completo separado en columnas
- Y si lo debe tener todo junto, use un separador �nico, una coma, espacio, etc
dependiendo de cuantos elementos se tengan para separar
*/

/*
FUNCIONES DE AGREGACI�N
------------------------
SUM
COUNT
MAX
MIN
AVG

*/

----------------------------
-- Funci�n SUM
----------------------------

--11 Hallar el pago total (mensual) que se debe hacer a nuestros vendedores

SELECT * FROM Tb_Vendedor


GO

SELECT SUM(sue_ven) AS 'Pago Total Mensual a Vendedores'


FROM Tb_Vendedor
GO

----------------------------
-- Funci�n MAX, MIN
----------------------------

-- 12 Liste el producto m�s barato y el producto m�s caro

SELECT * FROM Tb_Producto


GO

SELECT
MIN(Pre_pro) AS 'Precio M�nimo',
MAX(Pre_pro) AS 'Precio M�ximo'
FROM Tb_Producto
GO

-- 13 Con respecto a los Vendedores de Tipo '1'


-- listar el sueldo m�nimo y el sueldo m�ximo

SELECT * FROM Tb_Vendedor


GO

SELECT
MIN(sue_ven) AS 'Sueldo M�nimo',
MAX(sue_ven) AS 'Sueldo M�ximo'
FROM Tb_Vendedor
WHERE tip_ven='1'
GO

----------------------------
-- Funci�n AVG
----------------------------

-- 14 Sueldo Promedio de los Vendedores


SELECT * FROM Tb_Vendedor
GO

SELECT AVG(sue_ven) AS 'Sueldo Promedio'


FROM Tb_Vendedor
GO

-- 15 Liste el Promedio de Antig�edad de los clientes.


SELECT * FROM Tb_Cliente
GO

-- Hallando el promedio
SELECT AVG(FLOOR(DATEDIFF(DAY, fec_reg, GETDATE())/365.25)) AS 'Promedio
Antig�edad'
FROM Tb_Cliente -- Rpta: 15.15
GO

-- Debemos redondear hacia abajo dicho resultado


SELECT FLOOR(AVG(FLOOR(DATEDIFF(DAY, fec_reg, GETDATE())/365.25)))
AS 'Promedio Antig�edad'
FROM Tb_Cliente -- Rpta: 15
GO

----------------------------
-- Funci�n COUNT
----------------------------

--16 Cantidad de Clientes

SELECT COUNT(*) FROM Tb_Cliente --Total Clientes: 20


GO

--17 Cantidad de Clientes con Tel�fono


-- (Tel_cli es una columna con nulos)

SELECT COUNT(Tel_cli)
FROM Tb_Cliente --Total Clientes con Tel�fono: 17
GO

-- Nota:
-- Count (y cualquier funci�n de agregaci�n) omite nulos cuando especificas alguna
columna
-- Con SELECT COUNT(*) FROM Tb_Cliente --Total Clientes: 20
-- Pero SELECT COUNT(Tel_cli) FROM Tb_Cliente --Total Clientes: 17

-- Count(*) nos da el n�mero de filas que retorna una consulta, sin importar nulos
o no nulos.
-- Pero si se especifica una columna COUNT(columna), entonces count retorna
-- el n�mero de filas en la cual la expresi�n no es null.

--18 Cantidad de Clientes sin Tel�fono


-- (Los clientes sin tel�fono est�n como Null)

-- Primer intento
SELECT COUNT(Tel_cli) FROM Tb_Cliente
WHERE Tel_cli IS NULL --0 filas (?)
GO

-- �Por qu� sale error?


-- Sencillo: COUNT omite nulos. Al realizar COUNT(Tel_cli)
-- s�lo estar�a considerando 17 registros (los cuales son No Nulos)
-- y sobre ellos no tiene sentido realizar un WHERE preguntando
-- quienes son nulos porque ya sabemos que ninguno de ellos lo es.

-- Soluci�n 1
SELECT COUNT(*)-COUNT(Tel_cli)
FROM Tb_Cliente
GO

-- Soluci�n 2
SELECT COUNT(*) FROM Tb_Cliente
WHERE Tel_cli IS NULL --Rpta: 3
--Al utilizar COUNT(*) me refiero al total de registros

-- 19 Cantidad de Vendedores que han emitido una Factura

SELECT * FROM Tb_Factura


GO

SELECT COUNT(Cod_ven) -- 20 �Ser� la respuesta correcta? No.


FROM Tb_Factura
GO

SELECT COUNT(DISTINCT Cod_ven) -- 10 es la respuesta correcta


FROM Tb_Factura
GO

-- 20 Cantidad de Facturas pendientes (Estado=1)


-- que no hayan sido atendidas por el vendedor V08

SELECT * FROM Tb_Factura


GO

SELECT COUNT(*) AS 'Facturas Pendientes'


FROM Tb_Factura
WHERE est_fac='1' AND Cod_ven<>'V08'
GO
CREATE TABLE #Abc(
Vendedor VARCHAR(50),
Sueldo SMALLMONEY,
Bono SMALLMONEY
)
GO

INSERT #Abc
VALUES
('Juan', '2000', '200'),
('Kathy', '1500', NULL),
('Sonia', '3000', '300')
GO

-- 21 Calcular el Nuevo Sueldo (Sueldo + Bono)


SELECT Vendedor, Sueldo, Bono,
Sueldo + Bono AS 'Nuevo Sueldo'
FROM #Abc
GO -- Para Kathy la Suma da Null

----------------------------
-- Funci�n ISNULL
----------------------------

--Reemplazamos los NULL con valores 0 con la Funci�n ISNULL

SELECT Vendedor, Sueldo, Bono,


Sueldo + ISNULL(Bono,0) AS 'Nuevo Sueldo'
FROM #Abc
GO -- Respuesta correcta, ning�n registro de 'Nuevo Sueldo' es Null

-- 22 Con respecto a la columna Bono Tabla #Abc


-- SUM, AVG, MAX, MIN, COUNT (Nulos y no Nulos)

SELECT SUM(Bono) FROM #Abc


SELECT AVG(Bono) FROM #Abc
SELECT MAX(Bono) FROM #Abc
SELECT MIN(Bono) FROM #Abc
SELECT COUNT(Bono) FROM #Abc
SELECT COUNT(*) FROM #Abc WHERE Bono IS NULL
GO

-----------------------------------------
-- Agrupando con la Cl�usula GROUP BY
-----------------------------------------

-- 23 Cu�ntas facturas tiene cada cliente

SELECT * FROM Tb_Factura


GO

SELECT Cod_cli, COUNT(Num_Fac) AS 'N�mero de Facturas'


FROM Tb_Factura
GROUP BY Cod_cli
GO

-- 24 La consulta anterior ord�nela de manera descendente


SELECT * FROM Tb_Factura
GO

SELECT Cod_cli, COUNT(Num_Fac) AS 'N�mero de Facturas'


FROM Tb_Factura
GROUP BY Cod_cli
ORDER BY COUNT(Num_Fac) DESC
GO

SELECT Cod_cli, COUNT(Num_Fac) AS 'N�mero de Facturas'


FROM Tb_Factura
GROUP BY Cod_cli
ORDER BY 2 DESC -- Funciona, pero es mala pr�ctica ya que no es expl�cito.
GO

-- 25 Modifique la consulta anterior


-- Mostrando los 2 clientes que generaron m�s facturas
-- Especifique empates si es necesario

SELECT TOP 2 WITH TIES Cod_cli, COUNT(Num_Fac) AS 'N�mero de Facturas'


FROM Tb_Factura
GROUP BY Cod_cli
ORDER BY COUNT(Num_Fac) DESC
GO

-- Nota: WITH TIES siempre debe ir con un ORDER BY

-- 26 Ojo con los Empates

-- Top 5 sin empates


SELECT TOP 5 Cod_cli, COUNT(Num_Fac) AS 'N�mero de Facturas'
FROM Tb_Factura
GROUP BY Cod_cli
ORDER BY COUNT(Num_Fac) DESC
GO

-- Top 5 con empates


SELECT TOP 5 WITH TIES Cod_cli, COUNT(Num_Fac) AS 'N�mero de Facturas'
FROM Tb_Factura
GROUP BY Cod_cli
ORDER BY COUNT(Num_Fac) DESC
GO
-- Moraleja: El With Ties (los empates) es S�LO para el �ltimo valor de la lista

-- Analizando WITH TIES


CREATE TABLE #XYZ(
Venta Tinyint
)
GO

INSERT #xyz
VALUES
('1'),
('1'),
('2'),
('2'),
('3')
GO

SELECT * FROM #XYZ


GO

SELECT TOP 1 * FROM #XYZ -- 1


GO

SELECT TOP 1 WITH TIES * FROM #XYZ -- 1, 1


ORDER BY VENTA
GO

SELECT TOP 2 * FROM #XYZ -- 1, 1


GO

SELECT TOP 2 WITH TIES * FROM #XYZ -- 1, 1


ORDER BY VENTA

SELECT TOP 3 * FROM #XYZ -- 1, 1, 2


GO

SELECT TOP 3 WITH TIES * FROM #XYZ -- 1, 1, 2, 2


ORDER BY VENTA
GO

SELECT TOP 4 * FROM #XYZ -- 1, 1, 2, 2


GO

SELECT TOP 4 WITH TIES * FROM #XYZ -- 1, 1, 2, 2


ORDER BY VENTA

SELECT TOP 5 * FROM #XYZ -- 1, 1, 2, 2, 3


GO

SELECT TOP 5 WITH TIES * FROM #XYZ -- 1, 1, 2, 2, 3


ORDER BY VENTA
GO

-- 27 Cantidad de clientes por distrito


-- para los distritos D05, D10, D17 y D20
SELECT * FROM Tb_Cliente
GO

SELECT Cod_dis, COUNT(Cod_dis)


FROM Tb_Cliente
WHERE Cod_dis IN('D05', 'D10', 'D17', 'D20')
GROUP BY Cod_Dis
GO

-- 28 Cantidad de clientes por distrito


-- del distrito D05 en adelante

SELECT Cod_dis, COUNT(Cod_dis)


FROM Tb_Cliente
WHERE Cod_dis >='D05'
GROUP BY Cod_Dis
GO

-- Si quisiera del distrito D05 hasta el distrito D20


SELECT Cod_dis, COUNT(Cod_dis)
FROM Tb_Cliente
WHERE Cod_dis BETWEEN 'D05' and 'D20'
GROUP BY Cod_Dis
GO

-- 29 Como regla general es mejor evitar b�squedas con Strings


-- En una BD siempre es m�s r�pido buscar n�meros que caracteres.

SELECT ape_ven FROM Tb_Vendedor


WHERE ape_ven BETWEEN 'L' AND 'Q' -- Tenemos apellidos que empiezan con P
GO -- como Palacios y Pariona

SELECT ape_ven FROM Tb_Vendedor


WHERE ape_ven BETWEEN 'L' AND 'P' -- No aparecen apellidos que empiecen con P
GO -- Debido a que BETWEEN 'L' AND 'P'
-- es equivalente a >=L AND <=P

-- Recuerde que cuando usamos BETWEEN con


n�meros
-- por ejemplo BETWEEN 15 AND 177
-- puede mostrar 177, pero no muestra 177.00001

SELECT ape_ven FROM Tb_Vendedor


WHERE ape_ven BETWEEN 'L' AND 'Pz' -- S� aparecen los apellidos que empiezan con P
GO

SELECT ape_ven FROM Tb_Vendedor


WHERE ape_ven BETWEEN 'L' AND 'Sa' -- 8 registros.
GO -- No aparece ninguno empieza de los que
-- empieza con Sa como Salas o Salazar.

SELECT ape_ven FROM Tb_Vendedor


WHERE ape_ven BETWEEN 'L' AND 'Sz' -- 10 registros. Tenemos Salas, Salazar
GO

---------------------------------------------------------------
-- >> Nota:
-- Recuerde: un Group By muestra una fila por grupo,
-- mostrando el resultado de una funci�n de agregaci�n.
-- NO muestra el contenido del grupo.
---------------------------------------------------------------

-- 30 Cantidad de productos cuyo Precio sea 20, 35 � 45, agrupar.

SELECT * FROM Tb_Producto


GO

SELECT Pre_pro AS Precio, COUNT(*) AS 'Cantidad'


FROM Tb_Producto
WHERE Pre_pro IN (20, 35, 45)
GROUP BY Pre_pro
GO

-- 31 Cantidad de productos cuyo Precio no est� entre 20 y 40, agrupar.

SELECT Pre_pro AS Precio, COUNT(*) AS 'Cantidad'


FROM Tb_Producto
WHERE Pre_pro NOT BETWEEN 20 AND 40
GROUP BY Pre_pro
GO

-- 32 Cantidad de Productos que empiecen con las letras A, B � C. Agrupar.

SELECT LEFT(Des_pro,1), COUNT(*)


FROM Tb_Producto
WHERE LEFT(Des_pro,1) IN ('A','B','C')
GROUP BY LEFT(Des_pro,1)
GO

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 7 TSQL (3.5 hrs)
---------------------------------------*/

/*
, ,
$, $, ,
"ss.$ss. .s'
, .ss$$$$$$$$$$s,
$. s$$$$$$$$$$$$$$`$$Ss
"$$$$$$$$$$$$$$$$$$o$$$ ,
s$$$$$$$$$$$$$$$$$$$$$$$$s, ,s
s$$$$$$$$$"$$$$$$""""$$$$$$"$$$$$,
s$$$$$$$$$$s""$$$$ssssss"$$$$$$$$"
s$$$$$$$$$$' `"""ss"$"$s""
s$$$$$$$$$$, `"""""$ .s$$s
s$$$$$$$$$$$$s,... `s$$' `
`ssss$$$$$$$$$$$$$$$$$$$$####s. .$$"$. , s
`""""$$$$$$$$$$$$$$$$$$$$#####$$$$$$" $.$'
"$$$$$$$$$$$$$$$$$$$$$####s"" .$$$|
"$$$$$$$$$$$$$$$$$$$$$$$$##s .$$" $
$$""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
$$" "$"$$$$$$$$$$$$$$$$$$$$S""""'
, ," ' $$$$$$$$$$$$$$$$####s
$. .s$$$$$$$$$$$$$$$$$####"
, "$s. ..ssS$$$$$$$$$$$$$$$$$$$####"
$ .$$$S$$$$$$$$$$$$$$$$$$$$$$$$#####"
Ss ..sS$$$$$$$$$$$$$$$$$$$$$$$$$$$######""
"$$sS$$$$$$$$$$$$$$$$$$$$$$$$$$$########"
, s$$$$$$$$$$$$$$$$$$$$$$$$#########""'
$ s$$$$$$$$$$$$$$$$$$$$$#######""' s' ,
$$..$$$$$$$$$$$$$$$$$$######"' ....,$$.... ,$
"$$$$$$$$$$$$$$$######"' , .sS$$$$$$$$$$$$$$$$s$$
$$$$$$$$$$$$#####" $, .s$$$$$$$$$$$$$$$$$$$$$$$$s.
) $$$$$$$$$$$#####' `$$$$$$$$$###########$$$$$$$$$$$.
(( $$$$$$$$$$$##### $$$$$$$$###" "####$$$$$$$$$$
) \ $$$$$$$$$$$$####. $$$$$$###" "###$$$$$$$$$
( ) $$$$$$$$$$$$$####. $$$$$###" ####$$$$$$$$$
) ( ( $$"$$$$$$$$$$$#####.$$$$$###' .###$$$$$$$$$$
( ) ) _,$" $$$$$$$$$$$$######.$$##' .###$$$$$$$$$$
) ( ( \. "$$$$$$$$$$$$$#######,,,. ..####$$$$$$$$$$$"
( )$ ) ) ,$$$$$$$$$$$$$$$$$$####################$$$$$$$$$$$"
( ($$ ( \ _sS" `"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$S$$,
) )$$$s ) ) . . `$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"' `$$
( $$$Ss/ .$, .$,,s$$$$$$##S$$$$$$$$$$$$$$$$$$$$$$$$S"" '
\)_$$$$$$$$$$$$$$$$$$$$$$$##" $$ `$$. `$$.
`"S$$$$$$$$$$$$$$$$$#" $ `$ `$
`"""""""""""""' ' ' '

*/

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- I - SUBCONSULTA (SUBQUERY)
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

-- Regla General: En las Subconsultas s�lo puede haber un Campo.


-- y no deben tener ORDER BY.

-- La Subconsulta se puede especificar:


-- > En la Cl�usla WHERE del Select externo usando
-- un operador de comparaci�n (>, <, >=, <=, =, <>)
-- > Como parte de la lista de columnas del Select Externo.

--\ A) Subconsultas que entregan un solo valor \--

USE Ventas
GO

-- 1 Liste la Descripci�n y Precio de los Productos cuyo Precio


-- supera el Precio Promedio.

SELECT Des_pro, Pre_pro


FROM Tb_Producto
WHERE Pre_pro>=AVG(Pre_pro) --Lea el mensaje de error
GO

-- "Una funci�n de agregaci�n (SUM, AVG, COUNT, MAX, MIN) no puede estar
-- en una cl�usula WHERE a no ser que est� incluida como Subconsulta (Subquery)"

-- �xito
SELECT Des_pro, Pre_pro
FROM Tb_Producto
WHERE Pre_pro>=(SELECT AVG(Pre_pro) FROM Tb_Producto)
GO

-- 2 Liste la Raz�n Social, RUC y Antig�edad de Clientes


-- con una Antig�edad Mayor a la Antig�edad Promedio.

SELECT Raz_soc_cli AS 'Raz�n', Ruc_cli AS 'Ruc',


FLOOR(DATEDIFF(DAY, Fec_reg, GETDATE())/365.25) AS 'Antig�edad'
FROM Tb_Cliente
WHERE
FLOOR(DATEDIFF(DAY, Fec_reg, GETDATE())/365.25) >
(SELECT
FLOOR(AVG(FLOOR(DATEDIFF(DAY, Fec_reg, GETDATE())/365.25)))
FROM Tb_Cliente)
GO

-- 3 Liste la Cantidad de Facturas generadas por el Vendedor


-- que est� actualmente asignado al Distrito D09.

SELECT * FROM Tb_Distrito


GO

SELECT * FROM Tb_Factura


WHERE Cod_ven='V02'
GO

SELECT COUNT(*) AS 'N�mero de Facturas'


FROM Tb_Factura
WHERE Cod_ven=(SELECT Cod_ven
FROM Tb_Distrito WHERE Cod_dis='D09')
GO
-- 4 Mostrar C�digo y Sueldo de vendedores. Mostrar adem�s cu�l
-- es su Diferencia con respecto al Sueldo Promedio.

SELECT * FROM Tb_vendedor


GO

SELECT Cod_ven, Sue_ven,


'Diferencia' = Sue_ven-(SELECT AVG(Sue_ven) FROM Tb_Vendedor)
FROM Tb_Vendedor
--COMPUTE AVG(Sue_ven)
GO

-- 5 Mostrar C�digo y Sueldo de Vendedores. Mostrar adem�s qu�


-- porcentaje representa el Sueldo de cada Empleado
-- con respecto al Pago Total a Empleados

SELECT Cod_ven, Sue_ven,


'Porcentaje' = Sue_ven /(SELECT SUM(Sue_ven)FROM Tb_Vendedor)
FROM Tb_Vendedor
--COMPUTE SUM(Sue_ven)
GO
-- Recuerde la equivalencia de decimales en porcentaje:
-- 0.80 = 80% 0.30 = 30%
-- 0.10 = 10% 0.18 = 18%
-- 0.05 = 5% 0.0501 = 5.01% ...etc.

sp_help Tb_vendedor
GO -- Money tiene escala a 4 decimales

--\ B) Subconsultas que entregan un conjunto de valores \--


--\ Varias filas, una sola columna \--

-- 6 Liste los Nombres de los Productos comercializados en la Factura FA003.

SELECT * FROM Tb_Detalle_Factura


WHERE Num_fac='FA003'
GO

SELECT * FROM Tb_Producto


WHERE Cod_pro IN ('P002', 'P011', 'P017', 'P019')
GO

SELECT Des_pro AS Nombre


FROM Tb_Producto
WHERE cod_pro IN (SELECT Cod_pro FROM Tb_Detalle_Factura
WHERE Num_fac='FA003')
GO

-- 7 Liste los Nombres y Apellidos de Vendedores que NO ha generado Facturas.


SELECT Nom_ven, Ape_ven
FROM Tb_Vendedor
WHERE Cod_ven NOT IN (SELECT DISTINCT Cod_ven
FROM Tb_Factura)
GO

-- 8 Mostrar los Productos que NO han sido vendidos

SELECT Cod_pro, Des_pro


FROM Tb_Producto
WHERE Cod_pro NOT IN
(SELECT DISTINCT Cod_pro
FROM Tb_Detalle_Factura)
GO

-- 9 Mostrar los Clientes que NO tienen Facturas

SELECT Cod_cli, Raz_soc_cli


FROM Tb_Cliente
WHERE Cod_cli NOT IN
(SELECT DISTINCT Cod_cli
FROM Tb_Factura)
GO

-- 10 Mostrar los Productos que NO son abastecidos por Proveedores

SELECT * FROM Tb_Abastecimiento


GO

SELECT * FROM Tb_Producto


GO

SELECT Cod_pro, Des_pro


FROM Tb_Producto
WHERE Cod_pro NOT IN
(SELECT Cod_pro
FROM Tb_Abastecimiento)
GO

-- 11 �Cu�ntas facturas con un Monto Total mayor a 1000 existen?

SELECT COUNT(*)
FROM Tb_Factura
WHERE Num_fac IN (SELECT Num_fac
FROM Tb_Detalle_Factura
GROUP BY Num_fac
HAVING SUM(Can_ven*Pre_ven)>1000)
GO

-- 12 Listar las Facturas de Clientes con m�s de una Factura.


-- Mostrar C�digo de Cliente, N�mero de Factura y Fecha de Facturaci�n.
-- Primero ve�mos qui�nes son y cu�ntas facturas tienen

SELECT Cod_cli, COUNT(*) AS Cantidad


FROM Tb_Factura
GROUP BY Cod_cli
HAVING COUNT(*) > 1
GO

-- Nos piden mostrar los datos de cada una de dichas facturas


SELECT * FROM Tb_Factura
GO

SELECT Cod_cli, Num_fac, CONVERT(CHAR(10), Fec_fac, 103) AS 'Fecha'


FROM Tb_Factura
WHERE Cod_cli IN
(
SELECT Cod_cli
FROM Tb_Factura
GROUP BY Cod_cli
HAVING COUNT(*) > 1
)
ORDER BY Cod_cli
GO

--\ C) Subconsultas con 'Referencias Externas' \--


--\ Cuando un Campo de tu Subconsulta hace Referencia \--
--\ a la Tabla de tu Consulta Principal \--

-- 13 Liste c�digo, raz�n social y la fecha


-- de la primera factura de cada cliente

SELECT Cod_cli, Raz_soc_cli,

(SELECT MIN(Fec_fac) FROM Tb_Factura


WHERE
Tb_Factura.Cod_cli=Tb_Cliente.Cod_cli) AS 'Fecha 1ra Factura'

FROM Tb_Cliente
GO
--Por ejemplo, para el Cliente C016 su primera factura
--es del 16 de Enero del 2010 y para el Cliente C019 la
--primera factura es 16 de Septiembre del 2010

-- Comprobando
SELECT * FROM TB_FACTURA
WHERE Cod_cli='C016' OR Cod_cli='C019'
ORDER BY Cod_cli
GO

-- 14 Liste C�digo, Raz�n Social y cu�ntas Facturas


-- pertenecen a cada Cliente
SELECT Cod_cli, Raz_soc_cli,

(SELECT COUNT(*)
FROM Tb_Factura
WHERE Tb_Cliente.Cod_cli=Tb_Factura.Cod_cli
) AS 'Nro. de Facturas'

FROM Tb_Cliente
GO

-- b) La consulta anterior, pero mostrando s�lo


-- a los Clientes que tienen Facturas.

SELECT Cod_cli, Raz_soc_cli, Ruc_cli,

(SELECT COUNT(*)
FROM Tb_Factura
WHERE Tb_Cliente.Cod_cli=Tb_Factura.Cod_cli
) AS 'Nro. de Facturas'

FROM Tb_Cliente

WHERE (SELECT COUNT(*)


FROM Tb_Factura
WHERE Tb_Cliente.Cod_cli=Tb_Factura.Cod_cli
)>0
GO

--\ D) Utilizando EXISTS \--


--\ y NOT EXISTS \--

-- 15

-- a) Muestre los Productos que han sido Vendidos.

SELECT Cod_pro, Des_pro


FROM Tb_Producto
WHERE EXISTS (SELECT *
FROM Tb_Detalle_Factura
WHERE
Tb_Detalle_Factura.Cod_pro=Tb_Producto.Cod_pro)
GO

-- b) Muestre los Productos que NO han sido Vendidos.

SELECT Cod_pro, Des_pro


FROM Tb_Producto
WHERE NOT EXISTS (SELECT *
FROM Tb_Detalle_Factura
WHERE
Tb_Detalle_Factura.Cod_pro=Tb_Producto.Cod_pro)
GO
-- Una subconsulta no est� limitada a SELECT.
-- Tambi�n se puede hacer con INSERT, DELETE y UPDATE.

-- 16 Respecto a la pregunta 4, indicar la diferencia de tres maneras:


-- > Es inferior al promedio por #####
-- > Es igual al promedio
-- > Es superior al promedio por #####

SELECT Cod_ven, Sue_ven,

CASE

WHEN Sue_ven-(SELECT AVG(Sue_ven)FROM Tb_Vendedor)<0


THEN 'Es inferior al promedio por: '+
CAST(ABS(Sue_ven-(SELECT AVG(Sue_ven)FROM Tb_Vendedor)) AS VARCHAR(10))

WHEN Sue_ven-(SELECT AVG(Sue_ven)FROM Tb_Vendedor)=0


THEN 'Es igual al promedio el cual es: '+
CAST((SELECT AVG(Sue_ven)FROM Tb_Vendedor) AS VARCHAR(10))

WHEN Sue_ven-(SELECT AVG(Sue_ven)FROM Tb_Vendedor)>0


THEN 'Es superior al promedio por: '+
CAST(Sue_ven-(SELECT AVG(Sue_ven)FROM Tb_Vendedor) AS VARCHAR(10))
END Diferencia

FROM Tb_Vendedor
--COMPUTE AVG(sue_ven)
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- III - JOINS
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

----------------------
-- \ INNER JOIN \ --
----------------------

-- 17 Liste Raz�n Social, Direcci�n y el Nombre del Distrito donde viven


-- cada cliente.

-- Sin Alias

SELECT Raz_soc_cli, Dir_cli, Nom_dis


FROM Tb_Cliente
INNER JOIN Tb_Distrito
ON Tb_Cliente.Cod_dis=Tb_Distrito.Cod_dis
GO

-- Con Alias

SELECT Raz_soc_cli, Dir_cli, Nom_dis


FROM Tb_Cliente C
INNER JOIN Tb_Distrito D
ON C.Cod_dis=D.Cod_dis
GO

-- 18 Seleccionar N�mero de Factura, Fecha de Factura,


-- Nombre del Cliente y Nombre del Vendedor involucrado
-- en cada Factura

SELECT * FROM Tb_Factura


SELECT * FROM Tb_Cliente
SELECT * FROM Tb_Vendedor
GO

SELECT Num_fac, Fec_fac, Raz_soc_cli, Nom_ven


FROM Tb_Factura F
INNER JOIN Tb_Cliente C ON F.Cod_cli=C.Cod_cli
INNER JOIN Tb_Vendedor V ON F.Cod_ven=V.cod_ven
GO

-- 19
-- Mostrar una lista de Productos con sus respectivos Proveedores

SELECT * FROM Tb_Producto


SELECT * FROM Tb_Abastecimiento
SELECT * FROM Tb_Proveedor
GO

-- Mostrar Nombre del Producto (Des_Pro) y Nombre del Proveedor (Raz_Soc_Prov)


-- Noten que Producto y Proveedor no tienen relaci�n directa y que
-- est�n conectados a trav�s de Abastecimiento

SELECT Des_Pro, Raz_Soc_Prv


FROM Tb_Abastecimiento A
INNER JOIN Tb_Producto P ON A.Cod_pro=P.Cod_pro
INNER JOIN Tb_Proveedor PV ON A.Cod_prv=PV.Cod_prv
ORDER BY Des_pro
GO

-- 20 Liste el N�mero de Factura, Nombre del Cliente y el Total Facturado


-- por cada Factura

SELECT F.Num_fac, Raz_soc_cli, SUM(Can_ven*Pre_ven) AS 'Total'


FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura D ON F.Num_fac = D.Num_fac
INNER JOIN Tb_Cliente C ON F.Cod_cli=C.Cod_cli
GROUP BY F.Num_fac, Raz_soc_cli
ORDER BY F.Num_fac
GO

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 8 TSQL
---------------------------------------*/

/*

,-----.
\======'.
\ {} '.
\ \/ V '.
\ || | '._ _,cmmmnc,_
\___68FS___\'-._=----+- _______________,.-=:3H)###C-- `c._
:|=--------------`---"'`. ` `. `. `, `~""==="~` `'-.___
,dH] ' =(*)= : ---==;=--; . ; +-- -_ .-`
:HH]_:______________ ____,.........__ _____,.----=-"~ `
;:""'"'----._.------\` : . `.'`'"'"'"P
|: .-'==-.__)___\. : . .'`___L~___(
|: _.'` '| / \.: . .-`""`
`'"' `--' \: ._.-'
}_`============>-

*/

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- I- JOINS
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

CREATE DATABASE Joins


GO

USE Joins
GO

CREATE TABLE Clientes(


Id Tinyint,
Nombre Varchar(20),
Apellido Varchar(20),
Direcci�n Varchar(50),
Ciudad Varchar (30)
)
GO

INSERT Clientes
VALUES
('1', 'Juli�n', 'Castillo', 'Av. Sol 123', 'Lima'),
('2', 'Melissa', 'Saucedo', 'Jr. Luna 99', 'Lima'),
('3', 'Laura', 'Paz', 'Calle Astral 77', 'Callao'),
('4', 'Helen', 'Deza', 'Psje. Universo 444', 'Lima')
GO

SELECT * FROM Clientes


GO

CREATE TABLE Pedidos(


Id Tinyint,
Producto Varchar(30),
IdCli Tinyint,
)
GO

INSERT Pedidos
VALUES
('1', 'PC', '3'),
('2', 'Laptop', '3'),
('3', 'TV', '1'),
('4', 'Equipo', '1'),
('5', 'Blu-Ray', '7')
GO

SELECT * FROM Pedidos


GO

-- 01- INNER JOIN


-- Combina las filas que est�n relacionadas
-- de un conjunto de tablas especificadas.

SELECT Clientes.Apellido, Clientes.Nombre, Pedidos.Id


FROM Clientes
INNER JOIN Pedidos
ON Clientes.Id=Pedidos.IdCli
ORDER BY Clientes.Apellido
GO

-- 02- LEFT JOIN


-- Devuelve todas las filas que est�n relacionadas
-- y adem�s las filas no relacionadas de la Tabla Izquierda.

-- (Se considera 'Tabla Izquierda' a la Primera tabla mencionada en el JOIN.


-- En este caso ser�a la Tabla Clientes)

SELECT Clientes.Apellido, Clientes.Nombre, Pedidos.Id


FROM Clientes
LEFT JOIN Pedidos
ON Clientes.Id=Pedidos.IdCli
ORDER BY Clientes.Apellido
GO

-- 03- RIGHT JOIN


-- Devuelve todas las filas que est�n relacionadas
-- y adem�s las filas no relacionadas de la Tabla Derecha.

-- (Se considera 'Tabla Derecha' a la segunda tabla mencionada en el JOIN.


-- En este caso ser�a la Tabla Pedidos)

SELECT Clientes.Apellido, Clientes.Nombre, Pedidos.Id


FROM Clientes
RIGHT JOIN Pedidos
ON Clientes.Id=Pedidos.IdCli
ORDER BY Clientes.Apellido
GO

-- 04- FULL JOIN


-- Devuelve todas las filas que est�n relacionadas
-- y adem�s las filas no relacionadas de ambas Tablas.

SELECT Clientes.Apellido, Clientes.Nombre, Pedidos.Id


FROM Clientes
FULL JOIN Pedidos
ON Clientes.Id=Pedidos.IdCli
ORDER BY Clientes.Apellido
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- II- Ejercicios Joins
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

USE VENTAS
GO

-- 05- Productos que se vendieron en cada factura.


-- Mostrar C�digo y Nombre del Producto, as� como la Cantidad Vendida.

SELECT P.Cod_pro, P.Des_pro, DF.Can_ven


FROM Tb_Detalle_Factura DF
INNER JOIN Tb_Producto P ON DF.Cod_pro=P.Cod_pro
ORDER BY P.Cod_pro
GO

-- Totalizar
SELECT P.Cod_pro, P.Des_pro, SUM(DF.Can_ven) AS 'Items vendidos'
FROM Tb_Detalle_Factura DF
INNER JOIN Tb_Producto P ON DF.Cod_pro=P.Cod_pro
GROUP BY P.Cod_pro, P.Des_pro
ORDER BY P.Cod_pro
GO

-- 06- �Y qu� pasa si uso SELECT * en un JOIN?

SELECT *
FROM Tb_Detalle_Factura DF
INNER JOIN Tb_Producto P
ON DF.Cod_pro=P.Cod_pro
GO
-- Muestra ambas Tablas del Join, comparadas una
-- al lado de la otra.

-- 07- Productos que NO se vendieron en alguna factura.


-- Use LEFT JOIN

SELECT *
FROM Tb_Producto P
LEFT JOIN Tb_Detalle_Factura DF
ON DF.Cod_pro=P.Cod_pro
WHERE DF.Num_fac IS NULL
GO

-- 08- Productos que no se vendieron en alguna factura.


-- Use RIGHT JOIN

SELECT *
FROM Tb_Detalle_Factura DF
RIGHT JOIN Tb_Producto P ON DF.Cod_pro=P.Cod_pro
WHERE DF.Num_fac IS NULL
GO

-- Simplemente se cambi� el orden de las


-- tablas para poder usar el RIGHT JOIN

-- 09- Otra forma: con el NOT IN


-- Subconsulta.

SELECT * FROM Tb_Producto


WHERE Cod_pro NOT IN (
SELECT DISTINCT Cod_pro
FROM Tb_Detalle_Factura)
GO

-- 10- Quiero saber qu� Facturas que fueron realizadas a Clientes


-- que residen en San Borja o Lince.

-- > Primero tengo que saber qu� se vendi� en dichos distritos.

SELECT * FROM Tb_Factura --Tiene Cod_cli


SELECT * FROM Tb_Cliente --Tiene Cod_dis
SELECT * FROM Tb_Distrito --Tiene Cod_dis, Nom_dis
GO

SELECT * FROM Tb_Factura F


INNER JOIN Tb_Cliente C
ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis='San Borja' OR Nom_dis='Lince')
ORDER BY F.Num_fac
GO
-- Se us� IN en lugar de =
-- Ya que el subquery da m�ltiples valores como resultado
-- y un comparador de igualdad s�lo se compara a un �nico valor.

--Luego la negaci�n

SELECT * FROM Tb_Factura F


INNER JOIN Tb_Cliente C
ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis NOT IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis='San Borja' OR Nom_dis='Lince')
ORDER BY F.Num_fac
GO

-- Como resultado son todas las facturas excepto:


-- FA004, FA009, FA016, FA018 y FA019

-- 11- La consulta anterior pero que s�lo muestre:


-- N�mero de factura, Nombre del Cliente, Distrito del Cliente.

SELECT F.Num_fac, C.Raz_soc_cli, D.Nom_dis


FROM Tb_Cliente C
INNER JOIN Tb_Factura F ON C.Cod_cli=F.Cod_cli
INNER JOIN Tb_Distrito D ON C.Cod_dis=D.Cod_dis

WHERE C.Cod_dis NOT IN (


SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis='San Borja' OR Nom_dis='Lince')
ORDER BY F.Num_fac
GO

-- 12- Listar los nombres de los productos


-- que no se vendieron a clientes de San Borja o Lince

SELECT Des_pro FROM Tb_Producto


WHERE Cod_pro not in (
SELECT DISTINCT DF.Cod_pro
From Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis='San Borja' OR
Nom_dis='Lince')
)
GO

-- La consulta anterior resulta, pero siempre es m�s


-- r�pido utilizar JOINs en lugar de WHEREs

-- Utilizando LEFT JOIN /Is Null

SELECT Des_pro FROM Tb_Producto P

LEFT JOIN ( SELECT DISTINCT DF.Cod_pro


From Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis='San Borja' OR
Nom_dis='Lince')
) PX on PX.Cod_pro=P.Cod_pro

WHERE PX.Cod_pro IS NULL


GO

-- Ingresar las siguientes Tablas

CREATE DATABASE Zonas


GO

USE Zonas
GO

CREATE TABLE Ventas_Este(


IdVenta Tinyint,
Vendedor Varchar(30),
Monto Decimal(6,2)
)
GO

INSERT Ventas_Este
VALUES
('1', 'Juan', '3500'),
('2', 'Pedro', '1500'),
('3', 'Karla', '7000'),
('4', 'Miguel', '4000'),
('5', 'Pamela', '2800')
GO

SELECT * FROM Ventas_Este


GO

CREATE TABLE Ventas_Sur(


IdVenta Tinyint,
Vendedor Varchar(30),
Monto Decimal(6,2)
)
GO

INSERT Ventas_Sur
VALUES
('1', 'Laura', '4000'),
('2', 'Manuel', '900'),
('3', 'Dana', '8300'),
('4', 'Pamela', '750'),
('5', 'Lizeth', '2800'),
('6', 'Gladys', '3200'),
('7', 'Karla', '3200')
GO

SELECT * FROM Ventas_Sur


GO
CREATE TABLE Ventas_Oeste(
IdVenta Tinyint,
Vendedor Varchar(30),
Monto Decimal(6,2)
)
GO

INSERT Ventas_Oeste
VALUES
('1', 'Gisela', '4000'),
('2', 'C�sar', '900'),
('3', 'Juan', '8300'),
('4', 'Pamela', '7200')
GO

SELECT * FROM Ventas_Oeste


GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- III - UNION
-- Une los resultados de dos o m�s SELECT en un
-- solo conjunto de resultados.
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

-- Regla General:
-- > Cada select debe tener el mismo n�mero de columnas.
-- > Las columnas de cada tabla deben tener similar tipo de dato.
-- > Las columnas referenciadas deben estar en el mismo orden.

-- Note: El operador UNION selecciona distinto valores por defecto.


-- Para permitir valores duplicados, usamos UNION ALL.

-- 13
SELECT Vendedor FROM Ventas_Este
UNION
SELECT Vendedor FROM Ventas_Sur
GO -- En lugar de 12, salen 10, debido a que
-- Pamela y Karla tienen ventas registradas
-- en ambas zonas

-- 14
SELECT Vendedor FROM Ventas_Este
UNION ALL
SELECT Vendedor FROM Ventas_Sur
GO -- Salen los 12 registros, incluidas las ventas
-- de Pamela y Karla para ambas zonas.

-- 15
-- Si incluyo un campo adicional (por ejemplo el campo Monto),
-- la b�squeda se har�a con la dupla Vendedor/Monto la cual no tiene repeticiones
-- y har�a innecesaria la utilizaci�n de la cl�usula ALL si es que quiero ver
-- los 12 registros ya que Pamela y Karla tienen diferentes ventas en ambas zonas.

SELECT Vendedor, Monto FROM Ventas_Este


UNION
SELECT Vendedor, Monto FROM Ventas_Sur
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- IV - INTERSECT
-- Presenta los resultados que se repiten en cada
-- uno de los SELECT.
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

-- Regla General:
-- > Cada select debe tener el mismo n�mero de columnas.
-- > Las columnas de cada tabla deben tener similar tipo de dato.
-- > Las columnas referenciadas deben estar en el mismo orden.

-- 16
SELECT Vendedor FROM Ventas_Este
INTERSECT
SELECT Vendedor FROM Ventas_Sur
GO

-- 17
SELECT Vendedor FROM Ventas_Este
INTERSECT
SELECT Vendedor FROM Ventas_Sur
INTERSECT
SELECT Vendedor FROM Ventas_Oeste
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- V - EXCEPT
-- Presenta los resultados de la Primera Tabla
-- que no figuran en la Segunda o sucesivas Tablas.
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

-- Regla General:
-- > Cada select debe tener el mismo n�mero de columnas.
-- > Las columnas de cada tabla deben tener similar tipo de dato.
-- > Las columnas referenciadas deben estar en el mismo orden.

-- 18
SELECT Vendedor FROM Ventas_Este
EXCEPT
SELECT Vendedor FROM Ventas_Sur
GO -- Resultados:
-- Juan
-- Miguel
-- Pedro

-- 19
SELECT Vendedor FROM Ventas_Este
EXCEPT
SELECT Vendedor FROM Ventas_Sur
EXCEPT
SELECT Vendedor FROM Ventas_Oeste
GO -- Resultados:
-- Miguel
-- Pedro

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- VI - Vistas
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

-- Una vista es un objeto que almacena una consulta predefinida

-- Ventaja:
-- El usuario accede a la data apropiada para �l.
-- Con esto limitamos el acceso a data sensible.

-- Restricciones:
-- > No se puede definir una vista con ORDER BY, COMPUTE o SELECT INTO.
-- > No se puede hacer referencia a tablas temporales.

USE VENTAS
GO

-- 20 (Trabajar con la Consulta 12)

CREATE VIEW VW_ProductosEspeciales


AS

SELECT Des_pro FROM Tb_Producto P

LEFT JOIN ( SELECT DISTINCT DF.Cod_pro


From Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis='San Borja' OR
Nom_dis='Lince')
) PX on PX.Cod_pro=P.Cod_pro

WHERE PX.Cod_pro IS NULL


GO

-- A)
SELECT * FROM VW_ProductosEspeciales
GO

-- B)
SELECT * FROM VW_ProductosEspeciales WHERE Des_pro LIKE 'F%'
GO

-- C)
SELECT * FROM VW_ProductosEspeciales ORDER BY Des_pro ASC
GO

-- 21
-- Modificaremos la vista para que tambi�n excluya al distrito de San Miguel

ALTER VIEW VW_ProductosEspeciales


AS

SELECT Des_pro FROM Tb_Producto P

LEFT JOIN ( SELECT DISTINCT DF.Cod_pro


From Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis IN ('San Borja', 'Lince',
'San Miguel'))
) PX on PX.Cod_pro=P.Cod_pro

WHERE PX.Cod_pro IS NULL


GO

SELECT * FROM VW_ProductosEspeciales


GO

-- Generar el c�digo de una Vista

-- Expandir la Base de Datos Ventas (Men� de la Izquierda)


-- Expandir Vistas (Views)
-- Clic derecho a la vista dbo.VW_ProductosEspeciales
-- Script View as > Create To > New Query Editor Window

-- 22 WITH ENCRYPTION
-- Encriptar la Vista

ALTER VIEW VW_ProductosEspeciales WITH ENCRYPTION


AS

SELECT Des_pro FROM Tb_Producto P


LEFT JOIN ( SELECT DISTINCT DF.Cod_pro
From Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE C.Cod_dis IN (
SELECT Cod_dis FROM Tb_Distrito
WHERE Nom_dis IN ('San Borja', 'Lince',
'San Miguel'))
) PX on PX.Cod_pro=P.Cod_pro

WHERE PX.Cod_pro IS NULL


GO
-- Trate de ver nuevamente el c�digo de la Vista.
-- Ya no podr� verla.

-- 23 Crear una Vista para el Total de cada Factura.


-- Luego listar las Facturas con un Total superior al Promedio

CREATE VIEW VW_TotalporFactura


AS
SELECT Totales=SUM(Can_ven*Pre_ven)
FROM Tb_Detalle_Factura
GROUP BY Num_Fac
GO

SELECT * FROM VW_TotalporFactura


GO

SELECT * FROM VW_TotalporFactura


WHERE Totales>
(SELECT AVG(Totales) FROM VW_TotalporFactura)
GO

-- 24 Crear una vista para el Monto Total de todas las Facturas


-- por Cliente

CREATE VIEW VW_TotalFacturaporCliente


AS
SELECT F.Cod_cli, Raz_soc_cli, Totales=SUM(Can_ven*Pre_ven)
FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
GROUP BY F.Cod_cli
GO

SELECT * FROM VW_TotalFacturaporCliente


GO

-- 25 Cree una Vista similar a la anterior


-- pero ahora s�lo para clientes deudores.
CREATE VIEW VW_TotalFacturaporClienteDeudores
AS
SELECT F.Cod_cli, Raz_soc_cli, Totales=SUM(Can_ven*Pre_ven)
FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE Est_fac='1'
GROUP BY F.Cod_cli
GO

SELECT * FROM VW_TotalFacturaporClienteDeudores


GO

-- 26 Visualizar el c�digo de una Vista

sp_helptext VW_TotalporFactura
GO -- El c�digo es visible
-- ya que la vista no est� encriptada.

sp_helptext VW_ProductosEspeciales
GO

-- El c�digo no es visible
-- ya que la vista est� encriptada.

-- 27 Mostrar los objetos que dependen de una Vista

sp_depends VW_TotalporFactura
GO

sp_depends VW_ProductosEspeciales
GO

sp_depends Tb_Detalle_Factura
GO

-- 28 WITH CHECK OPTION

USE Zonas
GO

CREATE TABLE Clientes(


Id Int,
Nombre Varchar(20),
Estado Char(1)
)
GO

INSERT Clientes
VALUES
('1', 'Carla', 'A'),
('2', 'Hugo', 'C'),
('3', 'Paco', 'B'),
('4', 'Luis', 'A'),
('5', 'Diana', 'A'),
('6', 'Alberto', 'B'),
('7', 'Jenny', 'C'),
('8', 'Juan', 'C'),
('9', 'Melissa', 'A')
GO

-- Crearemos una Vista que nos muestre los Clientes


-- con Estado 'A' o 'C'

CREATE VIEW VW_ClientesAC


AS
SELECT ID, Nombre, Estado
FROM Clientes
WHERE Estado='A' or Estado='C'
GO

SELECT * FROM VW_ClientesAC


GO

-- Insertaremos un Cliente con Estado 'B' a trav�s de nuestra Vista.

INSERT VW_ClientesAC
VALUES
('10', 'Laura', 'B')
GO -- La Vista lo permite, pero lo ideal
-- es que no lo haga, ya que esta Vista s�lo
-- trabaja con Clientes con Estado 'A' o 'C'

-- L�gicamente, no podemos ver a Laura, pero su registro


-- fue insertado a trav�s de la Vista en el paso anterior.

SELECT * FROM VW_ClientesAC


GO

-- Haremos que la Vista trabaje para todos los casos s�lo con Estados 'A' y 'C'
-- Esto lo conseguimos con la Cl�usula WITH CHECK OPTION

ALTER VIEW VW_ClientesAC


AS
SELECT ID, Nombre, Estado
FROM Clientes
WHERE Estado='A' or Estado='C'
WITH CHECK OPTION
GO

-- Ya no debe dejarnos ingresar un Cliente con Estado 'B'

INSERT VW_ClientesAC
VALUES
('11', 'Tom', 'B')
GO
-- 29 Mostrar todas las Vistas de una Base de Datos

USE Ventas
GO

SELECT Name FROM SYSOBJECTS WHERE Type='V'


GO

-- Y si deseo mostrar todas las Tablas


SELECT Name FROM SYSOBJECTS WHERE Type='U'
GO
/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 9 TSQL
---------------------------------------*/

/*
_____|\
_.--| X |:
<____|.----||
.---''---,
;..__..' _...
,'/ ;|/..--'' \
,'_/.-/': :
_..-'''/ / | \ \ _|/|
\ /-./_ \; \ \,;' \
,\ / \: `:\ \ // `:`.
,' \ /-._; | : : :: ,. .
,' :: /`-._| | | || ' : `.`.)
_,' |;._:: | | | | `| : `'
,' `. / |`-:_ ; | | | : \
`--. ) /|-._: : | \ \
/ / :_| ;`-._; __..--'; : :
/ ( ;|;-./_ _/.-:'o | / ' |
/ , \._/_/_./--''/_|:|___|_,' |
: / `'-'--'----'---------' |
| : O ._O O_. O ._O O_. ; ;
: `. // // // // ,' /
~~ ~~~`.______//____//____//____//_______,'~ ~~ ~~
~~ // //~ // // ~~ ~~ ~~
~~ ~~ _// _// _// ~ _// ~ ~ ~ ~
~ / / / / / / / / ~ ~~ ~~ ~~
~~~ ~~~ ~~~ ~~~ ~~ ~~ ~~

*/

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- I - Programaci�n
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

/* Parte 1:
---------
Manejo de Variables Locales
----------------------------

Una variable local de Transact-SQL es un objeto que contiene un valor


individual de datos de un tipo espec�fico.

Normalmente, las variables se utilizan en lotes y scripts:

> Como contadores, para contar el n�mero de veces que se realiza


un bucle o controlar cu�ntas veces debe ejecutarse.

> Para contener un valor de datos que desea probar mediante


una instrucci�n de control de flujo.

> Para guardar el valor de un dato que se va a devolver en un


c�digo de retorno de un procedimiento almacenado o un valor
devuelto de una funci�n.
*/

SELECT 'Hola, Mundo!'


GO

PRINT 'Hola, Mundo!'


GO

--1 Escribir un programa que permita calcular el


-- promedio de dos notas enteras.

-- Declarar las variables


DECLARE @Nota1 INT
DECLARE @Nota2 INT
DECLARE @Prom DECIMAL(4,2)

-- Asignar valores a las variables


SET @Nota1=16
SET @Nota2=14

-- Proceso para calcular el promedio


SET @Prom=(@Nota1+@Nota2)/2

-- Salida de resultados
PRINT 'Fecha de evaluaci�n: '+ CAST(GETDATE() AS Varchar(20))
PRINT 'El promedio es: ' + CAST(@Prom AS Varchar(5))
GO

-- Cambiaremos las notas a 17 y 14

-- Declarar las variables


DECLARE @Nota1 INT
DECLARE @Nota2 INT
DECLARE @Prom DECIMAL(4,2)

-- Asignar valores a las variables


SET @Nota1=17
SET @Nota2=14

-- Proceso para calcular el promedio


SET @Prom=(@Nota1+@Nota2)/2.0 -- Si colocase 2 en lugar de 2.0
-- tendr�a como resultado 15.00 en lugar de 15.50
-- debido a que las variables Nota1 y Nota2
-- fueron declaradas como enteras.

-- Salida de resultados
PRINT 'Fecha de evaluaci�n '+ CAST(GETDATE() AS Varchar(20))
PRINT 'El promedio es: ' + CAST(@Prom AS Varchar(5))
GO

--2 Escribir un programa que permita calcular el


-- monto a pagar al comprar Equipos de C�mputo.

-- Se debe proporcionar :
-- > El Precio.
-- > La Cantidad a comprar.

-- Salida:
-- Fecha
-- Subtotal
-- IGV
-- T O T A L

-- Declarar las variables


DECLARE @Precio DECIMAL(7,2)
DECLARE @Cantidad INT
DECLARE @Igv DECIMAL(7,2)
DECLARE @Subtotal DECIMAL(7,2)
DECLARE @Total DECIMAL(7,2)

-- Asignar valores a las variables


SET @Precio=500
SET @Cantidad=30

-- Proceso
SET @Subtotal=(@Precio*@Cantidad)
SET @Igv=(@Subtotal*0.18)
SET @Total=(@Subtotal+@Igv)

-- Salida de resultados
PRINT 'Fecha de compra: '+ CAST(Getdate() AS Varchar(20))
PRINT 'El Subtotal es: '+CAST(@Subtotal AS Varchar(10))
PRINT 'El Igv del 18% es: '+CAST(@Igv AS Varchar(10))
PRINT 'El Total es: '+ CAST(@Total AS Varchar(10))
GO
-- Parte 2: Usando IF
------------------------

--3 Escribir un programa que permita calcular el promedio de dos notas enteras.
-- Mostrar el mensaje 'Aprobado' si el promedio es mayor o igual que 11.
-- En caso contrario mostrar 'Desaprobado'.

-- Declarar las variables


DECLARE @Nota1 INT
DECLARE @Nota2 INT
DECLARE @Prom DECIMAL(4,2)
DECLARE @Msj VARCHAR(20)

-- Asignar valores a las variables


SET @Nota1=16
SET @Nota2=5

-- Proceso para calcular el promedio y establecer el mensaje.


SET @Prom=(@Nota1+@Nota2)/2.00

IF(@Prom>=11)
BEGIN
SET @Msj='Aprobado'
END

ELSE
BEGIN
SET @Msj='Desaprobado'
END

-- Salida de resultados
PRINT 'Fecha de evaluaci�n '+ CAST(GETDATE() AS Varchar(20))
PRINT 'El promedio es: ' + CAST(@Prom AS Varchar(5))
PRINT 'Condici�n: ' + @Msj
GO

USE VENTAS
GO

-- 4 Contar Distritos
SELECT COUNT(*) FROM Tb_Distrito
GO

--
DECLARE @NumDis INT
SET @NumDis=(SELECT COUNT(*) FROM Tb_Distrito)
PRINT 'Tenemos '+ Convert(Varchar(10), @NumDis)+ ' distritos'
GO

-- 5 Contar Clientes
SELECT COUNT(*) FROM Tb_Cliente
GO
--
DECLARE @NumCli INT
SET @NumCli=(SELECT COUNT(*) FROM Tb_Cliente)
PRINT 'Tenemos '+ Convert(Varchar(10),@NumCli)+ ' clientes'
GO

-- 6 Hallar el Monto Total de todas las Facturas

--Declaraci�n de Variables
DECLARE @SumaMontoFacturas INT

--Asignando un Valor a la Variable


SET @SumaMontoFacturas = (SELECT SUM(Can_ven*Pre_ven)
FROM Tb_Detalle_Factura)

--Salida de Resultados
PRINT 'El Monto Total facturado es: ' + Convert(Varchar(10), @SumaMontoFacturas)
GO

--7 Guarde en una variable la Cantidad de �rdenes de Compras Atendidas


-- (Estado=1) por un determinado Proveedor.

--Declaraci�n de Variables
DECLARE @OC INT
DECLARE @Codprv CHAR(4)

--Asignando un Valor a las Variables


Set @Codprv='V009'
Set @OC = (SELECT COUNT(*)
FROM Tb_Orden_Compra
WHERE cod_prv=@codprv and Est_oco='1')

--Salida de Resultados
PRINT 'La cantidad de �rdenes de Compra atendidas por el Proveedor '
+ CAST(@Codprv AS Char(4)) + ' es: '+ CAST(@OC AS Varchar(2))
GO

-- 8 Guarde en una variable la deuda de un Cliente


-- (almacene el C�digo del Cliente en una variable tambi�n)
-- por concepto de Facturas Pendientes.
-- Pruebe con el Cliente C014 y luego con el C015.

--Declaraci�n de Variables
DECLARE @Deuda Smallmoney
DECLARE @Codcli Char(4)

--Asignamos Valores
SET @Codcli='C015'
SET @Deuda= (SELECT SUM(DF.Can_ven*DF.Pre_ven)
FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF
ON DF.Num_fac=F.Num_fac
WHERE F.cod_cli=@codcli AND F.est_fac='1')

--Imprimir la deuda
Print 'La deuda del cliente '+ @Codcli +
' es: ' + Convert(varchar(10),@Deuda)
GO

-- Nota: Los deudores son los clientes C014,


C015 y C019.
-- Si probamos con otros clientes, al no tener
deudas,
-- no se muestra ning�n tipo de resultado.

-- 9 En caso que el cliente no tenga deuda,


-- en vez de valor NULL imprima un 0.
-- Los deudores son C014, C015 y C019, as� que
-- probaremos con otros c�digos.

--Declaraci�n de Variables
DECLARE @Deuda Smallmoney
DECLARE @Codcli Char(4)

--Asignamos Valores
SET @Codcli='C001'
SET @Deuda= (SELECT SUM(DF.Can_ven*DF.Pre_ven)
FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF
ON DF.Num_fac=F.Num_fac
WHERE F.cod_cli=@codcli AND F.est_fac='1')

-- Proceso
IF @Deuda IS Null
Begin
SET @Deuda=0
End

--Imprimir la deuda
PRINT 'La deuda del cliente '+ @Codcli +
' es: ' + CONVERT(Varchar(10), @Deuda)
GO

-- [9b] Si personalizamos los PRINT

--Declaraci�n de Variables
DECLARE @Deuda Smallmoney
DECLARE @Codcli Char(4)

--Asignamos Valores
SET @Codcli='C001'
SET @Deuda= (SELECT SUM(DF.Can_ven*DF.Pre_ven)
FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF
ON DF.Num_fac=F.Num_fac
WHERE F.cod_cli=@codcli AND F.est_fac='1')

-- Proceso y Salida de Resultados


IF @Deuda IS Null
Begin
PRINT 'El Cliente '+ @Codcli + ' no registra deudas'
End
ELSE
Begin
-- Imprimir la deuda
PRINT 'La deuda del cliente '+ @Codcli +
' es: ' + CONVERT(Varchar(10), @Deuda)
End
GO

-- [9c]
-- La clase pasada se implement� una Vista que hallaba el
-- Total de Facturas para un Cliente Deudor.
-- Si no la tiene, ejec�tela a continuaci�n.

-- VW_TotalFacturaporClienteDeudores

CREATE VIEW VW_TotalFacturaporClienteDeudores


AS
SELECT F.Cod_cli, Totales=SUM(Can_ven*Pre_ven)
FROM Tb_Factura F
INNER JOIN Tb_Detalle_Factura DF ON F.Num_fac=DF.Num_fac
INNER JOIN Tb_Cliente C ON C.Cod_cli=F.Cod_cli
WHERE Est_fac='1'
GROUP BY F.Cod_cli
GO

SELECT * FROM VW_TotalFacturaporClienteDeudores


GO

--Ahora resolveremos el Ejercicio invocando a esta Vista

--Declaraci�n de Variables
DECLARE @Deuda Money
DECLARE @Codcli Char(4)

--Asignamos Valores
Set @Codcli='C001'
Set @Deuda= (SELECT Totales
FROM VW_TotalFacturaporClienteDeudores
WHERE Cod_cli=@Codcli)

-- Proceso y Salida de Resultados


IF @Deuda IS Null
Begin
PRINT 'El Cliente '+ @Codcli + ' no registra deudas'
End
ELSE
Begin
-- Imprimir la deuda
PRINT 'La deuda del cliente '+ @Codcli +
' es: ' + CONVERT(Varchar(10), @Deuda)
End
GO

-- 10
-- Calcule e imprima la Antig�edad de los Clientes.
-- Si es mayor o igual a 10 a�os imprima 'Cliente Antig�o' de lo contario
-- 'Cliente Nuevo'

--Declaraci�n de Variables
DECLARE @Antiguedad INT
DECLARE @Cod_cli CHAR(4)

--Asignamos Valores
SET @Cod_cli = 'C013'
SET @Antiguedad = (SELECT FLOOR(DATEDIFF(DAY, Fec_reg, GETDATE())/365.25)
FROM Tb_cliente
WHERE @Cod_cli=Cod_cli)

--Salida de Resultados
PRINT 'La Antig�edad del Cliente es de '+ CAST(@Antiguedad AS Varchar(2))+ ' a�os.'

IF @Antiguedad >=10
Begin
PRINT 'El Cliente '+ @Cod_cli + ' es un Cliente Antiguo'
End
ELSE
Begin
PRINT 'El Cliente '+ @Cod_cli + ' es un Cliente Nuevo'
End
GO

-- 11
-- Determine la sgte regla de negocio para una determinada factura
-- (almacene el n�mero de factura en una variable):
--
-- Si se cancel� (Estado 2) en un tiempo menor o igual a 10 d�as:
-- > Si el Monto es menor a 120, el descuento ser� el 10% del monto
-- > En caso contrario, el descuento ser� del 15%
--
-- Si se cancel� luego de 10 d�as:
-- > No se aplica descuento

-- Con la factura F019 debe salir cero, con la F008 sale 370.20, etc

-- Declaraci�n de variables
DECLARE @Num_fac CHAR(5)
DECLARE @Tiempo INT
DECLARE @Total DECIMAL(8,2), @Dcto DECIMAL(8,2)

--Asignaci�n de Variables
SET @Num_fac ='FA019'
--C�lculos
SET @Tiempo= (SELECT DATEDIFF (DAY, Fec_fac, Fec_can)
FROM Tb_Factura
WHERE Num_fac=@Num_fac AND Est_fac='2')

IF @Tiempo<=10
--Aplicamos descuento
Begin
SET @Total=(SELECT SUM(Can_ven*Pre_ven)
FROM Tb_Detalle_Factura
WHERE Num_fac=@Num_fac
GROUP BY Num_fac)

IF @Total <120
Begin
SET @Dcto=@Total*0.1
End
ELSE
Begin
SET @Dcto=@Total*0.12
End
End
ELSE
Begin
-- No hay descuento
SET @Dcto=0
End

--Imprimir
Print 'El descuento es : ' + Convert(Varchar(10), @Dcto)
GO

-- Parte 3: Estructura Repetitiva WHILE


-------------------------------------------

-- 12 Imprime tu nombre 50 veces

DECLARE @Contador SMALLINT


SET @Contador = 1

WHILE @Contador <= 50


Begin
PRINT 'Erick Tamayo'
SET @Contador= @Contador + 1
End
GO

-- 13 Listar los 100 primeros n�meros

DECLARE @Num INT


SET @Num=1

WHILE (@Num)<=100
Begin
PRINT 'El n�mero es: '+CONVERT(Varchar(3),@Num)
SET @Num=@Num+1
End
GO

-- Escapar al llegar al n�mero 17


DECLARE @Num INT
SET @Num=1

WHILE (@Num)<=100
Begin
PRINT 'El n�mero es: '+CONVERT(Varchar(3),@Num)
SET @Num=@Num+1

IF @Num=17
Begin
BREAK
End

End
GO

-- 14 Imprimir la suma de los n�meros del 1 al 100

DECLARE @Valor INT, @Suma INT

Set @Valor=1
Set @Suma=0

WHILE @Valor<=100
Begin
SET @Suma=@Suma+@valor
SET @Valor=@valor+1
Print @Suma
End

SELECT ' La sumatoria de los primeros 100 numeros es: ', @suma
GO

-- 15 Calcule el Factorial de un n�mero

DECLARE @Numero INT, @Valor INT, @Factorial BIGINT

SET @Numero=20
SET @Valor=1
SET @Factorial=1

WHILE @Valor<=@Numero
Begin
SET @Factorial=@Factorial*@Valor
SET @Valor=@Valor+1
End
SELECT ' El factorial de ' + Convert(Varchar(4), @Numero) + ' es: ', @Factorial
GO

-- 16 Imprima 10 n�meros enteros al azar


-- Dichos n�meros deben estar comprendidos entre 1 y 70

DECLARE @Contador SMALLINT


SET @Contador = 1

WHILE @Contador <= 10


Begin
PRINT FLOOR(RAND()*70+1)
SET @Contador= @Contador + 1
End
GO

-- 17 Actualizar el precio en 25% de aquellos productos


-- que est�n por debajo del promedio

--Copiamos la Tabla Producto a una Tabla Nueva llamada Mercader�a


SELECT * INTO Mercader�a
FROM Tb_Producto
GO

SELECT * FROM Mercader�a


GO

SELECT AVG(Pre_pro) FROM Mercader�a


GO -- El precio promedio de todos los productos
-- es 20.425

-- Si vamos a actualizar los productos cuyo precio es


-- superior al precio promedio, se actualizar�an los productos
-- P003, P004, P007 y del P009 al P019.

--Esto resulta, pero es ineficiente.


UPDATE Mercader�a
SET Pre_pro=Pre_pro*1.25
WHERE Pre_pro<(SELECT AVG(Pre_pro) FROM Mercader�a)
GO

SELECT * FROM Mercader�a


GO

--Esto es m�s r�pido y m�s eficiente


DECLARE @Prom float

SET @Prom=(SELECT AVG(Pre_pro) FROM Mercader�a)

UPDATE Mercader�a
SET Pre_pro=Pre_pro*1.25
WHERE Pre_pro<@Prom
GO

SELECT * FROM Mercader�a


GO

--18 Llenar una Tabla con N�meros Aleatorios

-- Caso: Queremos generar N�meros al Azar entre 1 y 5.

-- Si ejecutamos varias veces el siguiente SELECT, tendremos n�meros entre 0 y 5.


-- pero nunca CERO y nunca 5.

SELECT RAND()*5
GO --Ej: 0.45, 1.23, 3.7, 4.95, etc.

--Por eso sumamos UNO para asegurarnos que se llegue a 5 y no sea menor a 1.

SELECT RAND()*5+1
GO -- Nunca saldr� un n�mero menor a 1 y ya aparece 5, pero
-- tambi�n aparecer� valores como 5.70, 5.98, etc.

--Para solucionar lo anterior (se est� pasando de 5)


--
SELECT FLOOR(RAND()*5+1)
GO --Los �nicos resultados son 1,2,3,4 y 5.

-- Creamos la Tabla Temporal #Usuarios


CREATE TABLE #Usuarios(
Columna INT
)
GO

SELECT * FROM #Usuarios


GO

-- Insertaremos 50 registros con N�meros Enteros al Azar


-- entre 1 y 1000

DECLARE @Contador INT


DECLARE @Registrorandom INT

SET @Contador=1

WHILE @Contador<=50
Begin
SET @Registrorandom = FLOOR(RAND()*1000 + 1)

INSERT #Usuarios
VALUES(@Registrorandom)

SET @Contador=@Contador+1
End
GO

-- Comprobamos
SELECT * FROM #Usuarios
GO

-- Vemos cu�ntos registros al azar se repiten


SELECT DISTINCT * FROM #Usuarios
GO

--19 NewID es una mejor opci�n para aleatoriedad


-- ya que se basa en el n�mero MAC de tu computadora

--Aparecen N�meros y Letras


SELECT NEWID()
GO

--S�lo N�meros (sean Positivos o Negativos)


SELECT CHECKSUM(NEWID())
GO

--S�lo N�meros Positivos


SELECT ABS(CHECKSUM(NEWID()))
GO

--Limitarlos del 1 al 10
SELECT ABS(CHECKSUM(NEWID())) % 10+1
GO

--Limitarlos del 1 al 50
SELECT ABS(CHECKSUM(NEWID())) % 50+1
GO

--Limitarlos del 1 al 1000


SELECT ABS(CHECKSUM(NEWID())) % 100+1
GO

-- Para incluirlo en un INSERT, UPDATE, etc, utilizar esta estructura:


-- Aqu� por ejemplo quiero generar n�meros al azar hasta 100 000
SELECT ABS(CAST(NEWID() AS BINARY(6)) % 100000) + 1
GO

-- Creamos la Tabla Temporal #Usuarios2

CREATE TABLE #Usuarios2(


Columna INT
)
GO

SELECT * FROM #Usuarios2


GO

-- Insertaremos 50 registros con N�meros Enteros al Azar


-- entre 1 y 1000
DECLARE @Contador INT
DECLARE @Registrorandom INT

SET @Contador=1

WHILE @Contador<=50
Begin
SET @Registrorandom = ABS(CAST(NEWID() AS BINARY(6)) % 1000) + 1

INSERT #Usuarios2
VALUES(@Registrorandom)

SET @Contador=@Contador+1
End
GO

-- Comprobamos
SELECT * FROM #Usuarios2
GO

-- Vemos cu�ntos registros al azar se repiten


SELECT DISTINCT * FROM #Usuarios2
GO

-- 20 Res�menes de nuestras facturas

USE Ventas
GO

SET LANGUAGE SPANISH


GO

DECLARE @Facturas INT


DECLARE @Total_ventas DECIMAL(10,2)
DECLARE @Promedio_facturas DECIMAL(10,2)
DECLARE @Facturas_Pendientes INT

SET @Facturas=(SELECT COUNT(*) FROM Tb_Factura)

SET @Total_ventas=(SELECT SUM(Can_ven*Pre_ven)


FROM Tb_Detalle_Factura)

SET @Promedio_facturas=(SELECT SUM(Can_ven*Pre_ven)/(SELECT COUNT(*) FROM


Tb_Factura)
FROM Tb_Detalle_Factura) --Para que divida
entre 20 facturas.
--Si usaba AVG,
divid�a entre 47
--ya que
Tb_Detalle_Factura tiene
--47 registros.
SET @Facturas_Pendientes=(SELECT COUNT(*) FROM Tb_Factura
WHERE Est_fac=1)

PRINT
'Hoy ' + DATENAME(weekday, getdate())+' '
+ CAST(DATEPART(DAY,getdate()) as VARCHAR(2))+' de '
+ DATENAME(MONTH, getdate())+' del '
+ CAST(DATEPART(YEAR,getdate()) AS CHAR(4))

PRINT 'Tenemos '+ Convert(varchar(10), @Facturas)+ ' facturas'

PRINT 'Con un total de ventas de ' +Convert(Varchar(10), @total_ventas) + ' soles'


PRINT 'Con un promedio por factura de ' +Convert(Varchar(10), @Promedio_facturas) +
' soles'
PRINT 'Existen ' +Convert(Varchar(10),@facturas_Pendientes) + ' facturas
pendientes'
GO

-- 21 Mostrar una lista de productos e incrementar su precio en 25%


-- mientas que el precio promedio sea menor a 100

SELECT * INTO Productos


FROM Tb_Producto
GO

SELECT * FROM Productos


GO

--Comprobar primero en Excel

WHILE (SELECT AVG(PRE_PRO) FROM Productos) < 100


BEGIN
--Listamos
SELECT COD_PRO,DES_PRO,PRE_PRO
FROM Productos

SELECT AVG(PRE_PRO) AS 'Promedio antes de Actualizar' FROM Productos

--Actualizamos
UPDATE Productos
SET PRE_PRO = PRE_PRO * 1.25
END
GO

-- El �ltimo promedio antes de actualizar fue de 97.3939895629883


-- Como dicho promedio es menor que 100, realiz� una �ltima
-- actualizaci�n de 25% en el precio de todos los productos

SELECT * FROM PRODUCTOS


GO

-- El promedio actual es 121.742486190796


SELECT AVG(Pre_pro) FROM Productos
GO
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- II- Manejo de Excepciones (Control de Errores)
-- Estructura Begin Try - Begin Catch
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

--22

-- Sin manejo de excepci�n


PRINT 1/0
GO

-- Con manejo de excepci�n


BEGIN TRY
PRINT 1/0
END TRY

BEGIN CATCH
PRINT 'No est� definida la divisi�n por cero'
END CATCH
GO

-- 23 Utilizando los mensajes de error


BEGIN TRY
PRINT 1/0
END TRY

BEGIN CATCH
PRINT ERROR_NUMBER()
PRINT ERROR_MESSAGE()
END CATCH
GO

-- 24

SELECT * INTO Vendedores


FROM Tb_Vendedor
GO

SELECT * FROM Vendedores


GO

SET DATEFORMAT DMY


GO

ALTER TABLE Vendedores


ADD CONSTRAINT Pk_Vendedores
PRIMARY KEY (cod_ven)
GO
Sp_helpconstraint Vendedores
GO

-- Inserci�n manejando la Excepci�n


BEGIN TRY
INSERT Vendedores
VALUES('V01','Paul','Sosa', 1700,'04/04/2004','1')
PRINT 'Vendedor insertado'
End TRY

BEGIN CATCH
PRINT 'Tenemos el error: ' + CAST(Error_Number() AS VARCHAR(5))
PRINT Error_Message()
End CATCH
GO

-- Insertarlo como el Vendedor V90


BEGIN TRY
INSERT Vendedores
VALUES('V90','Paul','Sosa', 1700,'04/04/2004','1')
PRINT 'Vendedor insertado'
End TRY

BEGIN CATCH
PRINT 'Tenemos el error: ' + CAST(Error_Number() AS VARCHAR(5))
PRINT Error_Message()
End CATCH
GO

-- 25

SELECT * INTO Abastecimientos


FROM Tb_Abastecimiento
GO

SELECT * FROM Abastecimientos


GO

ALTER TABLE Abastecimientos


ADD CONSTRAINT Pk_Abastecimientos
PRIMARY KEY(Cod_prv, Cod_pro)
GO

ALTER TABLE Productos


ADD CONSTRAINT Pk_Productos
PRIMARY KEY(Cod_pro)
GO

ALTER TABLE Abastecimientos


ADD CONSTRAINT FK_Abastecimientos_Productos
FOREIGN KEY (Cod_pro)
REFERENCES Productos
GO

Sp_helpconstraint Abastecimientos
GO

-- Error con Valor Nulo(515)


INSERT Abastecimientos VALUES ('V002',NULL, 40 )
GO

-- Error con Campo que sobrepasa el Ancho de Columna (8152)


INSERT Abastecimientos VALUES ('V002','P0002', 40 )
GO

-- Error por Integridad Referencial


INSERT Abastecimientos VALUES ('V002','P900', 40)
GO

-- Con manejo de Excepciones


BEGIN TRY
INSERT Abastecimientos VALUES ('V002',NULL, 40 )
INSERT Abastecimientos VALUES ('V002','P0002', 40 )
INSERT Abastecimientos VALUES ('V002','P900', 40 )
INSERT Abastecimientos VALUES ('V003','P001', 40 )
PRINT 'Se insertaron los registros correctamente'
END TRY

BEGIN CATCH
IF ERROR_NUMBER() = 515
PRINT 'Algunas columnas no admiten nulos'
ELSE
IF ERROR_NUMBER() = 8152
PRINT 'Se ha sobrepasado el tama�o de un campo'
ELSE
PRINT 'Error por Integridad Referencial'
END CATCH
GO

SELECT * FROM Abastecimientos


GO

-- NOTA: Para ver la lista de Mensajes de Error

SELECT m.message_id, m.severity, m.is_event_logged, m.[text]


FROM sys.messages m
INNER JOIN sys.syslanguages l ON m.language_id = l.msglangid
WHERE l.alias = 'Spanish'
ORDER BY m.severity DESC, m.[text]
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- III- Funciones
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
/* Funciones Creadas por SQL
-------------------------

Deterministas:
Las funciones deterministas devuelven siempre el mismo resultado
cada vez que se invocan con un conjunto espec�fico de valores de entrada
y cuando el estado de la base de datos es el mismo.

Ej: Left, Count, Avg, Sum, Day, Month, etc.

No Deterministas:
Las funciones no deterministas pueden devolver resultados diferentes
cada vez que se llaman con un conjunto espec�fico de valores de entrada
aunque el estado de la base de datos a la que tienen acceso
permanezca sin cambios.

Ej: Getdate, Rand, etc.


*/

-- FUNCIONES ESCALARES
-- Da un solo resultado por registro

-- 27 Saber si un a�o es Bisiesto

/* Las reglas para que un a�o sea bisiesto son:


> Divisible entre 4
> No divisible entre 100 o Divisible entre 400
*/

CREATE FUNCTION EsBisiesto(@Fecha DATE)


RETURNS VARCHAR(11)
AS
BEGIN

DECLARE
@A�o INT,
@Bisiesto VARCHAR(11)

SET @A�o = YEAR(@fecha)

IF @A�o % 4 = 0 AND (@A�o % 100 <> 0 OR @A�o % 400 = 0)


BEGIN
SET @Bisiesto = 'Bisiesto'
END
ELSE
BEGIN
SET @Bisiesto = 'No Bisiesto'
END

RETURN @Bisiesto
END
GO

-- Probando
SELECT dbo.EsBisiesto('10/10/2000')
SELECT dbo.EsBisiesto('01/01/2003')
GO

-- 28 Una Funci�n que permita hallar el primer d�a del mes


-- de una fecha dada

-- Por ejemplo, dada la fecha 11/08/2013,


-- hallar el primer d�a del mes de dicha fecha.

SELECT
DATEADD(dd,-(DAY('11/08/2013')-1),'11/08/2013')
GO

-- Crearemos nuestra funci�n

CREATE FUNCTION uf_PrimerDiaMes(@Fecha_ingr DATE)


RETURNS DATE
AS
BEGIN
DECLARE @Fecha_resp DATE
SET @Fecha_resp=DATEADD(dd,-(DAY(@Fecha_ingr)-1),@Fecha_ingr)
RETURN @Fecha_resp
END
GO

-- Probando
SELECT dbo.uf_PrimerDiaMes('04/06/2008')
SELECT dbo.uf_PrimerDiaMes('17/10/2009')
GO

--Funci�n nueva a partir de Sql 2012, DATEFROMPARTS


SELECT DATEFROMPARTS(YEAR(getdate()),MONTH(getdate()),1)
GO

-- 29 Una funci�n que nos de el �ltimo d�a del mes de una fecha

CREATE FUNCTION uf_UltimoDiaMes(@Fecha_ingr DATE)


RETURNS DATE
AS
BEGIN
DECLARE @Fecha_resp DATE

SET @Fecha_ingr= dbo.uf_PrimerDiaMes(@Fecha_ingr)

SET @Fecha_resp = DATEADD(Day, -1, DATEADD(Month, 1, @Fecha_ingr))

RETURN @Fecha_resp
END
GO
-- Probando
SELECT dbo.uf_UltimoDiaMes('04/06/2008')
SELECT dbo.uf_UltimoDiaMes('17/10/2009')
SELECT dbo.uf_UltimoDiaMes('02/02/2010')
SELECT dbo.uf_UltimoDiaMes('02/02/2012')
GO

-- Aplicado a la tabla Factura


SELECT fec_fac, dbo.uf_UltimoDiaMes(fec_fac) AS [Ultimo Dia Mes]
FROM Tb_Factura
GO

-- Usando Convert 103


SELECT fec_fac,
CONVERT(VARCHAR(10), dbo.uf_UltimoDiaMes(fec_fac), 103) AS [Ultimo Dia Mes]
FROM Tb_Factura
GO

--PD: En SQL Server 2012, ya existe la funci�n EOMONTH

SELECT EOMONTH ( GETDATE() ) AS 'Este Mes'


SELECT EOMONTH ( GETDATE(), 1 ) AS 'Siguiente Mes'
SELECT EOMONTH ( GETDATE(), -1) AS 'Mes Pasado'
GO

-- 30 Una funci�n que nos de el Fin de mes (en letras) de una fecha dada

CREATE FUNCTION uf_FinMesLetras (@Fecha DATE)


RETURNS VARCHAR(30)
AS

BEGIN
DECLARE @Nombre VARCHAR(30)
SET @Nombre=
CASE DATENAME(MONTH, @Fecha)
WHEN 'Enero' THEN ('31 de Enero')
WHEN 'Febrero' THEN
CASE
WHEN dbo.EsBisiesto(@Fecha)='No Bisiesto' THEN('28 de
Febrero')
ELSE '29 de Febrero'
END
WHEN 'Marzo' THEN ('31 de Marzo')
WHEN 'Abril' THEN ('30 de Abril')
WHEN 'Mayo' THEN ('31 de Mayo')
WHEN 'Junio' THEN ('30 de Junio')
WHEN 'Julio' THEN ('31 de Julio')
WHEN 'Agosto' THEN ('31 de Agosto')
WHEN 'Septiembre' THEN ('30 de Septiembre')
WHEN 'Octubre' THEN ('31 de Octubre')
WHEN 'Noviembre' THEN ('30 de Noviembre')
WHEN 'Diciembre' THEN ('31 de Diciembre')
END -- End del Case

SET @Nombre= @Nombre +' del '+ CAST(YEAR(@Fecha) AS CHAR(4))

RETURN @Nombre
END
GO

-- Probando
SELECT dbo.uf_FinMesLetras('04/06/2008')
SELECT dbo.uf_FinMesLetras('17/10/2009')
SELECT dbo.uf_FinMesLetras('02/02/2010')
SELECT dbo.uf_FinMesLetras('02/02/2012')
GO

-- Aplicado a la Tabla factura


SELECT Fec_fac, dbo.uf_FinMesLetras(Fec_fac) AS '�ltimo D�a h�bil'
FROM Tb_Factura
GO

-- LIMBO: Algunos casos propuestos acerca de Fechas en la vida real

-- A Diferencia en d�as, meses y a�os de dos fechas dadas


-- B �El primer Viernes de cada mes?
-- C �Primer y �ltimo d�a de cada semana?
-- D �Cada 3 Mi�rcoles a partir de una fecha dada?
-- E �Qu� d�a cay� la quincena del mes de una fecha dada?
-- F �Imprimir todos los meses entre dos fechas?
-- G �Listar todas las fechas entre dos fechas?
-- Etc...

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 10 TSQL
---------------------------------------*/

/*

/~ ~\
|_ |
|/ __-__
\ /~ ~~-_
~~ -~~\ ~\
/ | \
, / / \
// _ _---~~~ //-_ \
/ (/~~ ) _____/-__ ~-_ _-\ _________
/ _-~\\0) ~~~~ ~~-_ \__--~~ `\ ___---~~~ /'
/_-~ _-/' )~/ /'
(___________/ _-~/' _-~~/ _-~
_ ----- _~-_\\\\ _-~ /' __--~ (_ ______---~~~--_
_-~ ~-_~\\\\ ( ( -_~ ~-_ | ~-_
/~~~~\ \ \~~ ~-_ ~-_ ~\ ~~--__-----_ \
; / \ ______-----\ ~-__~-~~~~~~--_ ~~--_ \ .
| | \((*)~~~~~~~~~~| __--~~ ~-_ ) | |
| \ |~|~---------)__--~~ \_____________/ / ,
\ ~-----~ / /~ ) \ ~-----~ /
~-_ _-~ /_______________________________/ `-_ _-~
~ ----- ~ ~ ----- ~

*/

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- I- Seguimos con las Funciones
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

USE VENTAS
GO

-- 01 Crear una Funci�n que calcule el Total de una Factura

CREATE FUNCTION uf_CalcularFactura (@Num_fac CHAR(5))


RETURNS DECIMAL(10,2)
AS
Begin
RETURN (SELECT SUM(Pre_ven*Can_ven)
FROM Tb_Detalle_Factura
WHERE Num_fac=@Num_fac)
End
GO

-- Probando la Funci�n
SELECT dbo.uf_CalcularFactura('FA007')
GO

SELECT Num_fac, fec_fac, dbo.uf_CalcularFactura(Num_fac) AS 'Total'


FROM Tb_Factura
GO

SELECT Num_fac, fec_fac, dbo.uf_CalcularFactura(Num_fac) AS 'Total'


FROM Tb_Factura
WHERE Num_fac='FA007'
GO

-- 02 Crear una Funci�n que nos muestre el Nombre del Cliente y su RUC

CREATE FUNCTION uf_NombreCompleto


(@Cod_cli varchar(4))
RETURNS varchar(100)
AS
Begin
RETURN (SELECT Raz_soc_cli +' Ruc N�: '+Ruc_cli
FROM dbo.Tb_Cliente
WHERE Cod_cli=@Cod_cli)
End
GO
-- Probando la Funci�n
SELECT dbo.uf_NombreCompleto('C014')
GO

SELECT Num_fac, dbo.uf_NombreCompleto(Cod_cli) AS 'Cliente'


FROM Tb_Factura
GO

SELECT Num_fac, dbo.uf_NombreCompleto(Cod_cli) AS 'Cliente'


FROM Tb_Factura
WHERE Cod_cli='C014'
GO

-- 03 Funci�n que retorne la Comisi�n de un Vendedor de acuerdo a sus Ventas:

-- a) Si el Monto es < que 500, la Comisi�n es del 5% del Monto


-- b) Si el Monto es >= que 500 y menor que 1200 ser� del 10% del Monto
-- c) En otro caso se aplicara el 15% de Comisi�n

CREATE FUNCTION ObtenerComision(@Monto MONEY)


RETURNS money
AS
Begin
DECLARE @Com money
IF @Monto<500
SET @Com=@Monto*0.05
ELSE
IF @Monto<1200
SET @Com=@Monto*0.1
ELSE
SET @Com=@Monto*0.15

RETURN @Com
End
GO

-- Probando la Funci�n
SELECT dbo.ObtenerComision(400) --Menos de 500. Su 5% es 20.
SELECT dbo.ObtenerComision(1000) --Menos de 1200. Su 10% es 100.
SELECT dbo.ObtenerComision(2000) --De 1200 en adelante. Su 15% es 300.
GO

-- Aplicado a la Base de Datos Ventas


CREATE FUNCTION ObtenerComision2(@Cod_ven CHAR(3))
RETURNS Money
AS
Begin
DECLARE @Com Money
DECLARE @Monto Money

SET @Monto=(SELECT SUM(dbo.uf_CalcularFactura(Num_Fac))


FROM Tb_Factura
WHERE Cod_ven=@Cod_ven)

IF @Monto<500
SET @Com=@Monto*0.05
ELSE
IF @Monto<1200
SET @Com=@Monto*0.1
ELSE
SET @Com=@Monto*0.15

RETURN @Com
End
GO

-- Probando la Funci�n
SELECT dbo.ObtenerComision2('V01')
GO

SELECT Nom_ven+' '+Ape_ven AS 'Vendedor', dbo.ObtenerComision2(Cod_ven) AS


'Comisi�n'
FROM Tb_Vendedor
GO

-- Vendedor 10 tiene dos facturas;


-- FA008 por 3085 soles y FA018 por 290 soles.
-- 3085 + 290 = 3375 15% de 3375 = 506.25

SELECT Nom_ven+' '+Ape_ven AS 'Vendedor', dbo.ObtenerComision2(Cod_ven) AS


'Comisi�n'
FROM Tb_Vendedor
WHERE Cod_ven='V10'
GO

-- Reutilizando Funciones
CREATE FUNCTION ObtenerComision3(@cod_ven CHAR(3))
RETURNS MONEY
AS
Begin
DECLARE @Com MONEY
DECLARE @Monto MONEY

SET @Monto=(SELECT SUM(dbo.uf_CalcularFactura(Num_Fac))


FROM Tb_Factura F
WHERE Cod_ven=@Cod_ven)

SET @Com=(SELECT dbo.ObtenerComision(@Monto))

RETURN @Com
End
GO

-- Probando la Funci�n
SELECT dbo.ObtenerComision3('V01')
GO

SELECT Nom_ven+' '+Ape_ven AS 'Vendedor', dbo.ObtenerComision3(Cod_ven) AS


'Comisi�n'
FROM Tb_Vendedor
GO

--05 Funci�n que calcule la deuda de un Cliente en base a sus


-- Facturas pendientes de Pago

CREATE FUNCTION CalcularDeuda(@Codcli CHAR(4))


RETURNS MONEY
AS

Begin
DECLARE @Deuda MONEY

SET @Deuda=(SELECT SUM(dbo.uf_CalcularFactura(Num_fac))


FROM Tb_Factura
WHERE Cod_cli=@Codcli AND Est_fac='1') -- 1 es No cancelada

IF @Deuda IS NULL
SET @Deuda=0

RETURN @Deuda
END
GO

-- Probando la Funci�n
SELECT Cod_cli, Raz_soc_cli, dbo.CalcularDeuda(Cod_cli) AS 'Deuda'
FROM Tb_Cliente
WHERE dbo.calcularDeuda(Cod_cli)>0
GO

--06 Una Funci�n que halle el Mejor Precio de Abastecimiento

-- Por ejemplo, el producto P001 nos venden a 28 y a 27 soles.


SELECT Cod_pro, Pre_aba FROM Tb_Abastecimiento
WHERE Cod_pro='P001'
GO

-- De los dos, el mejor precio ser�a 27


SELECT TOP 1 Cod_pro, Pre_aba FROM Tb_Abastecimiento
WHERE Cod_pro='P001'
ORDER BY Pre_Aba ASC
GO

-- Creando la Funci�n
CREATE FUNCTION uf_MejorPrecioAbas (@Cod_pro CHAR(4))
RETURNS MONEY
AS
Begin
DECLARE @Aba MONEY

SET @Aba=(SELECT TOP 1 Pre_Aba


FROM Tb_Abastecimiento
WHERE Cod_pro=@Cod_pro
ORDER BY Pre_Aba ASC)

IF @Aba is null
SET @Aba =0

RETURN @Aba
End
GO

-- Probando la Funci�n
SELECT Cod_pro, Des_pro, Pre_pro AS 'Precio Venta',
dbo.uf_MejorPrecioAbas(Cod_pro) AS 'Mejor Precio Abast.'
FROM Tb_Producto
GO

SELECT Cod_pro, Des_pro, Pre_pro AS 'Precio Venta',


dbo.uf_MejorPrecioAbas(Cod_pro) AS 'Mejor Precio Abast.',
Pre_pro-dbo.uf_MejorPrecioAbas(Cod_pro) AS 'Ganancia'
FROM Tb_Producto
GO

-- Necesitamos las funciones PrimerDiaMes y UltimoDiaMes

-- PrimerDiaMes
CREATE FUNCTION uf_PrimerDiaMes(@Fecha_ingr DATE)
RETURNS DATE
AS
BEGIN
DECLARE @Fecha_resp DATE
SET @Fecha_resp=DATEADD(dd,-(DAY(@Fecha_ingr)-1),@Fecha_ingr)
RETURN @Fecha_resp
END
GO

--UltimoDiaMes
CREATE FUNCTION uf_UltimoDiaMes(@Fecha_ingr DATE)
RETURNS DATE
AS
BEGIN
DECLARE @Fecha_resp DATE
SET @Fecha_ingr= dbo.uf_PrimerDiaMes(@Fecha_ingr)
SET @Fecha_resp = DATEADD(Day, -1, DATEADD(Month, 1, @Fecha_ingr))
RETURN @Fecha_resp
END
GO

-- 07 Una Funci�n que calcule el Total de las Compras de


-- un Cliente realizadas durante el Mismo Nes
-- de una Fecha dada

CREATE FUNCTION CalcularCompras (@Codcli CHAR(4), @Fecha_ing DATE)


RETURNS MONEY
AS

Begin
DECLARE @Compra MONEY

SET @Compra=(SELECT SUM(dbo.uf_CalcularFactura(Num_fac))


FROM dbo.Tb_Factura
WHERE Cod_cli=@Codcli
AND Fec_Fac BETWEEN
dbo.uf_PrimerDiaMes(@Fecha_ing) AND
dbo.uf_UltimoDiaMes(@Fecha_ing))

IF @Compra IS NULL
SET @Compra=0

Return @Compra
End
GO

--Establecemos
SET DATEFORMAT DMY
GO

-- Probando la Funci�n
SELECT Cod_cli, dbo.CalcularCompras(cod_cli, '05/01/2010') AS 'Total'
FROM Tb_Factura
GO

-- Uso DISTINCT ya que hay varias facturas de un mismo


-- cliente en el mismo mes y s�lo necesito mostrar el total una vez
-- Ej: Cliente C015 que tiene 2 facturas en Enero 2010

SELECT DISTINCT cod_cli, dbo.CalcularCompras(Cod_cli, '05/01/2010') AS 'Total'


FROM Tb_Factura
WHERE dbo.CalcularCompras(cod_cli, '05/01/2010')<>'0'
ORDER BY cod_cli
GO

--En casa adapte la funci�n con Eomonth

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- II- Manejo de Transacciones
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
/*
Una transacci�n es un conjunto de modificaciones de datos
que deben ser procesados como una unidad.

Al ejecutarse como un solo bloque, la idea es que si una de las operaciones


falla, todas deben fallar.
*/

-- MANEJO DE BATCHS

-- 08 PruebaBatch
--A)
CREATE TABLE PruebaBatch(
ColA INT,
ColB CHAR(3) NOT NULL
)
GO

-- B) Ejecutar ambos, INSERT y SELECT

INSERT PruebaBatch VALUES ('1', 'AAA')


INSERT PruebaBatch VALUES ('2', 'BBB')
INSERT PruebaBatch VALEUS ('3', 'CCC') --Error Sintaxis

SELECT * FROM PruebaBatch


GO

--C) Ejecutar ambos, INSERT y SELECT


INSERT PruebaBatch VALUES ('1', 'AAA')
INSERT PruebaBatch VALUES ('2', 'BBB')
INSERT PruebaBatch VALEUS ('3', 'CCC') --Error Sintaxis
GO

SELECT * FROM PruebaBatch


GO

--D) Ejecutar primero los INSERT. Luego el SELECT

INSERT PruebaBatch VALUES ('1', 'AAA')


INSERT PruebaBatch VALUES ('2', 'BBB')
INSERT PruebaBatc VALUES('3', 'CCC') --Error Sintaxis
GO

SELECT * FROM PruebaBatch -- 1er y 2do INSERT s�


GO -- 3er INSERT no
-- El motor usa resoluci�n diferida de nombres
-- No verifica los nombres hasta el final
-- TRANSACCIONES IMPL�CITAS

-- Se inicia autom�ticamente una nueva Transacci�n cuando se


-- ejecuta una instrucci�n que realiza modificaciones en los datos,
-- pero cada transacci�n se completa expl�citamente con una instrucci�n
-- COMMIT o ROLLBACK.

-- 09 PruebaBatch2

CREATE TABLE PruebaBatch2(


ColA INT,
ColB CHAR(3) NOT NULL
)
GO

-- Inicio el modo de Transacci�n Impl�cita


SET IMPLICIT_TRANSACTIONS ON
GO

INSERT PruebaBatch2 VALUES ('1', 'AAA')


INSERT PruebaBatch2 VALUES ('2', 'BBB')
INSERT PruebaBatch2 VALUES ('3', 'CCC')
GO

SELECT * FROM PruebaBatch2


GO

-- Cancelaremos la transacci�n
ROLLBACK TRANSACTION
GO

SELECT * FROM PruebaBatch2


GO

--Confirma la transacci�n del �ltimo SELECT


COMMIT TRANSACTION
GO

-- Desactivo el modo de Transacci�n Impl�cita


SET IMPLICIT_TRANSACTIONS OFF
GO

-- Nota:
-- Obligatoriamente Toda Transacci�n debe terminar con:
-- > ROLLBACK TRANSACTION: Si es que la vamos a deshacer.
-- > COMMIT TRANSACTION: Si es que la vamos a confirmar.

-- 10 PruebaBatch3

-- Inicio el modo de Transacci�n Impl�cita


SET IMPLICIT_TRANSACTIONS ON
GO

CREATE TABLE PruebaBatch3(


ColA INT,
ColB CHAR(3) NOT NULL
)

INSERT PruebaBatch3 VALUES ('1', 'AAA')


INSERT PruebaBatch3 VALUES ('2', 'BBB')
INSERT PruebaBatch3 VALUES ('3', 'CCC')
GO

SELECT * FROM PruebaBatch3


GO

-- Cancelaremos la transacci�n
ROLLBACK TRANSACTION
GO

SELECT * FROM PruebaBatch3


GO

--Confirma la transacci�n del �ltimo SELECT


COMMIT TRANSACTION
GO

-- Desactivo el modo de Transacci�n Impl�cita


SET IMPLICIT_TRANSACTIONS OFF
GO

-- 11 Batch4

-- Inicio el modo de Transacci�n Impl�cita


SET IMPLICIT_TRANSACTIONS ON
GO

CREATE TABLE PruebaBatch4(


ColA INT,
ColB CHAR(3) NOT NULL
)
GO

INSERT PruebaBatch4 VALUES ('1', 'AAA')


INSERT PruebaBatch4 VALUES ('2', 'BBB')
INSERT PruebaBatch4 VALUES ('3', 'CCC')
GO

SELECT * FROM PruebaBatch4


GO

--�Hay transacciones activas?


SELECT @@TRANCOUNT
GO

-- Cancelaremos la transacci�n
ROLLBACK TRANSACTION
GO

--�Hay transacciones activas?


SELECT @@TRANCOUNT
GO

SELECT * FROM PruebaBatch3


GO

--�Hay transacciones activas?


SELECT @@TRANCOUNT
GO

--Confirma la transacci�n del �ltimo SELECT


COMMIT TRANSACTION
GO

--�Hay transacciones activas?


SELECT @@TRANCOUNT
GO

-- Desactivo el modo de Transacci�n Impl�cita


SET IMPLICIT_TRANSACTIONS OFF
GO

/*

Cuando estemos trabajando con Transacciones Impl�citas podr�a


suceder que en alg�n momento olvidemos hacer el COMMIT TRANSACTION
correspondiente originando m�s adelante transacciones grandes,
y posiblemente provocando bloqueos con otras conexiones,
o teniendo ROLLBACKs indeseados debido a conexiones cerradas.

Se recomienda no olvidar realizar el COMMIT TRANSACTION


o ROLLBACK TRANSACTION
cuando trabaje en este modo.

*/

-- TRANSACCIONES EXPL�CITAS

-- Cada transacci�n se inicia expl�citamente con la instrucci�n


-- BEGIN TRANSACTION y se termina expl�citamente con una instrucci�n
-- COMMIT o ROLLBACK.

SELECT * INTO Facturas


FROM Tb_Factura
GO

SELECT * FROM Facturas


GO

ALTER TABLE Facturas


ADD CONSTRAINT Pk_Facturas
PRIMARY KEY(Num_Fac)
GO

SELECT * INTO DetallesFac


FROM Tb_Detalle_Factura
GO

SELECT * FROM DetallesFac


GO

ALTER TABLE DetallesFac


ADD CONSTRAINT Pk_DetallesFacs
PRIMARY KEY(Num_Fac, Cod_pro)
GO

ALTER TABLE DetallesFac


ADD CONSTRAINT FK_DetallesFac_Facturas
FOREIGN KEY (Num_fac)
REFERENCES Facturas
GO

-- 12 Insertando una Factura

-- Para que la Factura se inserte correctamente, tanto la cabecera


-- (Tabla Facturas) como sus detalles (Tabla DetallesFac) deben
-- insertarse correctamente.

-- Si alguno de estos elementos no se inserta correctamente,


-- toda la operaci�n aborta (ROLLBACK TRANS)
-- de lo contrario, se confirma (COMMIT TRANS)

SET DATEFORMAT DMY


GO

-- A) Transacci�n hasta antes de SQL 2005


Begin Transaction

INSERT Facturas
VALUES ('FA050','02/05/2008','C001','02/06/2008','2','V02',0.19)

INSERT DetallesFac VALUES


('FA050','P001',10,25),
('FA050','P005',50,5),
('FA0500','P007',8,50)

IF (@@Error<> 0) GOTO Error_Capturado


Else
Commit Transaction
RETURN --RETURN se utiliza para salir inmediatamente de un lote
--las instrucciones despu�s de RETURN no se ejecutan

Error_Capturado:
RollBack Transaction
GO

-- Veamos
SELECT * FROM Facturas
GO

SELECT * FROM DetallesFac


GO

-- B) Transacci�n con Manejo de excepciones (SQL 2005, 2008, 2012)

Begin Try
Begin Transaction

INSERT Facturas
VALUES ('FA070','02/05/2008','C001','02/06/2008','2','V02',0.19)

INSERT DetallesFac VALUES


('FA070','P001',10,25),
('FA070','P005',50,5),
('FA0700','P007',8,50)

Commit Transaction
Print 'Factura Insertada'
End Try

Begin Catch
RollBack Transaction
Print 'Tenemos el error ' + CAST(Error_number() AS VARCHAR(5))
+ ': '+ Error_message()
Print 'No se insert� ni la cabecera ni los detalles'
End Catch
GO

-- No fue insertada la Factura en la Tabla Facturas


SELECT * FROM Facturas
GO

-- No fueron insertados los Detalles de la Factura en DetallesFac


SELECT * FROM DetallesFac
GO

-- Necesitamos trasladar la cierta informaci�n a las siguientes Tablas


SELECT * INTO Abastecimientos
FROM Tb_Abastecimiento
GO

SELECT * FROM Abastecimientos


GO

ALTER TABLE Abastecimientos


ADD CONSTRAINT Pk_Abastecimientos
PRIMARY KEY(Cod_prv, Cod_pro)
GO

SELECT * INTO Productos


FROM Tb_Producto
GO

SELECT * FROM Productos


GO

ALTER TABLE Productos


ADD CONSTRAINT Pk_Productos
PRIMARY KEY(Cod_pro)
GO

ALTER TABLE Abastecimientos


ADD CONSTRAINT FK_Abastecimientos_Productos
FOREIGN KEY (Cod_pro)
REFERENCES Productos
GO
--

-- 13 Insertando un nuevo producto y sus proveedores.


-- Para que un producto se inserte correctamente, tanto el nuevo
-- registro como el de sus proveedores (en la tabla Abastecimientos)
-- deben insertarse correctamente.
-- Si alguno de estos elementos no se inserta correctamente,
-- toda la operacion aborta (ROLLBACK TRANS), de lo contrario,
-- se confirma (COMMIT TRANS).

Begin Try
Begin Transaction
Insert Productos values ('P092','Calculadora',50,30,10,'UNI','1',0)
Insert Abastecimientos values('V001','P090',98.5)
Insert Abastecimientos values('V007','P090',99)
Insert Abastecimientos values('V045','P090',96.8)
Commit Transaction
Print 'Producto Insertado'
End Try

Begin Catch
RollBack Transaction
Print 'Tenemos el error ' + CAST(error_number() AS VARCHAR(5))
+ ': '+ error_message()
Print 'No se insert� el producto ni sus proveedores'
End Catch
GO

-- No fue insertado en la Tabla Productos


SELECT * FROM Productos
GO

-- No fueron insertados los proveedores en la Tabla Abastecimientos


SELECT * FROM Abastecimientos
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- III- Procedimientos Almacenados
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

/*
Un Procedimiento Almacenado (Stored Procedure) es un Programa
(o Procedimiento) el cual es almacenado f�sicamente en una Base de Datos.

Los procedimientos almacenados no son mas que una sucesion ordenada de


instrucciones T-SQL que pueden recibir y devolver parametros provistos
por el usuario y se pueden guardar en el servidor con un nombre, para luego
poder invocarlos y ejecutarlos.

Algunas de las ventajas de usar procedimientos almacenados


----------------------------------------------------------

> Compilaci�n: La primera vez que se invoca un procedimiento almacenado,


el motor lo compila y a partir de ah�, se sigue usando la version compilada
del mismo, hasta que se modifique o se reinicie el servicio de SQL.
Esto hace que que tengan un mejor rendimiento que las consultas directas
que usan cadenas con instrucciones T-SQL, que el motor compila cada vez que se
invoca.

> Automatizaci�n: Si tenemos un conjunto de instrucciones T-SQL que queremos


ejecutar en un orden, los stored procedures son el espacio ideal para hacerlo.

> Administraci�n: Si hacemos buen uso de los procedimientos almacenados,


muchas veces alg�n cambio en nuestra aplicaci�n, solo implica modificar
un stored procedure y no toda la aplicaci�n.
Si nuestra aplicaci�n llama a los stored procedures, con solo cambiarlo
en el servidor, ya tenemos todo funcionado sin la necesidad de actualizar
la aplicaci�n en todos los equipos cliente.

> Seguridad: Otra ventaja que tienen es que permiten aplicar un esquema
de seguridad mas potente, haciendo que los usuarios que usen nuestra aplicaci�n,
s�lo tengan permisos para ejecutar procedimientos almacenados y no a todos los
objetos de la base. De esta forma si un hacker encuentra una vulnerabilidad
(SQL Injection) en nuestra aplicaci�n, no podra explotarla ejecutando comandos SQL
directamente sobre la base, ya que el usuario con el cual se ejecuta la aplicaci�n
s�lo tiene derecho a la ejecucion de los procedimientos almacenados en la
base de datos.

> Programabilidad: Los procedimientos almacenados admiten el uso de variables


y estructuras de control como IF, Bucles, Case, etc. Adem�s de el manejo de
transacciones, que permiten que los stored procedures sean aplicables para
escribir logica del negocio en los mismos.

Trafico de Red: Pueden reducir el trafico de la red, debido a que se trabaja


sobre el motor (en el servidor), y si una operaci�n incluye hacer un trabajo
de lectura primero y en base a eso realizar algunas operaciones, esos datos
que se obtienen no viajan por la red.

*/

-- 14 Elabore un Stored Procedure que permita saber el nombre de los Distritos


-- que cubre determinado Vendedor.
CREATE PROCEDURE USP_DISTRITOS_CUBRE_VENDEDOR (@Vendedor CHAR(3))
AS
Begin
SELECT Nom_dis FROM dbo.Tb_Distrito
WHERE @Vendedor=Cod_ven
End
GO

-- Probando el Stored Procedure


EXEC USP_DISTRITOS_CUBRE_VENDEDOR 'V04'
GO

-- Elabore un Procedimiento que determine el N�mero de Facturas


-- vencidas de un Cliente.

CREATE PROCEDURE USP_FACTURAS_VENCIDAS


(@Codcli CHAR(4)
)
AS
Begin
SELECT COUNT(Num_fac) FROM dbo.Tb_Factura
WHERE Est_fac='1' AND Cod_cli=@Codcli
End
GO

-- Probando el Stored Procedure


EXEC USP_FACTURAS_VENCIDAS @Codcli='C019'
GO

-- �El ejercicio anterior, quedar�a como Procedimiento o Funci�n?

--15 Cree un Procedimiento que permita visualizar los n�meros de factura,


-- fecha de facturaci�n y cancelaci�n, as� como el total de las facturas
-- generadas por un determinado clientes.

CREATE PROCEDURE USP_VISUALIZAR (@Codcli CHAR(4))


AS

Begin
SELECT Num_Fac, Fec_fac, Fec_can,
dbo.uf_CalcularFactura(Num_Fac) AS 'Total'
FROM Tb_Factura
WHERE Cod_cli=@CodCli
End
GO

-- Probando el Stored Procedure


EXEC USP_VISUALIZAR @Codcli='C001'
GO
EXEC USP_VISUALIZAR @Codcli='C019'
GO

-- Manejando el que no haya cancelado a�n

ALTER PROCEDURE USP_VISUALIZAR (@Codcli CHAR(4))


AS

Begin
SELECT Num_Fac, Fec_fac,
IsNull(CAST(Fec_can AS VARCHAR(30)), 'No cancel� a�n'),
dbo.uf_CalcularFactura(Num_Fac) AS 'Total'
FROM Tb_Factura
WHERE Cod_cli=@CodCli
End
GO

-- Probando el Stored Procedure


EXEC USP_VISUALIZAR @Codcli='C001'
GO

EXEC USP_VISUALIZAR @Codcli='C019'


GO

-- �Podr�a hacer que las que son fechas se vean como fechas y los null
-- con el correspondiente mensaje?

---------------------------------
--/SQL VARIANT/--
---------------------------------

CREATE TABLE Variedad(


Id SMALLINT,
Dato SQL_VARIANT)
Go

-- Si es un n�mero que va a ser usado en operaciones matem�ticas,


-- colocarlo sin comillas.

Insert Variedad (Id, Dato)


Values
('1', 'HOLA')
GO

Insert Variedad (Id, Dato)


Values
('2', 2000)
GO

Insert Variedad (Id, Dato)


Values
('3', '1/12/2000')
GO
Insert Variedad (Id, Dato)
Values
('4', 50000)
GO

SELECT * FROM Variedad


GO

--Al sumar
SELECT SUM(Dato) FROM Variedad
GO

--Al contar
SELECT COUNT(Dato) FROM Variedad
GO

--En el caso de LIKE, sql_variant no soporta LIKE


SELECT Dato FROM Variedad
WHERE Dato LIKE 'H%'
GO

--Sobre la Suma
SELECT SUM(CAST(Dato AS DECIMAL(10, 2)))
FROM Variedad
WHERE Sql_Variant_Property(Dato, 'Basetype')
IN ('Int', 'Smallint', 'Tinyint', 'Bigint', 'Decimal', 'Numeric', 'Float')
GO

-- Resolviendo lo solicitado

ALTER PROCEDURE USP_VISUALIZAR (@Codcli nvarchar(4))


AS

Begin
SELECT Num_Fac, Fec_fac,
CASE
WHEN Fec_can IS NULL
THEN IsNull(CAST(Fec_can AS SQL_VARIANT), 'No cancel� a�n')
ELSE Fec_can
END AS 'Cancelaci�n',
dbo.uf_CalcularFactura(Num_Fac) AS 'Total'
FROM Tb_Factura
WHERE Cod_cli=@CodCli
End
GO

-- Probando el Stored Procedure


EXEC USP_VISUALIZAR @Codcli='C001'
GO

EXEC USP_VISUALIZAR @Codcli='C019'


GO
-- 16 Elabore un Store Procedure que elimine un determinado Cliente
-- si �ste no ha generado Factura alguna.

CREATE PROCEDURE USP_ELIMINA_CLIENTE (@CODCLI CHAR(4))


AS

IF EXISTS (SELECT COD_CLI


FROM TB_CLIENTE WHERE COD_CLI=@CODCLI)
BEGIN
IF EXISTS (SELECT COD_CLI FROM TB_FACTURA WHERE COD_CLI=@CODCLI)
PRINT 'CLIENTE TIENE FACTURAS, NO SERA ELIMINADO'
ELSE
BEGIN
PRINT 'EL CLIENTE SERA DADO DE BAJA'
DELETE FROM TB_CLIENTE
WHERE COD_CLI=@CODCLI
END
END
ELSE
PRINT 'CLIENTE NO EXISTE'
GO

--Insertando un Cliente sin facturas


INSERT Tb_Cliente
VALUES
('C050', 'Nestle', 'Av Sol', NULL, '20', 'D01', '2010', '1', 'Liz')
GO

SELECT * FROM TB_CLIENTE


GO

-- Probando el Procedimiento Almacenado


EXEC USP_ELIMINA_CLIENTE 'C001'
GO

EXEC USP_ELIMINA_CLIENTE 'C050'


GO

SELECT * FROM TB_CLIENTE


GO

-- 17 Incremente el Precio de Art�culos Importados en un 10%


-- y en un 7% el Precio de los Nacionales que abastezca
-- un determinado Proveedor.

-- Importado=1, Nacional=0

CREATE PROCEDURE USP_INCREMENTA_PRECIO (@CODPRV CHAR(4))


AS
Begin
UPDATE TB_PRODUCTO
SET PRE_PRO =PRE_PRO * 1.1
WHERE COD_PRO IN (SELECT COD_PRO
FROM TB_ABASTECIMIENTO
WHERE COD_PRV=@CODPRV) AND IMPORTADO=1

UPDATE TB_PRODUCTO SET PRE_PRO =PRE_PRO * 1.07


WHERE COD_PRO IN (SELECT COD_PRO
FROM TB_ABASTECIMIENTO
WHERE COD_PRV=@CODPRV) AND IMPORTADO=0
End
GO

-- Proveedor V009 abastece al


-- producto P002, cuyo precio de venta es 35 y es Nacional (0)
-- producto P014, cuyo precio de venta es 20 y es Importado (1)
SELECT * FROM Tb_Abastecimiento
GO

SELECT * FROM Tb_Producto


WHERE Cod_pro='P002' OR Cod_pro='P014'
GO

-- Probando el Stored Procedure


EXEC USP_INCREMENTA_PRECIO 'V009'
GO

SELECT * FROM Tb_Producto


WHERE Cod_pro='P002' OR Cod_pro='P014'
GO

-- Update M�ltiple
UPDATE Tb_Producto
SET Pre_pro= CASE cod_pro
WHEN 'P002' THEN '35'
WHEN 'P014' THEN '20'
END
WHERE Cod_pro in ('P002', 'P014')
GO

--
SELECT * FROM Tb_Producto
WHERE Cod_pro='P002' OR Cod_pro='P014'
GO

-- 18 Construya un Stored Procedure que devuelva la raz�n social,


-- direcci�n, tel�fono de los proveedores que abastecen un determinado
-- producto, as� como el nombre y precio de abastecimiento de dicho producto.

CREATE PROCEDURE USP_PROVEEDORES_PRODUCTO (@COD_PRO CHAR (4))


AS
SELECT RAZ_SOC_PRV AS 'Proveedor', --Tabla Proveedor
DIR_PRV AS 'Direcci�n', --Tabla Proveedor
TEL_PRV AS 'Tel�fono', --Tabla Proveedor
Des_pro AS 'Producto', --Tabla Producto
Pre_Aba AS 'Precio Abast.' --Tabla Producto
FROM TB_ABASTECIMIENTO A
INNER JOIN Tb_Proveedor P ON A.COD_PRV = P.Cod_prv
INNER JOIN Tb_Producto X ON A.COD_PRO = X.Cod_pro
WHERE X.Cod_pro=@COD_PRO
GO

-- Probando el Stored Procedure


EXEC USP_PROVEEDORES_PRODUCTO 'P002'
GO

------------------------------------

CREATE DATABASE DATA


GO

USE Data
GO

-- 19 Crear un store procedure que seleccione el c�digo, nombres y apellidos


-- de alumnos que pertenecen a una determinada escala y como par�metro de salida

-- indique cuantos son.

SELECT * FROM TB_Alumno


GO

CREATE PROCEDURE USP_ALUMNOS


(
@Escala CHAR(1),
@TotalAlumnos INT OUTPUT
)
AS
Begin
SELECT Cod_Alumno,
Nombre+', '+Ape_Pater+' '+Ape_Mater AS 'Nombres y Apellidos'
FROM TB_Alumno
WHERE Cod_escala=@Escala

SET @TotalAlumnos=(SELECT COUNT(Cod_Alumno)


FROM TB_Alumno
WHERE Cod_escala=@Escala)

PRINT 'La cantidad de alumnos es: '+ CONVERT(VARCHAR(2), @TotalAlumnos)


End
GO

-- Probando el Stored Procedure


EXEC USP_ALUMNOS 'A', 0
GO

--20 Construya un Stored Procedure que permita saber como Par�metro de Salida
-- cu�ntos alumnos han aprobado y desaprobado un determinado Curso.

SELECT * FROM Tb_Detalle_Alumno


GO
CREATE PROCEDURE USP_APROBADOS_DESAPROBADOS
(
@Curso VARCHAR(3),
@Aprobados INT OUTPUT,
@Desaprobados INT OUTPUT
)

AS
Begin
SET @Aprobados=(SELECT COUNT (Cod_Curso) FROM TB_Detalle_Alumno
WHERE Cod_Curso=@Curso AND (Parcial+Final)/2.00>=11)

SET @Desaprobados=(SELECT COUNT (Cod_Curso) FROM TB_Detalle_Alumno


WHERE Cod_Curso=@Curso AND (Parcial+Final)/2.00<11)

PRINT 'La cantidad de alumnos aprobados es: '+CONVERT(VARCHAR(2), @Aprobados)

PRINT 'La cantidad de alumnos desaprobados es: '+CONVERT(VARCHAR(2),


@Desaprobados)
End
GO

-- Probando el Stored Procedure


EXEC USP_APROBADOS_DESAPROBADOS 'C04', 0, 0
GO

-- 21 Elabore un Stored Procedure que permita insertar un nuevo Curso.


-- Si el c�digo del Curso ya existe enviar el mensaje respectivo
-- y no agregar el Curso.

SELECT * FROM TB_Curso


GO

CREATE PROCEDURE USP_INSERTAR_CURSO


(
@Cod_Curso CHAR(3),
@Nom_curso varchar(30),
@Num_Creditos smallint
)
AS
Begin
IF @Cod_Curso = (SELECT Cod_Curso
FROM TB_Curso
WHERE @Cod_Curso=Cod_curso)

PRINT 'Curso ya Existe!'

ELSE
INSERT Tb_Curso(Cod_Curso,Nom_Curso,Num_creditos)
VALUES (@Cod_curso, @Nom_curso, @Num_Creditos)
End
GO

-- Probando el Stored Procedure


EXEC USP_INSERTAR_CURSO 'C19', 'Dise�o Web', 5
GO

EXEC USP_INSERTAR_CURSO 'C26', 'Dise�o Web', 5


GO

SELECT * FROM TB_Curso


GO

SELECT * FROM TB_Curso


ORDER BY Cod_Curso
GO

-- 22 Elabore un store procedure que dado un c�digo de t�tulo,


-- devuelva cuantos libros disponibles y no disponibles existen de dicho titulo.

SELECT * FROM Tb_Titulo --Nombre abstracto


GO

SELECT * FROM TB_Libro --Libro f�sico


GO

CREATE PROCEDURE USP_TITULO_LIBROS_DISPONIBLES_Y_NO


(
@Cod_Titulo varchar(3),
@Disponibles INT OUTPUT,
@NoDisponibles INT OUTPUT
)
AS

--Disponible=0 significa No disponible


--Disponible=1 significa Disponible
Begin
SET @NoDisponibles=(SELECT COUNT(Cod_Libro) FROM TB_Libro
WHERE Cod_Titulo=@Cod_Titulo AND Disponible=0)
PRINT 'El t�tulo '+@Cod_Titulo+' tiene '
+CONVERT(VARCHAR(2), @NoDisponibles)+' libros No Disponibles'

SET @Disponibles=(SELECT COUNT(Cod_Libro) FROM TB_Libro


WHERE Cod_Titulo=@Cod_Titulo AND Disponible=1)
PRINT 'El t�tulo '+@Cod_Titulo+' tiene '
+CONVERT(VARCHAR(2), @Disponibles)+' libros Disponibles'
End
GO

-- Probando el Stored Procedure


EXEC USP_TITULO_LIBROS_DISPONIBLES_Y_NO 'T03',0,0
GO

EXEC USP_TITULO_LIBROS_DISPONIBLES_Y_NO 'T04',0,0


GO

-- 23 Construya un Stored Procedure que devuelva el promedio de un alumno


-- en un determinado curso. Si el curso no ha sido llevado por el alumno
-- que se envi� un mensaje que as� lo indique.

SELECT * FROM TB_Detalle_Alumno


GO

CREATE PROCEDURE USP_PROMEDIO_ALUMNO_CURSO


(
@Alumno varchar(4),
@Curso varchar(3)
)
AS
Begin
IF @Curso NOT IN(SELECT Cod_Curso
FROM TB_Detalle_Alumno
WHERE Cod_Curso=@Curso AND Cod_Alumno=@Alumno)
PRINT 'Curso no ha sido llevado a�n por el alumno '+CONVERT(VARCHAR(4),
@Alumno)
ELSE
SELECT Cod_Alumno, Cod_Curso, (Parcial+Final)/2.00 AS Promedio
FROM TB_Detalle_Alumno
WHERE @Alumno=Cod_Alumno AND @Curso=Cod_Curso
End
GO

-- Probando el Stored Procedure


EXEC USP_PROMEDIO_ALUMNO_CURSO 'A001', 'C03'
GO

EXEC USP_PROMEDIO_ALUMNO_CURSO 'A001', 'C04'


GO

-- 24 Crear un Stored Procedure que permita visualizar los n�meros de boletas,


-- el c�digo del libro y el nombre del titulo alquilado en las boletas de
-- un determinado alumno.

SELECT * FROM TB_Boleta --De aqu� necesito Nro_Boleta


GO

SELECT * FROM TB_Libro --De aqu� necesito Cod_libro


GO

SELECT * FROM TB_Titulo --De aqu� necesito Nom_Titulo


GO
CREATE PROCEDURE USP_BOLETAS_ALUMNOS (@Alumno varchar(4))
AS
Begin
SELECT Nro_Boleta, B.Cod_Libro AS 'Libro F�sico', Nom_Titulo AS 'T�tulo'
FROM TB_Boleta B
INNER JOIN Tb_Libro L ON B.Cod_Libro=L.Cod_Libro
INNER JOIN TB_Titulo T ON L.Cod_Titulo=T.Cod_Titulo
WHERE Cod_Alumno=@Alumno
ORDER BY Nro_Boleta
End
GO

-- Probando el Stored Procedure


EXEC USP_BOLETAS_ALUMNOS 'A001'
GO

-- 25 Elabore un Stored Procedure que permita seleccionar los nombres de titulos,


-- nombre y apellido del autor de t�tulos y cantidad de libros existentes
-- de un determinado tema.

SELECT * FROM TB_Autor


GO

SELECT * FROM TB_Titulo


GO

CREATE PROCEDURE USP_LIBROS_TEMA


(@Tema CHAR(5),
@Cantidad INT OUTPUT)
AS
Begin
SELECT Cod_Tema, Nom_Autor+' '+ Ape_Autor AS 'Autor', Nom_Titulo AS 'T�tulo'
FROM TB_Autor A, TB_Titulo T
WHERE A.Cod_Autor=T.Cod_Autor AND Cod_Tema=@Tema
ORDER BY Autor

SET @Cantidad=(SELECT COUNT(Cod_Tema) FROM TB_Titulo WHERE @Tema=Cod_Tema)


PRINT 'La cantidad de libros del tema '+@Tema+' es '+CONVERT(VARCHAR(2),
@Cantidad)
End
GO

-- Probando el Stored Procedure


EXEC USP_LIBROS_TEMA 'M05',0
GO

EXEC USP_LIBROS_TEMA 'M02',0


GO

-- Nota: En lugar de INNER JOIN (ANSI SQL 92 Standard),


-- us� simplemente un WHERE con el s�mbolo Igual (ANSI SQL 89 Standard),
-- lo cual a�n se puede usar, pero es mejor hacerlo con JOIN
-- para que los Where s�lo sean dedicados a los filtros y la lectura
-- del c�digo sea m�s legible.

/*---------------------------------------
Profesor: Ing. F. Erick Tamayo
E-mail: f.erick.tamayo@gmail.com
Curso: Base de Datos
Sesi�n 11 TSQL
---------------------------------------*/

/*

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'~~~ ~~~`@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@' `@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@ n, @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@ _/ | _ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@ /' `'/ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@a <~ .' a@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@ .' | @@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@a _/ | a@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@a _/ `.`. a@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@a ____/ ' \__ | |______ a@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@a__/___/ /__\ \ \ \___.a@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@/ (___.'\_______)\_|_| \@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@|\________ ~~~~~\@@@@@@@@@@@@@@@@@@
~~~\@@@@@@@@@@@@@@|| |\___________________________/|@/~~~~~~~~~~~\@@@
|~~~~\@@@@@@@/ | | | | | ||\____________|@@

*/

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- I- Seguimos con los Stored Procedure
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

CREATE DATABASE CLASEFINAL


GO
USE CLASEFINAL
GO

CREATE TABLE Distrito(


IDDistrito CHAR(3) NOT NULL PRIMARY KEY,
Nombre VARCHAR(30) NOT NULL
)
GO

INSERT Distrito
VALUES
('D01', 'San Isidro'),
('D02', 'Ate'),
('D03', 'Barranco')
GO

SELECT * FROM Distrito


GO

--No acepta Nulos la Columna IDDistrito


INSERT Distrito
VALUES
(NULL, 'Los Olivos')
GO

--No acepta Nulos la Columna IDDistrito


INSERT Distrito
VALUES
('D04', NULL)
GO

-- 01 Crear un Stored Procedure que exija el ingreso de todos los campos


-- a la Tabla Distrito, de lo contrario no debe permitir la inserci�n
-- de un registro

CREATE PROCEDURE usp_Prueba


(@IDDistrito CHAR(3),
@Nombre VARCHAR(30))
AS
BEGIN
IF(@IDDistrito IS NULL OR @Nombre IS NULL)
BEGIN
PRINT 'Debe ingresar todos los par�metros'
RETURN 1
END

INSERT Distrito(IDDistrito, Nombre)


VALUES(@IDDistrito, @Nombre)
RETURN 0 -- �xito
END
GO

--Probando si ingreso uno de los par�metros como NULL


EXECUTE usp_Prueba NULL, 'Los Olivos'
GO

--Probando si no ingreso uno de los par�metros


EXECUTE usp_Prueba 'D04'
GO
-- Como ve, si no ingreso uno de los par�metros
-- exigidos por el Stored Procedure, �ste no procede
-- a ejecutarse.

-- �xito
EXECUTE usp_Prueba 'D04', 'Los Olivos'
GO

--Comprobando
SELECT * FROM Distrito
GO

-- 02 Mejorando el SP anterior
-- Stored Procedure "PruebaCompleta"

CREATE PROCEDURE usp_PruebaCompleta


(@IDDistrito CHAR(3)=NULL, --Inicializo ambas variables como NULL
@Nombre VARCHAR(30)=NULL)
AS
BEGIN
IF(@IDDistrito IS NULL OR @Nombre IS NULL)
BEGIN
PRINT 'Debe ingresar todos los par�metros'
END
RETURN 1

INSERT Distrito(IDDistrito, Nombre)


VALUES(@IDDistrito, @Nombre)

RETURN 0 -- �xito
END
GO

--Probando la nulidad de los par�metros


EXECUTE usp_PruebaCompleta NULL, 'Lince'
GO

EXECUTE usp_PruebaCompleta 'D05'


GO

-- Tenemos a�n 4 distritos


SELECT * FROM Distrito
GO
--CASO:
----

--Insertamos Lince
INSERT Distrito
VALUES
('D05', 'Lince')
GO

-- Tenemos 5 distritos
SELECT * FROM Distrito
GO

--Insertemos nuevamente Lince en el SP


EXECUTE usp_PruebaCompleta 'D05', 'Lince'
GO

--�Comandos Completados Correctamente?


--Pero si es PK...
--�Aparecer� dos veces el registro D05 Lince?

--Veamos
SELECT * FROM Distrito
GO

--En realidad no se insert� el registro repetido al ejecutar el �ltimo Procedure.


--Entonces, �por qu� afirma que los comandos fueron realizados correctamente?
--�Por qu� no vemos la alerta de infraci�n de retricci�n PRIMARY KEY?

--Lo que sucede es que nuestro SP termina con la instrucci�n Return 0


--Eso quiere decir que si llegamos a esa parte del c�digo es porque
--se han cumplido todas las reglas anteriores (la �nica regla que dimos
--es que las columnas no admitan nulos), sin interesarle al SP si se est�n
--transgrediendo reglas propias de la Tabla como los Constraints (PK, FK, CK, DF,
U)
--y es por ello que no vemos la alerta de infraci�n de la Restricci�n PRIMARY KEY

--Si usted crea un SP sin RETURNs, puede ver las alertas normales de infracci�n.

--03 SP sin RETURNs

CREATE PROCEDURE usp_PruebaCompletaSinReturn


(@IDDistrito CHAR(3)=NULL, --Inicializo ambas variables como NULL
@Nombre VARCHAR(30)=NULL)
AS
BEGIN
IF(@IDDistrito IS NULL OR @Nombre IS NULL)
BEGIN
PRINT 'Debe ingresar todos los par�metros'
END

INSERT Distrito(IDDistrito, Nombre)


VALUES(@IDDistrito, @Nombre)
END
GO
-- Insertemos nuevamente Lince en el SP

-- Nuestro SP no considera una alerta personalizada para la infracci�n de PK


-- por lo cual vemos la alerta propia de SQL Server
EXECUTE usp_PruebaCompletaSinReturn 'D05', 'Lince'
GO

-- Probemos el ingreso de Nulos con nuestro SP


EXECUTE usp_PruebaCompletaSinReturn NULL, 'Lince'
GO

-- Debido a que no se ingresaron todos los par�metros, vemos el mensaje


-- configurado por nosotros "Debe ingresar todos los par�metros".

-- Al no tener RETURN 1 para el error con respecto a los nulos, vemos nuestro
-- mensaje personalizado, pero tambi�n vemos el Mensaje de Error de SQL Server
-- predeterminado para estos casos (Mensaje 515)

-- 04 SP que permita insertar un registro a la Tabla Distrito:

--01 Nulidad de los Par�metros


--02 Validar que el C�digo no se repita
--03 Validar que el C�digo no tenga m�s de 3 caracteres
--04 Validar que el Nombre no se repita

CREATE PROCEDURE usp_InsertarDistrito


(@IDDistrito CHAR(3)=NULL,
@Nombre VARCHAR(30)=NULL) -- Inicializo como Null
-- por si el usuario no ingresa datos a alguna
-- de estas dos variables.
-- Al tenerlas como null me permite ejecutar
-- la primera parte de mi Procedimiento Almacenado.
AS
BEGIN

--01 Nulidad de los par�metros


IF(@IDDistrito IS NULL OR @Nombre IS NULL)
BEGIN
PRINT 'Debe ingresar todos los par�metros'
RETURN 1
END

--02 Validar que el c�digo no se repita


IF EXISTS (SELECT IDDistrito FROM DISTRITO
WHERE IDDistrito=@IDDistrito)

BEGIN
PRINT 'El c�digo del distrito ya existe'
RETURN 2
END
--03 Validar que el c�digo tenga tres caracteres
IF LEN(@IDDistrito)<>3
BEGIN
PRINT 'El c�digo debe tener 3 caracteres'
RETURN 3
END

--04 Validar que el nombre no se repita


IF EXISTS (SELECT Nombre FROM Distrito
WHERE Nombre=@Nombre)
BEGIN
PRINT 'El nombre del distrito ya existe'
RETURN 4
END

INSERT Distrito(IDDistrito, Nombre)


VALUES(@IDDistrito, @Nombre)

RETURN 0 -- �xito
END
GO

--01 Nulidad de los par�metros


EXECUTE usp_insertarDistrito NULL, 'Miraflores'
GO

EXECUTE usp_insertarDistrito 'D06'


GO

--02 Validar que el c�digo no se repita


EXECUTE usp_insertarDistrito 'D01', 'Miraflores'
GO

--03 Validar que el c�digo tenga 3 caracteres


EXECUTE usp_insertarDistrito 'D', 'Miraflores'
GO

EXECUTE usp_insertarDistrito 'D0', 'Miraflores'


GO

--04 Validar que el nombre del Distrito no se repita


EXECUTE usp_insertarDistrito 'D06', 'Ate'
GO

--�xito
EXECUTE usp_insertarDistrito 'D06', 'Miraflores'
GO

--Comprobamos
SELECT * FROM Distrito
GO

--Crearemos la Tabla Cliente


CREATE TABLE Cliente(
IDCliente CHAR(5) NOT NULL PRIMARY KEY,
Nombre VARCHAR(30) NOT NULL,
Direccion VARCHAR(30) NOT NULL,
IDDistrito CHAR(3) NOT NULL,
Credito DECIMAL(8,2) NULL,
)
GO

ALTER TABLE Cliente


ADD CONSTRAINT FK_Distrito
FOREIGN KEY (IDDistrito)
REFERENCES Distrito(IDDistrito)
GO

INSERT Cliente (IDCliente, Nombre, Direccion, IDDistrito, Credito)


VALUES ('CLI01', 'Mirella Vega', 'Calle Encuesta N� 20', 'D03', '3000')
GO

SELECT * FROM CLIENTE


GO

-- 05 SP que permita insertar un registro a la Tabla Cliente

--01 Nulidad de los par�metros


--02 Validar que el c�digo no se repita
--03 Validar que el c�digo no tenga m�s de 5 caracteres
--04 Validar que el distrito exista
--05 El monto de cr�dito no debe ser mayor a 10000

CREATE PROCEDURE usp_insertarCliente


@IDCliente CHAR(5)=NULL,
@Nombre VARCHAR(30)=NULL,
@Direccion VARCHAR(30)=NULL,
@IDDistrito VARCHAR(3)=NULL,
@Credito DECIMAL(8,2)=NULL

AS BEGIN

--01 Nulidad de los par�metros


IF(@IDCliente IS NULL OR @Nombre IS NULL OR @Direccion IS NULL
OR @IDDistrito IS NULL OR @Credito IS NULL)
BEGIN
PRINT 'Debe ingresar todos los par�metros'
RETURN 1
END

--02 Validar que el c�digo no se repita


IF EXISTS (SELECT IDCliente FROM Cliente
WHERE IDCliente=@IDCliente)

BEGIN
PRINT 'El C�digo del Cliente ya existe'
RETURN 2
END

--03 Validar que el c�digo tenga 5 caracteres


IF(LEN(@IDCliente)<>5)
BEGIN
PRINT 'El C�digo del Cliente debe tener 5 caracteres'
RETURN 3
END

--04 Validar que el distrito exista


IF NOT EXISTS (SELECT IDDistrito FROM Distrito WHERE IDDistrito=@IDDistrito)

BEGIN
PRINT 'El Distrito no existe'
RETURN 4
END

--05 Validar que el monto no sea mayor a 10000


IF @Credito>10000
BEGIN
PRINT 'El Cr�dito no puede ser mayor que 10000'
RETURN 5
END

INSERT Cliente(IDCliente, Nombre, Direccion, IDDistrito, Credito)


VALUES(@IDCliente, @Nombre, @Direccion, @IDDistrito, @Credito)

RETURN 0 -- �xito
END
GO

--01 Nulidad de los par�metros


EXECUTE usp_insertarCliente
'Ingrid D�az'
GO

--02 Validar que el c�digo del Cliente no se repita


EXECUTE usp_insertarCliente
'CLI01', 'Ingrid D�az', 'Calle BuenaVida 123', 'D04', '5000'
GO

--03 Validar que el c�digo tenga 5 caracteres


EXECUTE usp_insertarCliente
'CL2', 'Ingrid D�az', 'Calle BuenaVida 123', 'D04', '5000'
GO

EXECUTE usp_insertarCliente
'CL02', 'Ingrid D�az', 'Calle BuenaVida 123', 'D04', '5000'
GO

--04 Validar que el distrito exista


EXECUTE usp_insertarCliente
'CLI02', 'Janeth Vela', 'Calle BuenaVida 456', 'D07', '7000'
GO
--05 Validar que el cr�dito no sea mayor a 10000
EXECUTE usp_insertarCliente
'CLI02', 'Janeth Vela', 'Calle BuenaVida 456', 'D02', '70000'
GO

--�xito
EXECUTE usp_insertarCliente
'CLI02', 'Janeth Vela', 'Calle BuenaVida 456', 'D02', '7000'
GO

-- Comprobamos
SELECT * FROM Cliente
GO

-- Usar Edutec

USE Edutec
GO

--
SELECT * FROM Alumno
SELECT * FROM Curso
SELECT * FROM CursoProgramado
SELECT * FROM Matricula
GO

-- 06 crear un SP que permita registrar una Matr�cula.

-- 01 Nulidad de los parametros


-- 02 Validar que el alumno exista
-- 03 Validar que exista el cursoProgramado
-- 04 Validar que el alumno no se matricule en el mismo Curso Programado.
-- 05 Validar que el Curso Programado est� activado
-- 06 Que exista vacantes
-- 07 Actualizar el numero de vacantes y matriculados.

CREATE PROCEDURE usp_insertarMatricula

--Par�metros de entrada y salida


@IdCursoProg INT=NULL,
@IdAlumno CHAR(5) = NULL,
@FecMatricula DATE= NULL

AS

BEGIN

-- Declaraci�n de variables locales


DECLARE @Vacantes INT
DECLARE @Activo INT
DECLARE @Matriculados INT
--01 Nulidad de los parametros
IF(@IdCursoProg IS NULL OR @IdAlumno IS NULL
OR @FecMatricula IS NULL)
BEGIN
PRINT 'Debe ingresar todos los datos'
RETURN 1
END

--02 Validar que exista el Curso Programado


IF NOT EXISTS(SELECT IdCursoProg FROM CursoProgramado
WHERE IdCursoProg=@IdCursoProg)
BEGIN
PRINT 'El Curso Programado no existe'
RETURN 2
END

--03 validar que el Alumno exista


IF NOT EXISTS(SELECT IdAlumno FROM Alumno
WHERE IdAlumno=@IdAlumno)
BEGIN
PRINT 'El Alumno no existe'
RETURN 3
END

--04 Validar que el Alumno no se matricule en el mismo Curso Programado.

IF EXISTS (SELECT IdCursoProg


FROM Matricula
WHERE
IdCursoProg=@IdCursoProg AND
IdAlumno=@IdAlumno)
BEGIN
PRINT 'El alumno ya se matricul� en el Curso Programado'
RETURN 4
END

--05 Validar que el curso est� activado


--06 Validar que existan vacantes

SELECT @Vacantes=Vacantes,
@Activo=Activo,
@Matriculados=Matriculados
FROM Cursoprogramado
WHERE IdCursoProg=@IdCursoProg

IF(@Activo=0)
BEGIN
PRINT 'El Curso Programado no est� activado'
RETURN 5
END

IF(@Vacantes=0)
BEGIN
PRINT 'No hay vacantes'
RETURN 6
END

--07 Actualizar el n�mero de Vacantes y Matriculados.


-- Iniciar una transaccion

BEGIN TRANSACTION
UPDATE CursoProgramado
SET Vacantes=@Vacantes-1,
Matriculados=@Matriculados+1
WHERE IDCursoProg=@IDCursoProg

INSERT Matricula(IdCursoProg, IdAlumno, FecMatricula)


VALUES(@IdCursoProg, @IdAlumno, @FecMatricula)

IF(@@ERROR<> 0)
BEGIN
PRINT 'Error en la Base de Datos'
ROLLBACK TRANSACTION
RETURN 7
END
COMMIT TRANSACTION

RETURN 0
END
GO

-- Vemos que para insertar una Matr�cula necesitamos


-- IdCursoProg, IdAlumno y FecMatricula
SELECT * FROM Matricula
GO

--01 Nulidad de los parametros


EXEC usp_insertarMatricula '1'
GO

--02 Validar que exista el Curso Programado


EXEC usp_insertarMatricula '100', 'A0001', '01/11/2013'
GO

--03 Validar que el Alumno exista


EXEC usp_insertarMatricula '1', 'A9000', '01/11/2013'
GO

--04 Validar que el Alumno no se matricule en el mismo Curso Programado.


EXEC usp_insertarMatricula '1', 'A0001', '01/11/2013'
GO

--05 Validar que el Curso Programado est� activo


EXEC usp_insertarMatricula '14', 'A0001', '01/11/2013'
GO

--06 Validar que exista vacantes


-- F�jese en el Curso Programado 44
SELECT * FROM CursoProgramado
WHERE IdCursoProg='44'
GO

UPDATE CursoProgramado
SET Vacantes='0', Matriculados='20'
WHERE IdCursoProg='44'
GO

SELECT * FROM CursoProgramado


WHERE IdCursoProg='44'
GO

EXEC usp_insertarMatricula '44', 'A0001', '01/11/2013'


GO

-- Regresemos a la normalidad el Curso Programado 44


UPDATE CursoProgramado
SET Vacantes='20', Matriculados='0'
WHERE IdCursoProg='44'
GO

SELECT * FROM CursoProgramado


WHERE IdCursoProg='44'
GO

--07 Actualizar el n�mero de Vacantes y Matriculados


-- despu�s de matricular a un Alumno

-- El Curso Programado 1 tiene 10 alumnos matriculados (de 20 posibles)


-- Quedan 10 vacantes
SELECT * FROM Matricula
WHERE IdCursoProg='1'
GO

-- Ingresaremos el und�cimo alumno, el A0011


EXEC usp_insertarMatricula '1', 'A0011', '01/02/2012'
GO

-- Se hizo la Matr�cula con �xito


SELECT * FROM Matricula
WHERE IdCursoProg='1'
GO

-- Las Matr�culas subieron a 11 y las vacantes disminuyeron a 9


SELECT * FROM CursoProgramado
WHERE IdCursoProg='1'
GO

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--
-- II- Triggers
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--

/*

Los desencadenadores DML constituyen un tipo especial de procedimiento almacenado


que se inicia autom�ticamente cuando tiene lugar un evento de lenguaje de
manipulaci�n
de datos (DML) que afecta a la tabla o la vista definida en el desencadenador.

TRIGGERS DML
AFTER:
- AFTER INSERT
- AFTER DELETE
- AFTER UPDATE

Estos Triggers pueden proteger contra operaciones INSERT, UPDATE y DELETE


incorrectas o malintencionadas, y exigir otras restricciones que sean m�s
complejas que las definidas con restricciones CHECK.

A diferencia de las Restricciones CHECK, los desencadenadores DML pueden hacer


referencia a columnas de otras tablas. Por ejemplo, un desencadenador puede
utilizar una instrucci�n SELECT de otra tabla para comparar con los datos
insertados
o actualizados y para realizar acciones adicionales, como modificar los datos
o mostrar un mensaje de error definido por el usuario.

Los Triggers pueden evaluar el estado de una tabla antes y despu�s de realizar
una modificaci�n de datos y actuar en funci�n de esa diferencia.

Las restricciones solo pueden comunicar la existencia de errores mediante


mensajes de error est�ndar del sistema. Si la aplicaci�n necesita o puede
aprovechar
mensajes personalizados y un control de errores m�s complejo, deber� usar un
Trigger.

*/

-- Del libro
-- (Ejercicio 141)

CREATE DATABASE Test


GO

USE TEST
GO

-- Creando la Tabla Factura


CREATE TABLE Factura(
IdFactura int PRIMARY KEY,
FecFactura datetime default Getdate(),
Cliente varchar(30)not null,
MontoFactura money null)
GO

-- Creando la Tabla DetalleFactura


CREATE TABLE DetalleFactura(
IdFactura int not null,
IdProducto integer not null,
PrecioUnitario money not null,
Cantidad int not null)
GO

-- PK en DetalleFactura
ALTER TABLE DetalleFactura
ADD CONSTRAINT PK_DetalleFactura
PRIMARY KEY(IdFactura,IdProducto)
GO

-- FK del IDFactura de DetalleFactura con Factura


ALTER TABLE DetalleFactura
ADD CONSTRAINT FK_DetalleFactura_Factura
FOREIGN KEY(IdFactura)
REFERENCES Factura
GO

-- Establecemos el Formato de Fechas a D�a/Mes/A�o


SET DATEFORMAT DMY
GO

-- Insertamos 2 Facturas
INSERT Factura
VALUES
(1, '31/10/2013', 'Comercial G�mez', NULL),
(2, '02/11/2013', 'Juan L�pez Cordero', NULL)
GO

-- Insertamos sus Detalles


INSERT DetalleFactura
VALUES
(1,101,12.5,100),
(1,127,15,50),
(1,107,10,50),
(2,132,15.5,100),
(2,107,10,250)
GO

-- Vemos que las 2 Facturas no llevan el Monto


SELECT * FROM Factura
GO

-- Actualizaremos los Montos


UPDATE Factura
SET MontoFactura= CASE IdFactura
WHEN '1' THEN '2500'
WHEN '2' THEN '4050'
END
WHERE IdFactura IN ('1', '2')
GO

-- Comprobamos
SELECT * FROM Factura
GO

--------------------------------
-- TRIGGER AFTER INSERT
--------------------------------

-- 08 Crearemos un Trigger que calcule el Monto en la Tabla Factura


-- luego de insertar sus detalles en la Tabla DetalleFactura
-- (Ejercicio 142)

CREATE TRIGGER TR_Insert_DetalleFactura


ON DetalleFactura AFTER INSERT
AS

DECLARE @Factura INT


DECLARE @Suma MONEY

SET @Factura=(SELECT IdFactura FROM INSERTED)

SET @Suma= (SELECT SUM(PrecioUnitario * Cantidad)


FROM DetalleFactura
WHERE DetalleFactura.IdFactura=@Factura)

UPDATE Factura
SET MontoFactura=@Suma
WHERE IdFactura=@Factura
GO

-- Registrando la Factura 3
INSERT Factura
VALUES(3, '02/11/2013', 'Rep.Asunci�n', NULL)
GO

-- Probando el desencadenante
INSERT DetalleFactura VALUES (3,101,12.5,100)
INSERT DetalleFactura VALUES (3,127,15,100)
INSERT DetalleFactura VALUES (3,107,10,100)
GO

-- Verificando la Data
SELECT * FROM DetalleFactura
GO

-- Vemos que el Monto (3750) ha sido calculado autom�ticamente


SELECT * FROM Factura
GO

--------------------------------
-- TRIGGER AFTER DELETE
--------------------------------

-- 09 Crearemos un Trigger que recalcule el Monto en la Tabla DetalleFactura


-- luego de borrar alguno de sus detalles en la Tabla DetalleFactura
-- (Ejercicio 143)

CREATE TRIGGER TG_Delete_DetalleFactura


ON DetalleFactura AFTER DELETE
AS

DECLARE @Factura INT


DECLARE @Suma MONEY

SET @Factura=(SELECT IdFactura from DELETED)


SET @Suma=(SELECT SUM(PrecioUnitario * Cantidad)
FROM DetalleFactura
WHERE DetalleFactura.IdFactura=@Factura)

UPDATE Factura
SET MontoFactura=@Suma
WHERE IdFactura=@Factura
GO

-- Probando el Desencadenante
DELETE FROM DetalleFactura
WHERE IdFactura=1 AND IdProducto=101
GO

-- Se borr� el primer detalle de la Factura 1 en DetalleFactura


SELECT * FROM DetalleFactura
GO

-- El monto de la Factura 1 era 2500. Al borrarse uno de sus detalles


-- disminuy� a 1250
SELECT * FROM Factura
GO

--------------------------------
-- TRIGGER AFTER UPDATE
--------------------------------

-- 10 Crearemos un Trigger que recalcule el Monto en la Tabla DetalleFactura


-- luego de actualizar alguno de sus detalles en la Tabla DetalleFactura
-- (Ejercicio 144)

CREATE TRIGGER TG_Update_DetalleFactura


ON DetalleFactura AFTER UPDATE
AS

IF UPDATE (PrecioUnitario) OR UPDATE(Cantidad)


BEGIN
DECLARE @Factura INT
DECLARE @Suma MONEY

SET @Factura=(SELECT IdFactura FROM INSERTED)


SET @Suma=(SELECT SUM(PrecioUnitario * Cantidad)
FROM DetalleFactura
WHERE DetalleFactura.IdFactura=@Factura)

UPDATE Factura
SET MontoFactura=@Suma
WHERE IdFactura=@Factura
END
GO

-- Probando Desencadenante. Actualizamos el primer Detalle de la Factura 3


UPDATE DetalleFactura
SET Cantidad='200'
WHERE IdFactura='3' AND IdProducto='101'
GO

-- Verificando la actualizaci�n del primer detalle de la Factura 3


SELECT * FROM DetalleFactura
GO

-- Vemos que en la Factura 3 el Monto ha sido actualizado a 5000


SELECT * FROM Factura
GO

/*

TRIGGERS DDL
------------

Los desencadenadores DDL se inician en respuesta a una variedad de eventos


de lenguaje de definici�n de datos (DDL).

Estos eventos corresponden principalmente a las instrucciones de Transact-SQL


que comienzan por las palabras clave CREATE, ALTER, DROP, GRANT, DENY, REVOKE
o UPDATE STATISTICS.

*/

-- 11 Crearemos un Trigger que no dejar� Borrar o Modificar una Tabla


-- (Ejercicio 146)

CREATE TRIGGER Tg_Seguridad


ON DATABASE FOR DROP_TABLE, ALTER_TABLE
AS
PRINT 'Debe deshabilitarse el Trigger Tg_Seguridad para eliminar
o modificar una Tabla'
ROLLBACK
GO

--Probamos el desencadenante
DROP TABLE Factura
GO

--------------------------------
-- TRIGGERS CON LA BD EDUTEC
--------------------------------

USE Edutec
GO

-- 12 Crear un Trigger que matricule a un alumno en la Tabla Matr�cula


-- si es que existen Vacantes.
-- De existir las vacantes, actualizar en la Tabla CursoProgramado
-- el n�mero de Vacantes y el n�mero de Matriculados en dicho Curso Programado.

CREATE TRIGGER Tr_Insert_Matricula


ON Matricula
AFTER INSERT
AS

DECLARE @Vacantes INT

SELECT @Vacantes=CP.Vacantes
FROM CursoProgramado CP, Inserted I
WHERE CP.IdCursoProg=I.IdCursoProg

IF(@Vacantes=0)
Begin
PRINT 'No hay vacantes'
ROLLBACK TRANSACTION
End
Else
Begin
UPDATE CursoProgramado
SET Vacantes=Vacantes-1, Matriculados=Matriculados+1
FROM Inserted I
WHERE CursoProgramado.IdCursoProg=i.IdCursoProg -- Se uso un UPDATE
FROM
-- con WHERE entre
Tablas
-- (pudo usarse Join)

PRINT 'Base de Datos actualizada'


End
GO

-- Probando el Trigger

-- El Curso Programado 1 tiene 11 alumnos matriculados (de 20 posibles)


-- Quedan 9 vacantes
SELECT COUNT(*) FROM Matricula
WHERE IdCursoProg='1'
GO

-- Ingresaremos el duod�cimo alumno, el A0012


INSERT Matricula(IdCursoProg, IdAlumno, FecMatricula)
VALUES('1', 'A0012', '01/11/2013')
GO

-- Se hizo la Matr�cula con �xito


SELECT * FROM Matricula
WHERE IdCursoProg='1'
GO

-- Las Matr�culas subieron a 12 y las vacantes disminuyeron a 8


SELECT * FROM CursoProgramado
WHERE IdCursoProg='1'
GO
----------------------------------
-- TRIGGERS CON LA BD MARKETPERU
----------------------------------

USE MarketPERU
GO

-- Veamos una lista de todos los Productos con sus respectivos Stocks Actuales
SELECT IdProducto, Nombre, StockActual FROM PRODUCTO
COMPUTE COUNT(IdProducto)
GO

-- Veamos c�mo se insertan los registros en la Tabla Guia_Detalle


SELECT IdGuia, IdProducto, PrecioVenta, Cantidad
FROM Guia_Detalle
GO

-- 13 Crear un Trigger que descuente el Stock Actual de los Productos


-- cada vez que se especifique la cantidad de un producto en la Tabla
Guia_Detalle

CREATE TRIGGER DescuentaStock


ON Guia_Detalle
AFTER INSERT
AS

DECLARE @Cantidad INT,


@Unidades INT

-- Asignamos a la variable el contenido del campo


SELECT @Cantidad=GD.Cantidad
FROM GUIA_DETALLE GD
INNER JOIN Inserted I
ON GD.IdGuia=I.IdGuia

-- Asignamos a la variable el contenido del campo


SELECT @Unidades=P.StockActual
FROM PRODUCTO P
INNER JOIN Inserted I
ON P.IdProducto=I.IdProducto

BEGIN TRANSACTION
-- Verificamos la cantidad pedida

IF @Cantidad<= @Unidades
Begin
UPDATE PRODUCTO
SET StockActual=@Unidades-@Cantidad
FROM PRODUCTO P
INNER JOIN Inserted I
ON P.IdProducto=I.IdProducto

COMMIT TRANSACTION
PRINT 'Stock Actualizado'
End

ELSE
Begin
PRINT 'No existen suficientes Productos para satisfacer el Pedido'
ROLLBACK TRANSACTION
End
GO

-- Probando el Trigger

SELECT * FROM GUIA

INSERT GUIA
VALUES(108, 2, '11/11/2013', 'VELASQUEZ ORTIZ, FRANCISCO')
GO

SELECT * FROM GUIA


WHERE IdGuia='108'
GO

-- Con el Producto 2, el Stock Actual es 300


SELECT IdProducto, Nombre, StockActual
FROM PRODUCTO
WHERE IdProducto='2'
GO

INSERT GUIA_DETALLE
VALUES(108, 2, 1.50, 50)
GO

-- Pido 50 del Producto 2 en la Gu�a 108


SELECT * FROM GUIA_DETALLE
WHERE IdGuia='108'
GO

-- En la Tabla Producto, el Stock Actual del Producto 2 ya no es 200,


-- disminuy� a 250
SELECT IdProducto, Nombre, StockActual
FROM PRODUCTO
WHERE IdProducto='2'
GO

--------------------------------
-- TRIGGERS CON LA BD VENTAS
--------------------------------

USE Ventas
GO

-- 14 HACER UN TRIGGER PARA EVITAR QUE SE INGRESE UN CLIENTE


-- CUYO RUC TERMINE EN 150
CREATE TRIGGER ruc_I on TB_Cliente for insert as
Begin tran
if exists(select Ruc_cli from inserted
where Ruc_cli like '%150')
begin
print 'Cliente no deseado'
rollback tran
end
else
begin
commit tran
print 'Se insert� cliente'
end

-- Probando el Trigger
INSERT TB_CLIENTE
VALUES
('C021', 'Procter y Gamble', 'Av El Sol 111', '5551010',
'12345150', 'd17', GETDATE(), '1', 'Mateo H.')
GO

-- 15 No vender un producto del cual no tengo Stock

CREATE TRIGGER TG_DET_FAC_I


ON TB_DETALLE_FACTURA
FOR INSERT
AS

BEGIN

DECLARE @SA INT


DECLARE @CAN_VEN INT

SET @SA=(SELECT Stk_act


FROM Tb_Producto
WHERE Cod_pro=(SELECT Cod_pro FROM INSERTED))

SET @CAN_VEN =(SELECT CAN_VEN FROM INSERTED)

BEGIN TRAN
IF (@SA>=@CAN_VEN)
BEGIN
PRINT 'SI VENDIO'

UPDATE Tb_Producto
SET Stk_act= @SA-@CAN_VEN
WHERE Cod_pro=(SELECT Cod_pro FROM INSERTED)

COMMIT TRAN
END
ELSE
BEGIN
ROLLBACK TRANSACTION
PRINT 'NO HAY STOCK'
END
END
GO

-- Probando el Trigger

-- El producto P009 s�lo tiene 100 como Stock Actual


SELECT * FROM TB_PRODUCTO
WHERE Cod_pro='P009'
GO

-- Tenemos de la FA001 a la FA020


SELECT DISTINCT Num_fac FROM TB_DETALLE_FACTURA
GO

-- Vendo 5 (Stock de 100 baja a 95)


INSERT Tb_Detalle_Factura
VALUES ('FA017', 'P009', '5', '10')
GO

-- Vendo 95 (Stock de 95 baja a 0)


INSERT Tb_Detalle_Factura
VALUES ('FA018', 'P009', '95', '10')
GO

-- Quiero vender 50, pero tengo 0 en Stock para dicho producto


-- El trigger no debe dejar realizar la Venta
INSERT Tb_Detalle_Factura
VALUES ('FA019', 'P009', '50', '10')
GO
GO

-- 16 No eliminar a un vendedor que tenga Facturas generadas

CREATE TRIGGER TG_ELIMINA ON TB_VENDEDOR


FOR DELETE AS
IF EXISTS (SELECT NUM_FAC FROM TB_FACTURA
WHERE COD_VEN = (SELECT COD_VEN
FROM DELETED))
BEGIN
PRINT 'NO SE PUEDE ELIMINAR A ESTE VENDEDOR, TIENE FACTURAS GENERADAS'
ROLLBACK TRAN
END
ELSE
BEGIN
UPDATE TB_DISTRITO SET COD_VEN = NULL
WHERE COD_VEN = (SELECT COD_VEN FROM DELETED)
COMMIT TRAN
END
GO

-- Probando el Trigger
-- Trataremos de eliminar al Vendedor V01
DELETE FROM Tb_Vendedor
WHERE Cod_ven='V01'
GO

-- 17 No dar cr�dito a Clientes Tipo 2

CREATE TRIGGER TG_CLIENTE ON TB_FACTURA


AFTER INSERT
AS

IF (SELECT EST_FAC FROM INSERTED) = '1'


BEGIN TRAN
IF (SELECT TIP_CLI
FROM TB_CLIENTE C, INSERTED I
WHERE C.COD_CLI = I.COD_CLI) = '2'
BEGIN
PRINT 'NO SE PUEDE DAR CREDITO A ESTE CLIENTE'
ROLLBACK TRANSACTION
END
ELSE
COMMIT TRANSACTION
GO

-- Una factura de Estado 1 significa que es una factura sin fecha de cancelaci�n,
-- por lo tanto, significa que est� siendo dada a cr�dito.
-- Es por eso que igualo que en la factura a insertar su estado sea igual a 1.

SELECT * FROM Tb_Cliente


WHERE Tip_cli='2'
GO

-- Probando el Trigger
SELECT * FROM Tb_Factura
GO

INSERT Tb_Factura(Num_fac, Fec_fac, Cod_cli, Fec_can, Est_fac, Cod_ven, Por_Igv)


VALUES('FA021', GETDATE(), 'C002', NULL, '1', 'V05', '0.19')
GO

-- 18 No dar cr�dito a clientes que tienen alguna Factura pendiente (Est_fac=1)

CREATE TRIGGER TR_VALIDA_CLIENTE


ON TB_FACTURA
AFTER INSERT
AS

DECLARE @PENDIENTES INT


DECLARE @CLIENTE CHAR(4)

SET @CLIENTE =(SELECT COD_CLI FROM INSERTED)


SET @PENDIENTES=(SELECT COUNT(*) FROM TB_FACTURA
WHERE COD_CLI=@CLIENTE AND EST_FAC='1')

BEGIN TRANSACTION
IF @PENDIENTES>=1
BEGIN
PRINT 'CLIENTE TIENE FACTURAS PENDIENTES'
ROLLBACK TRANSACTION
END
ELSE
BEGIN
PRINT ' SE GENERO LA FACTURA'
COMMIT TRANSACTION
END
GO

-- Probando el Trigger

-- Vemos que los Clientes con Facturas pendientes son los Clientes C014, C015 y
C019
SELECT * FROM Tb_Factura
WHERE Est_fac='1'
GO

INSERT Tb_Factura(Num_fac, Fec_fac, Cod_cli, Fec_can, Est_fac, Cod_ven, Por_Igv)


VALUES('FA021', GETDATE(), 'C015', NULL, '1', 'V05', '0.19')
GO

SELECT * FROM Tb_Factura


GO

/*
.---.
/ . \
|\_/| |
| | /|
.----------------------------------------------------------------' |
/ .-. |
| / \ |
| |\_. | Hasta la pr�xima |
|\| | /| |
| `---' | Atte. |
| | Ing. F. Erick Tamayo |
| | Email: f.erick.tamayo@gmail.com |
| | Diciembre 2017 |
| | /
| |----------------------------------------------------------'
\ |
\ /
`---'

*/

Вам также может понравиться