Skill

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.


91
Spark score
out of 100
Updated 4 months ago
Version 1.0.0

Add to Favorites

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

01

Write T-SQL, PL/pgSQL, MySQL, and PL/SQL stored procedures.

02

Implement input validation and security best practices (e.g., SQL injection prevention).

03

Incorporate comprehensive error handling and transaction management.

04

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

Generate code

Writes source code or scripts from a description.

Query a database

Writes and executes SQL or NoSQL queries on databases.

Debug

Traces errors to their root cause and suggests fixes.

Review code

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.