Buenas prácticas al definir procedimientos almacenados

Definir procedimientos almacenados no es solo cuestión de escribir lógica T-SQL funcional. Es una disciplina que requiere previsión, consistencia y enfoque estructurado.

El uso de procedimientos almacenados es una de las bases del desarrollo robusto en SQL Server. Aportan encapsulamiento, seguridad, rendimiento y reutilización del código. Pero como cualquier otro elemento persistente de base de datos, su eficacia no reside solo en lo que hacen, sino en cómo están definidos y estructurados. En este artículo repasaremos una serie de buenas prácticas que deberíamos aplicar de forma sistemática al crear procedimientos almacenados, tanto desde el punto de vista funcional como desde una perspectiva de mantenimiento y rendimiento.

Estructura básica de los procedimientos almacenados

Todo procedimiento almacenado debería comenzar por una cabecera clara, que incluya las opciones de sesión imprescindibles. Estas opciones afectan al comportamiento del objeto y quedan almacenadas junto con su definición, por lo que no deben dejarse al azar:

Las opciones ANSI_NULLS y QUOTED_IDENTIFIER son obligatorias para garantizar compatibilidad con vistas indexadas, funciones deterministas y otras funcionalidades. Y SET NOCOUNT ON evita el envío innecesario de mensajes como “(x filas afectadas)”, lo cual mejora el rendimiento en operaciones masivas o dentro de cursores.

Nombres coherentes y significativos para procedimientos almacenados

Otro de los mejores consejos que podemos seguir a la hora de crear procedimientos almacenados es que los nombres deben seguir una convención clara y consistente. Lo ideal es utilizar un prefijo común, como el esquema dbo o app, y un verbo que indique claramente la acción. Evitemos prefijos de sistema como sp_, ya que están reservados para procedimientos del sistema. Cuando un procedimiento almacenado empieza por sp_ SQL Server realiza una búsqueda prioritaria en la base de datos master, lo que afecta al rendimiento y puede provocar colisiones de nombres. Si quieres que el prefijo especifique claramente que es un procedimiento almacenado yo soy más partidario de prefijos como usp_ (User Stored Procedure) pero, esto ya va en gustos. Te dejo unos ejemplos de lo que para mi serían buenos nombres:

  • dbo.usp_ObtenerClientesPorCiudad
  • app.usp_ActualizarStockProducto
  • dbo.usp_InsertarPedidoCabecera

Declara los parámetros de los procedimientos almacenados de forma explícita y validada

Todo parámetro debe tener un tipo de dato bien definido, preferiblemente sin utilizar tipos innecesariamente amplios como NVARCHAR(MAX) o INT si con TINYINT es suficiente. Además, es una buena práctica validar parámetros críticos antes de ejecutar lógica compleja:

Esto permite fallos controlados y evita errores más adelante que sean difíciles de rastrear. Si no quieres usar RAISERROR también puedes dejar log en una tabla diseñada para este fin.

Evita la lógica excesiva en un solo procedimiento almacenado

Un error común es concentrar demasiada lógica en un solo procedimiento, lo que dificulta su mantenimiento, pruebas unitarias y reutilización. Si un procedimiento está realizando múltiples tareas (validación, inserción, actualización, notificación…), es mejor dividirlo en partes más pequeñas y orquestarlas desde uno principal.

Además, si reutilizamos lógica compartida entre procedimientos, podemos encapsularla en funciones o en procedimientos secundarios.

Utiliza transacciones de forma segura y explícita en tus procedimientos almacenados

Si un procedimiento realiza más de una operación que debe completarse como una unidad, debemos protegerla con una transacción. Pero cuidado, de nada sirve iniciar una transacción si no vamos a contar con que puede haber errores y tenemos planificado rollback cuando sea necesario.

Esto garantiza integridad de datos y un control efectivo de los errores. Nuevamente, también puedes usar una tabla de log en vez de RAISERROR.

Documenta todos tus procedimientos almacenados

Seamos claros, para mi este punto no es opcional. Una breve cabecera que explique qué hace el procedimiento, qué parámetros recibe y qué devuelve es una inversión de tiempo que ahorra horas de análisis futuro. Especialmente en equipos grandes o proyectos duraderos, esta práctica marca una gran diferencia.

Cuidado con el uso de SELECT * en procedimientos almacenados

El uso de SELECT * dentro de código que se va a persistir puede ser cómodo al principio, pero es una mala práctica y te dará problemas en cuanto el esquema cambie. Rompe la estabilidad del contrato de salida del procedimiento y complica la integración con aplicaciones externas. En su lugar, deberíamos listar explícitamente las columnas:

Añade a tus procedimientos almacenados un control de errores robusto

Todo procedimiento que modifique datos debe incluir manejo de errores. Además del bloque TRY…CATCH, conviene capturar el código y mensaje del error para diagnóstico:

También puede ser útil registrar errores en una tabla de log para su análisis posterior.

Cuida el rendimiento de los procedimientos almacenados desde el diseño

Cuantas veces hemos oido eso de “Es que en desarrollo funcionaba…”. Cada vez que definimos un procedimiento, estamos estableciendo un plan de ejecución potencialmente reutilizable. Además, como son objetos que se van a persistir tenemos que tener en cuenta que los datos van a crecer en algún momento y el rendimiento tiene que seguir siendo óptimo. Aunque con datos de desarrollo o en etapas tempranas del proyecto pueda parecer que no hace falta invertir tiempo en la optimización te prometo que tu yo del futuro te agradecerá que lo hayas pensado a tiempo. Algunas recomendaciones básicas podrían ser:

  • No uses OPTION (RECOMPILE) si no es estrictamente necesario (casi nunca lo es).
  • Declara los parámetros con tipos de datos que coincidan con las columnas.
  • Evita subconsultas complejas innecesarias.
  • Usa EXISTS en lugar de COUNT(*) si solo interesa saber si hay filas.
  • Indexa correctamente las tablas que usas como origen o destino.

Pruebas, idempotencia y versionado de los procedimientos almacenados

En general, es buena práctica que los procedimientos sean idempotentes si su función lo permite (es decir, que al ejecutarse más de una vez no cambien el resultado final).

Además, es recomendable mantener versiones numeradas y fechadas en sistemas donde los procedimientos evolucionan con el tiempo, y anotar los cambios relevantes en el propio código fuente.

Conclusión

Definir procedimientos almacenados no es solo cuestión de escribir lógica T-SQL funcional. Es una disciplina que requiere previsión, consistencia y enfoque estructurado. Aplicando estas buenas prácticas, conseguimos objetos más fiables, mantenibles y adaptables a largo plazo.

Tengo en mi lista de posibles futuros artículos aspectos complementarios a este artículo como procedimientos para auditoría, patrones para operaciones masivas o generación dinámica de SQL con seguridad. Mientras tanto, si aún no lo has hecho, te invito a revisar nuestro artículo sobre opciones SET imprescindibles al crear procedimientos, un complemento perfecto para consolidar estos conceptos.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima! 

Publicado por Roberto Carrancio

Mi nombre es Roberto Carrancio y soy un DBA de SQL server con más de 10 años de experiencia en el sector. Soy el creador del blog soydba.es donde intento publicar varios artículos a la semana (de lunes a viernes que los fines de semana me gusta estar con mi gente y disfrutar de mi moto) Espero que disfrutes leyendo este blog tanto como yo disfruto escribiendo y que te sea de utilidad. Si tienes alguna sugerencia, pregunta o comentario, puedes dejarlo al final de cada entrada o enviarme un correo electrónico. Estaré encantado de leerte y responderte. ¡Gracias por tu visita! Mi principal interés es compartir mi conocimiento sobre bases de datos con todo el que quiera aprenderlo. Me parece un mundo tan apasionante como desconocido. Fuera de lo profesional me encanta la cocina, la moto y disfrutar de tomar una cervecita con amigos.

Deja una respuesta