Está en la página 1de 15

101

@@ROWCOUNT will give the number of rows affected by the last SQL


statement, it is best to capture it into a local variable following the
command in question, as its value will change the next time you look at
it:
DECLARE @Rows int
DECLARE @TestTable table (col1 int, col2 int)
INSERT INTO @TestTable (col1, col2) select 1,2 union select 3,4
SELECT @Rows=@@ROWCOUNT
SELECT @Rows AS Rows,@@ROWCOUNT AS [ROWCOUNT]
OUTPUT:

(2 row(s) affected)
Rows ROWCOUNT
----------- -----------
2 1

(1 row(s) affected)
you get Rows value of 2, the number of inserted rows, but ROWCOUNT is 1
because the SELECT @Rows=@@ROWCOUNT command affected 1 row
if you have multiple INSERTs or UPDATEs, etc. in your transaction, you
need to determine how you would like to "count" what is going on. You
could have a separate total for each table, a single grand total value, or
something completely different. You'll need to DECLARE a variable for
each total you want to track and add to it following each operation that
applies to it:

--note there is no error handling here, as this is a simple example


DECLARE @AppleTotal int
DECLARE @PeachTotal int

SELECT @AppleTotal=0,@PeachTotal=0

BEGIN TRANSACTION

INSERT INTO Apple (col1, col2) Select col1,col2 from xyz where ...
SET @AppleTotal=@AppleTotal+@@ROWCOUNT

INSERT INTO Apple (col1, col2) Select col1,col2 from abc where ...
SET @AppleTotal=@AppleTotal+@@ROWCOUNT

INSERT INTO Peach (col1, col2) Select col1,col2 from xyz where ...
SET @PeachTotal=@PeachTotal+@@ROWCOUNT

INSERT INTO Peach (col1, col2) Select col1,col2 from abc where ...
SET @PeachTotal=@PeachTotal+@@ROWCOUNT

COMMIT

SELECT @AppleTotal AS AppleTotal, @PeachTotal AS PeachTotal


Funciones frente a los procedimientos
almacenados en SQL Server
October 14, 2019 by Daniel Calbimonte

Introducción
Por lo general, los administradores de bases de datos prefieren los procedimientos
almacenados en SQL en vez de funciones en SQL Server. ¿Es esta una buena práctica?

En este artículo, le vamos a enseñar cómo poder crear procedimientos y funciones


almacenados en SQL Server y vamos a mostrar las ventajas y desventajas de cada uno de
ellos. En los ejemplos que vamos a usar en este artículo, utilizaremos funciones escalares
definidas por el usuario, también conocidas como UDF. Mostraremos algunas funciones
con valores de tabla en el futuro. Las funciones CLR no se cubrirán aquí.

Incluiremos los siguientes temas:

 Crear un “Hello World” en un procedimiento almacenado frente a una función


 Invocar un procedimiento almacenado versus invocar una función
 Usar variables en un procedimiento almacenado frente a una función
 Reusabilidad
 Invocar funciones/procedimientos dentro de funciones/ procedimientos

Empecemos

1. Crear un “Hello world” en un procedimiento


almacenado en SQL versus una función
Vamos a crear un simple “Hello world” en un procedimiento almacenado y una función
para verificar cuál es más fácil de poder crear.

Primero empecemos creando un procedimiento de almacenado simple usando la


declaración en SSMS:

CREATE PROCEDURE HelloWorldprocedure

AS

PRINT 'Hello World'


 

Ejecute el código y después llame al procedimiento almacenado en SQL:

exec HelloWorldprocedure

Si ejecuta el código, podrá ver el mensaje “Hello World”:

Figura 1. Resultado del procedimiento almacenado “Hello World”

Ahora intentemos hacer lo mismo con una función:

CREATE FUNCTION dbo.helloworldfunction()

RETURNS varchar(20)

AS

BEGIN

RETURN 'Hello world'

END

Podemos llamar a la función utilizando un select:

La función devolverá el siguiente mensaje:

Figura 2. “Hello world” utilizando una función

Si se compara el código, la función requiere más código para hacer lo mismo. Los bloques
BEGIN y END son obligatorios en una función, mientras que el procedimiento almacenado
no los requiere si es solo una línea. En una función, es obligatorio utilizar los argumentos
RETURNS y RETURN, mientras que en un procedimiento almacenado no es necesario.
En pocas palabras, un procedimiento almacenado es mucho más flexible para escribir
cualquier código que uno desee, mientras que las funciones tienen una estructura y
funcionalidad rígidas.

2. Invocar un procedimiento almacenado en


SQL frente a Invocar una función
Usted puede invocar un procedimiento almacenado de diferentes maneras:

exec HelloWorldprocedure

execute HelloWorldprocedure

execute dbo.HelloWorldprocedure

HelloWorldprocedure

Puede invocar utilizando exec o execute e incluso puede invocar el procedimiento


almacenado sin la instrucción execute. No es necesario que se tenga que especificar el
nombre del esquema.

The functions are less flexible. You need to specify the schema to invoke it (which is a good
practice to avoid conflicts with other object with the same name and different schema).

Llamemos a una función sin el esquema:

select helloworldfunction() as regards

El mensaje que se muestra es el siguiente:

El mensaje 195, Nivel 15, Estado 10, Línea 20 ‘helloworldfunction’


no es un nombre de función incorporado reconocido

Como puede ver, el nombre del esquema es obligatorio para poder invocar una función:

select dbo.helloworldfunction() as regards

 
3. Usar variables en un procedimiento
almacenado en SQL vs a una función
Ahora vamos a convertir grados Celsius a Fahrenheit utilizando procedimientos y funciones
almacenados para ver las diferencias. Empecemos con un procedimiento almacenado:

CREATE PROCEDURE CONVERTCELSIUSTOFAHRENHEIT

@celsius real

as

select @celsius*1.8+32 as Fahrenheit

Celsius es el parámetro de entrada y estamos haciendo los cálculos en la instrucción select


para convertir a grados Fahrenheit.

Si invocamos el procedimiento almacenado, vamos a verificar el resultado convirtiendo 0


°C:

exec CONVERTCELSIUSTOFAHRENHEIT 0

El resultado será 32 °F:

Figura 3. Procedimiento almacenado en SQL para convertir Celsius a Fahrenheit

Tratemos de hacer lo mismo con una función:

CREATE FUNCTION dbo.f_celsiustofahrenheit(@celcius real)

RETURNS real

AS

BEGIN
RETURN  @celcius*1.8+32

END

Puede llamar a la función creada de la siguiente manera:

select dbo.f_celsiustofahrenheit(0) as fahrenheit

Estamos convirtiendo 0° C a °F. Como se puede ver, el código es muy simple en ambos
casos.

4. Reusabilidad
La principal ventaja de una función es que esta puede reutilizarse en código. Como por
ejemplo, puede hacer lo siguiente:

select CONCAT(dbo.helloworldfunction(),', welcome to sqlshack') Regards

En este ejemplo, estamos concatenando la función del ejemplo 1 con una cadena. El
resultado va a ser el siguiente:

Figura 4. Concatenación de una cadena a una función

Como usted puede ver, se puede concatenar fácilmente una función con una cadena. Para
realizar algo similar con un procedimiento almacenado en SQL, vamos a necesitar una
variable de salida en un procedimiento almacenado para poder concatenar la variable de
salida con una cadena. Vamos a echar un vistazo al procedimiento almacenado:

create procedure outputparam

@paramout varchar(20) out

as

select @paramout='Hello world'

 
El procedimiento consta en asignar la cadena “Hello World” a un parámetro de salida.
Puede utilizar la palabra de salida o salir para especificar que el parámetro es un parámetro
de salida.

El código puede ser simple, pero tiene que llamar al procedimiento para usar el parámetro
de salida que se concatena, es un poco más complejo que una función:

declare @message varchar(20)

exec outputparam @paramout=@message out

select @message as regards

select CONCAT(@message,', welcome to sqlshack')

Como puede apreciar, se debe declarar una nueva variable llamada @message o cualquier
otro nombre de su preferencia. Cuando llama al procedimiento almacenado, se debe
especificar que es un parámetro externo. Una ventaja de los procedimientos almacenados
es que puede obtener varios parámetros mientras que, en las funciones, solo se puede
devolver una variable (función escalar) o una tabla (funciones con valores de tabla).

5. Invocar funciones/Procedimientos dentro de


funciones/Procedimientos almacenados en
SQL
¿Podemos invocar procedimientos almacenados dentro de una función?

Vamos a echar un vistazo:

CREATE FUNCTION dbo.procedureinsidefunction()

RETURNS varchar(22)

AS

BEGIN

execute HelloWorldprocedure

Declare @hellovar varchar(22)=', welcome to sqlshack'

RETURN  @hellovar

END

La función va a invocar el procedimiento “Hello World” creado en la sección 1.


Si invocamos la función, tendremos el siguiente mensaje:

Msg 557, Nivel 16, Estado 2, Línea 65 Solo se pueden ejecutar


funciones y algunos procedimientos almacenados extendidos desde una
función.

Como se puede apreciar, no es posible llamar a un procedimiento almacenado desde una


función. ¿Se puede llamar a una función desde un procedimiento almacenado?

Aquí está el procedimiento:

create procedure functioninsideprocedure

as

select dbo.helloworldfunction()

Si invocamos el procedimiento almacenado en SQL, podremos verificar si este funciona o


no:

exec functioninsideprocedure

El resultado que se muestra es el siguiente:

Figura 5. Una función dentro de un procedimiento

Como se puede apreciar, es posible invocar funciones dentro de un procedimiento


almacenado y no se puede invocar un procedimiento almacenado dentro de una función.

Puede invocar una función dentro de una función. El siguiente código muestra un ejemplo
simple:

CREATE FUNCTION dbo.functioninsidefunction()

RETURNS varchar(50)

AS

BEGIN
RETURN  dbo.helloworldfunction()

END

Podemos llamar a la función como de costumbre:

select dbo.functioninsidefunction() as regards

¿Es posible que podamos llamar a procedimientos dentro de otros procedimientos?

Sí se puede. Aquí tienes un ejemplo al respecto:

create procedure procedureinsideprocedure

as

execute dbo.HelloWorldprocedure

Puede ejecutar el procedimiento como de costumbre:

exec dbo.procedureinsideprocedure

Conclusiones
Los procedimientos almacenados en SQL son mucho más fáciles de crear y las funciones
tienen una estructura más rígida y admiten menos cláusulas y funcionalidades. Pero, por
otro lado, usted puede usar fácilmente los resultados de la función en T-SQL. Le mostramos
cómo concatenar una función con una cadena. La manipulación de resultados de un
procedimiento almacenado es más compleja.

En una función escalar, puede devolver solo una variable y en un procedimiento


almacenado múltiples variables. Sin embargo, para llamar a las variables de salida en un
procedimiento almacenado, es necesario el declarar variables fuera del procedimiento para
poder invocarlo.

Asimismo, no puede invocar procedimientos dentro de una función. Pero, por otro lado, en
un procedimiento se puede invocar funciones y procedimientos almacenados.
Finalmente, es muy importante mencionar algunos problemas de rendimiento cuando
utilizamos funciones. Sin embargo, esta desventaja se explicará en un próximo
artículo, Funciones y comparaciones de procedimientos almacenados en SQL Server.
Procedimientos Almacenados
 By Trainer SQL in Programación

Procedimientos Almacenados en
SQL Server
Un procedimiento almacenado son instrucciones T-SQL almacenadas con un
nombre en la base de datos.

Los procedimientos almacenados se pueden utilizar para


 Devolver un conjunto de resultados, se puede incluir parámetros de entrada
para especificar el filtro del conjunto resultado.
 Ejecutar instrucciones de programación.
 Devolver valores numéricos que permiten realizar acciones cuando un grupo
de instrucciones se realizó con éxito o no.

Ventajas del uso de procedimientos


almacenados en SQL Server
Reutilización del código
El encapsulamiento en un procedimiento es óptimo para reutilizar su código. Se
elimina la necesidad de escribir el mismo código, se reducen  inconsistencias
en el código y permite que cualquier usuario ejecute el código aún sin tener
acceso a los  objetos que hace referencia.

Mayor seguridad
Se pueden ejecutar SP con instrucciones que hacen referencia a objetos que
los usuarios no tienen permisos. El procedimiento realiza la ejecución del
código y todas las instrucciones y controla el acceso a los  objetos a los que
hace referencia. Esto hace mas sencillo la asignación de permisos. Se puede
implementar la suplantación de usuarios usando Exexute As. Existe un nivel
fuerte de encapsulamiento.

Tráfico de red reducido


Un SP se ejecuta en un único lote de código. Esto reduce el tráfico de red
cliente servidor porque únicamente  se envía a través de la red la llamada que
ejecuta el SP. La encapsulación del código del SP permite que viaje a través de
la red como un solo bloque.

Mantenimiento más sencillo


Se puede trabajar en los aplicativos en base a capas, cualquier cambio en la
Base de datos, hace sencillo los cambios en los procedimientos que hacen uso
de los objetos cambiados en la BD.

Rendimiento mejorado
Los procedimientos almacenados se compila la primera vez que se ejecutan y
crean un plan de ejecución que vuelve a usarse en posteriores ejecuciones.

Tipos de procedimientos almacenados en SQL


Server
Definidos por el usuario
Se crea por el usuario en las bases de datos definidas por el usuario o en las
de sistema (Master, Tempdb, Model y MSDB)

Procedimientos almacenados Temporales


Los procedimientos temporales son procedimientos definidos por el usuario,
estos se almacenan en tempdb.  Existen dos tipos de procedimientos
temporales: locales (primer caracter es #) y globales (primer caracter ##).  Se
diferencian entre sí por los nombres, la visibilidad y la disponibilidad.
Los procedimientos temporales locales tienen como primer carácter de sus
nombres un solo signo de número (#);  solo son visibles en la conexión actual
del usuario y se eliminan cuando se cierra la conexión.  Los procedimientos
temporales globales presentan dos signos de número (##) antes del nombre;
lo pueden usar todos los usuarios conectados, se eliminan cuando se
desconectan todos los usuarios.

Procedimientos Almacenados del Sistema


Los procedimientos del sistema son propios de SQL Server. Los caracteres
iniciales de estos procedimientos son sp_  la cual no se recomienda para los
procedimientos almacenados definidos por el usuario.

Extendidos definidos por el usuario


Los procedimientos extendidos tienen instrucciones externas en un lenguaje de
programación como puede ser C.  Estos procedimientos almacenados son DLL
que una instancia de SQL Server puede cargar y ejecutar dinámicamente.
Sintaxis
Para crear un procedimiento almacenado se utiliza
Create procedure NombreProcedimiento
[(
@PrimerParametro TipoDato,
@SegundoParametro TipoDato,…
)]
As
Instrucciones del SP
go

Para modificar un SP
Alter procedure NombreProcedimiento
[(
@PrimerParametro TipoDato,
@SegundoParametro TipoDato,… cambios
)]
As
Instrucciones del SP con cambios
go

Eliminar un SP
Drop procedure NombreProcedimiento
go

Para listar los SP


select * from sys.procedures
go

Ejercicios
Use Northwind
go

— Procedimiento para listar los productos


Create procedure spProductosListadoPrecios
As
Select P.ProductID, P.ProductName,
P.UnitPrice , P.UnitsInStock
from Products As P
go
Ejecutar el Store Procedure creado
Execute spProductosListadoPrecios
go

— Procedimiento para insertar un registro en la tabla Shippers


— La instrucción para insertar un Shipper es:
insert into Shippers (CompanyName, Phone)
values (‘Tolva Couriers’,’954542452′)
go
El SP para insertar Shippers se crea de la siguiente forma.
create procedure spShippersInsertaNuevo
(
@NombreEmpresa nvarchar(40),
@Fono nvarchar(24)
)
As
insert into Shippers (CompanyName, Phone)
values (@NombreEmpresa,@Fono)
go
Ejecutar el SP, se puede ejecutar de las siguiente formas:
Execute spShippersInsertaNuevo ‘Chasqui’,’87545852′
go
Execute spShippersInsertaNuevo
@Fono = ‘345435645’, @NombreEmpresa =’Ford’
go
Execute spShippersInsertaNuevo
@NombreEmpresa =’Turbo XD’, @Fono = ‘8569856’
go

— Procedimiento para el listado de productos  de una determinada


categoría
Create procedure spProductosListadoPorCategoria
(
@CategoriaCodigo int
)
As
select P.ProductID, P.ProductName,
P.UnitPrice , P.UnitsInStock, P.UnitsOnOrder
from Products As P
where CategoryID = @CategoriaCodigo
go
Ejecutar el SP
Productos de categoria 2
Execute spProductosListadoPorCategoria 2
go

Modificar el procedimiento de Listado de Productos por categoría que lo


muestre ordenados por precio descendente
Alter procedure spProductosListadoPorCategoria
(
@CategoriaCodigo int
)
As
select P.ProductID, P.ProductName,
P.UnitPrice , P.UnitsInStock, P.UnitsOnOrder
from Products As P
where CategoryID = @CategoriaCodigo
order by P.UnitPrice desc
go

— Procedimiento para crear una tabla con los productos de una


determinada categoría
Create procedure spCreaTablaProductosDeCategoria
(
@CodigoCategoria int
)
As
Declare @NombreTabla nvarchar(40), @DropTablaTSQL
nvarchar(100),@CrearTablaTSQL nvarchar(100)
set @NombreTabla = ‘ProductosDeCategoria’+
LTRIM(STR(@CodigoCategoria))
Set @DropTablaTSQL = ‘Drop Table ‘+ @NombreTabla
Set @CrearTablaTSQL = ‘select * into ‘+ @NombreTabla + ‘ from Products
where CategoryID = ‘+LTRIM(STR(@CodigoCategoria))
if exists (select * from sys.tables where name = @NombreTabla)
Begin
Execute(@DropTablaTSQL)
End
Execute(@CrearTablaTSQL)
go

 Ejecutar para la categoría 3


Execute spCreaTablaProductosDeCategoria 3
go
Ver los registros
select * from Productosdecategoria3
go

También podría gustarte