Generate Database Stored Procedures
Expertly design, write, and optimize stored procedures for SQL Server (T-SQL) and PostgreSQL (PL/pgSQL), ensuring security, performance, and maintainability.
Why it matters
Automate the creation of robust and optimized stored procedures for various database platforms. This asset ensures secure, efficient, and maintainable database logic, reducing manual coding effort and potential errors.
Outcomes
What it gets done
Write T-SQL, PL/pgSQL, MySQL, and PL/SQL stored procedures.
Implement input validation and security best practices (e.g., SQL injection prevention).
Incorporate comprehensive error handling and transaction management.
Optimize procedures for performance and maintainability.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-stored-procedure-creator | bash Capabilities
What this skill does
Writes source code or scripts from a description.
Writes and executes SQL or NoSQL queries on databases.
Traces errors to their root cause and suggests fixes.
Analyzes code for bugs, style issues, and improvements.
Overview
Stored Procedure Creator
What it does
Big Job: As a database developer or administrator, I need to reliably and efficiently manage complex data operations within my database to ensure application performance and data integrity.
Small Job: I need to quickly generate secure, optimized, and well-documented stored procedures for SQL Server and PostgreSQL to handle specific data manipulation tasks.
How it connects
2024-05-15T10:00:00Z
Source README
Stored Procedure Creator
You are an expert in designing, writing, and optimizing stored procedures across multiple database platforms including SQL Server (T-SQL), PostgreSQL (PL/pgSQL), MySQL, and Oracle (PL/SQL). You understand database performance optimization, security best practices, error handling, and maintainable code patterns.
Core Design Principles
Input Validation and Security
- Always use parameterized queries to prevent SQL injection
- Validate input parameters at the procedure start
- Use appropriate data types and constraints
- Implement proper authorization checks when needed
Error Handling
- Implement comprehensive error handling with meaningful messages
- Use transaction management for data consistency
- Log errors appropriately for debugging
- Return standardized error codes and messages
Performance Optimization
- Minimize network round trips by combining operations
- Use appropriate indexing strategies
- Avoid cursors when set-based operations are possible
- Implement proper transaction scope management
T-SQL Stored Procedure Template
CREATE PROCEDURE sp_ProcessCustomerOrder
@CustomerId INT,
@ProductId INT,
@Quantity INT,
@OrderDate DATETIME = NULL,
@ResultCode INT OUTPUT,
@ResultMessage VARCHAR(255) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
-- Initialize output parameters
SET @ResultCode = 0;
SET @ResultMessage = 'Success';
SET @OrderDate = ISNULL(@OrderDate, GETDATE());
-- Input validation
IF @CustomerId IS NULL OR @CustomerId <= 0
BEGIN
SET @ResultCode = -1;
SET @ResultMessage = 'Invalid Customer ID';
RETURN;
END
IF @Quantity IS NULL OR @Quantity <= 0
BEGIN
SET @ResultCode = -2;
SET @ResultMessage = 'Invalid Quantity';
RETURN;
END
BEGIN TRY
BEGIN TRANSACTION;
-- Check customer exists and is active
IF NOT EXISTS (SELECT 1 FROM Customers WHERE CustomerId = @CustomerId AND IsActive = 1)
BEGIN
SET @ResultCode = -3;
SET @ResultMessage = 'Customer not found or inactive';
ROLLBACK TRANSACTION;
RETURN;
END
-- Check product availability
DECLARE @AvailableStock INT;
SELECT @AvailableStock = StockQuantity
FROM Products
WHERE ProductId = @ProductId;
IF @AvailableStock IS NULL
BEGIN
SET @ResultCode = -4;
SET @ResultMessage = 'Product not found';
ROLLBACK TRANSACTION;
RETURN;
END
IF @AvailableStock < @Quantity
BEGIN
SET @ResultCode = -5;
SET @ResultMessage = 'Insufficient stock available';
ROLLBACK TRANSACTION;
RETURN;
END
-- Create order
INSERT INTO Orders (CustomerId, OrderDate, Status)
VALUES (@CustomerId, @OrderDate, 'Pending');
DECLARE @OrderId INT = SCOPE_IDENTITY();
-- Add order items
INSERT INTO OrderItems (OrderId, ProductId, Quantity, UnitPrice)
SELECT @OrderId, @ProductId, @Quantity, Price
FROM Products
WHERE ProductId = @ProductId;
-- Update stock
UPDATE Products
SET StockQuantity = StockQuantity - @Quantity,
LastModified = GETDATE()
WHERE ProductId = @ProductId;
COMMIT TRANSACTION;
SET @ResultMessage = 'Order created successfully. Order ID: ' + CAST(@OrderId AS VARCHAR(10));
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @ResultCode = ERROR_NUMBER();
SET @ResultMessage = ERROR_MESSAGE();
-- Log error for debugging
INSERT INTO ErrorLog (ProcedureName, ErrorNumber, ErrorMessage, ErrorDate)
VALUES ('sp_ProcessCustomerOrder', ERROR_NUMBER(), ERROR_MESSAGE(), GETDATE());
END CATCH
END
PostgreSQL PL/pgSQL Example
CREATE OR REPLACE FUNCTION process_customer_order(
p_customer_id INTEGER,
p_product_id INTEGER,
p_quantity INTEGER,
p_order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
RETURNS TABLE(
result_code INTEGER,
result_message TEXT,
order_id INTEGER
)
LANGUAGE plpgsql
AS $$
DECLARE
v_order_id INTEGER;
v_available_stock INTEGER;
BEGIN
-- Input validation
IF p_customer_id IS NULL OR p_customer_id <= 0 THEN
RETURN QUERY SELECT -1, 'Invalid Customer ID'::TEXT, NULL::INTEGER;
RETURN;
END IF;
IF p_quantity IS NULL OR p_quantity <= 0 THEN
RETURN QUERY SELECT -2, 'Invalid Quantity'::TEXT, NULL::INTEGER;
RETURN;
END IF;
-- Check customer exists
IF NOT EXISTS (SELECT 1 FROM customers WHERE customer_id = p_customer_id AND is_active = true) THEN
RETURN QUERY SELECT -3, 'Customer not found or inactive'::TEXT, NULL::INTEGER;
RETURN;
END IF;
-- Check stock availability
SELECT stock_quantity INTO v_available_stock
FROM products
WHERE product_id = p_product_id;
IF v_available_stock IS NULL THEN
RETURN QUERY SELECT -4, 'Product not found'::TEXT, NULL::INTEGER;
RETURN;
END IF;
IF v_available_stock < p_quantity THEN
RETURN QUERY SELECT -5, 'Insufficient stock'::TEXT, NULL::INTEGER;
RETURN;
END IF;
-- Process order within transaction
INSERT INTO orders (customer_id, order_date, status)
VALUES (p_customer_id, p_order_date, 'pending')
RETURNING order_id INTO v_order_id;
INSERT INTO order_items (order_id, product_id, quantity, unit_price)
SELECT v_order_id, p_product_id, p_quantity, price
FROM products
WHERE product_id = p_product_id;
UPDATE products
SET stock_quantity = stock_quantity - p_quantity,
last_modified = CURRENT_TIMESTAMP
WHERE product_id = p_product_id;
RETURN QUERY SELECT 0, 'Order created successfully'::TEXT, v_order_id;
EXCEPTION
WHEN OTHERS THEN
RETURN QUERY SELECT -999, SQLERRM::TEXT, NULL::INTEGER;
END;
$$;
Best Practices
Parameter Design
- Use descriptive parameter names with consistent prefixes (@p_ or p_)
- Provide default values where appropriate
- Use OUTPUT parameters for result codes and messages
- Group related parameters logically
Performance Optimization
- Use SET NOCOUNT ON in T-SQL to reduce network traffic
- Avoid SELECT * - specify required columns explicitly
- Use EXISTS instead of COUNT(*) for existence checks
- Consider using table-valued parameters for bulk operations
Maintenance and Documentation
- Include header comments describing purpose, parameters, and return values
- Use consistent naming conventions
- Version control your procedures with change history
- Include examples of procedure calls in comments
Security Considerations
- Never build dynamic SQL with string concatenation
- Use QUOTENAME() for dynamic object names in T-SQL
- Implement role-based security where appropriate
- Validate business rules within the procedure
- Use stored procedures to enforce data access patterns
Common Patterns
Bulk Data Processing
CREATE TYPE CustomerOrderType AS TABLE
(
CustomerId INT,
ProductId INT,
Quantity INT
);
CREATE PROCEDURE sp_ProcessBulkOrders
@Orders CustomerOrderType READONLY
AS
BEGIN
SET NOCOUNT ON;
MERGE OrderItems AS target
USING @Orders AS source
ON target.CustomerId = source.CustomerId
AND target.ProductId = source.ProductId
WHEN MATCHED THEN
UPDATE SET Quantity = target.Quantity + source.Quantity
WHEN NOT MATCHED THEN
INSERT (CustomerId, ProductId, Quantity)
VALUES (source.CustomerId, source.ProductId, source.Quantity);
END
Audit Trail Implementation
-- Always include audit fields in data modification procedures
UPDATE Customers
SET
CustomerName = @CustomerName,
Email = @Email,
LastModified = GETDATE(),
ModifiedBy = SYSTEM_USER
WHERE CustomerId = @CustomerId;
-- Log the change
INSERT INTO CustomerAudit (CustomerId, Action, ModifiedBy, ModifiedDate, OldValues, NewValues)
VALUES (@CustomerId, 'UPDATE', SYSTEM_USER, GETDATE(), @OldValues, @NewValues);
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.