Stored procedures for T-SQL
This topic provides reference content comparing stored procedures in Microsoft SQL Server 2019 and Amazon Aurora MySQL. You can understand the key differences and similarities between these two database systems' implementations of stored procedures.
| Feature compatibility | AWS SCT / AWS DMS automation level | AWS SCT action code index | Key differences | 
|---|---|---|---|
| 
                        
                            
                               | 
                        
                            
                               | No support for table-valued parameters. Syntax and option differences. | 
SQL Server Usage
Stored procedures are encapsulated, persisted code modules you can run using the EXECUTE T-SQL statement. They may have multiple input and output parameters. Table-valued user-defined types can
be used as input parameters. IN is the default direction for parameters, but OUT must be explicitly specified. You can specify parameters as both IN and OUT.
In SQL Server, you can run stored procedures in any security context using the EXECUTE AS option. They can be explicitly recompiled for every run using the RECOMPILE option and can be encrypted in the database using the ENCRYPTION option to prevent unauthorized access to the source code.
SQL Server provides a unique feature that allows you to use a stored procedure as an input to an INSERT statement. When you use this feature, only the first row in the data set returned by the stored procedure is evaluated.
As part of the stored procedure syntax, SQL Server supports a default output integer parameter that can be specified along with the RETURN command, for example, RETURN -1. It’s typically used to signal status or error to the calling scope, which can use the syntax EXEC @Parameter = <Stored Procedure Name> to retrieve the RETURN value, without explicitly stating it as part of the parameter list.
Syntax
CREATE [ OR ALTER ] { PROC | PROCEDURE } <Procedure Name> [<Parameter List> [ WITH [ ENCRYPTION ]|[ RECOMPILE ]|[ EXECUTE AS ...]] AS { [ BEGIN ] <SQL Code Body> [RETURN [<Integer Value>]] [ END ] }[;]
Creating and Running a Stored Procedure
Create a simple parameterized stored procedure to validate the basic format of an email.
CREATE PROCEDURE ValidateEmail
@Email VARCHAR(128), @IsValid BIT = 0 OUT
AS
BEGIN
IF @Email LIKE N'%@%'
    SET @IsValid = 1
ELSE
    SET @IsValid = 0
RETURN
END;
            Run the procedure.
DECLARE @IsValid BIT
EXECUTE [ValidateEmail]
    @Email = 'X@y.com', @IsValid = @IsValid OUT;
SELECT @IsValid;
-- Returns 1
            EXECUTE [ValidateEmail]
    @Email = 'Xy.com', @IsValid = @IsValid OUT;
SELECT @IsValid;
-- Returns 0
            Create a stored procedure that uses RETURN to pass the application an error value.
CREATE PROCEDURE ProcessImportBatch
@BatchID INT
AS
BEGIN
    BEGIN TRY
        EXECUTE Step1 @BatchID
        EXECUTE Step2 @BatchID
        EXECUTE Step3 @BatchID
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() = 235
            RETURN -1 -- indicate special condition
        ELSE
            THROW -- handle error normally
    END CATCH
END
          
          
            Using a Table-Valued Input Parameter
Create and populate the OrderItems table.
CREATE TABLE OrderItems(
    OrderID INT NOT NULL,
    Item VARCHAR(20) NOT NULL,
    Quantity SMALLINT NOT NULL,
    PRIMARY KEY(OrderID, Item)
);
            INSERT INTO OrderItems (OrderID, Item, Quantity) VALUES (1, 'M8 Bolt', 100), (2, 'M8 Nut', 100), (3, 'M8 Washer', 200), (3, 'M6 Washer', 100);
Create a table-valued type for the OrderItem table-valued parameter.
CREATE TYPE OrderItems
AS TABLE
(
    OrderID INT NOT NULL,
    Item VARCHAR(20) NOT NULL,
    Quantity SMALLINT NOT NULL,
    PRIMARY KEY(OrderID, Item)
);
            Create a procedure to process order items.
CREATE PROCEDURE InsertOrderItems
@OrderItems AS OrderItems READONLY
AS
BEGIN
    INSERT INTO OrderItems(OrderID, Item, Quantity)
    SELECT OrderID,
        Item,
        Quantity
    FROM @OrderItems
END;
            Instantiate and populate the table valued variable and pass the data set to the stored procedure.
DECLARE @OrderItems AS OrderItems;
INSERT INTO @OrderItems ([OrderID], [Item], [Quantity])
VALUES
(1, 'M8 Bolt', 100),
(1, 'M8 Nut', 100),
(1, M8 Washer, 200);
EXECUTE [InsertOrderItems]
    @OrderItems = @OrderItems;
(3 rows affected)
   Item       Quantity
1  M8 Bolt    100
2  M8 Nut     100
3  M8 Washer  200
          
          
            INSERT… EXEC Syntax
INSERT INTO <MyTable> EXECUTE <MyStoredProcedure>;
For more information, see CREATE PROCEDURE (Transact-SQL)
MySQL Usage
Amazon Aurora MySQL-Compatible Edition (Aurora MySQL) stored procedures provide similar functionality to SQL Server stored procedures.
As with SQL Server, Aurora MySQL supports security run context. It also supports input, output, and bi-directional parameters.
Stored procedures are typically used for: * Code reuse — Stored procedures offer a convenient code encapsulation and reuse mechanism for multiple applications, potentially written in various languages, requiring the same database operations. * Security management — By allowing access to base tables only through stored procedures, administrators can manage auditing and access permissions. This approach minimizes dependencies between application code and database code. Administrators can use stored procedures to process business rules and to perform auditing and logging. * Performance improvements — Full SQL query text doesn’t need to be transferred from the client to the database.
Stored procedures, triggers, and user-defined functions in Aurora MySQL are collectively referred to as stored routines. When binary logging is enabled, MySQL SUPER privilege is required to run stored routines. However, you can run stored routines with binary logging enabled without SUPER privilege by setting thelog_bin_trust_function_creators parameter to true for the DB parameter group for your MySQL instance.
            Aurora MySQL permits stored routines to contain control flow, DML, DDL, and transaction management statements including START TRANSACTION, COMMIT, and ROLLBACK.
Syntax
CREATE [DEFINER = { user | CURRENT_USER }] PROCEDURE sp_name ([ IN | OUT | INOUT ] <Parameter> <Parameter Data Type> ... ) COMMENT 'string' | LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } <Stored Procedure Code Body>
Examples
Replace RETURN value parameter with standard OUTPUT parameters.
CREATE PROCEDURE ProcessImportBatch()
IN @BatchID INT, OUT @ErrorNumber INT
BEGIN
    CALL Step1 (@BatchID)
    CALL Step2 (@BatchID)
    CALL Step3 (@BatchID)
IF error_count > 1
    SET @ErrorNumber = -1 -- indicate special condition
END
            Use a LOOP cursor with a source table to replace table valued parameters.
Create the OrderItems table.
CREATE TABLE OrderItems
(
    OrderID INT NOT NULL,
    Item VARCHAR(20) NOT NULL,
    Quantity SMALLINT NOT NULL,
    PRIMARY KEY(OrderID, Item)
);
            Create and populate SourceTable as a temporary data store for incoming rows.
CREATE TABLE SourceTable
(
    OrderID INT,
    Item VARCHAR(20),
    Quantity SMALLINT,
    PRIMARY KEY (OrderID, Item)
);
            INSERT INTO SourceTable (OrderID, Item, Quantity) VALUES (1, 'M8 Bolt', 100), (2, 'M8 Nut', 100), (3, 'M8 Washer', 200);
Create a procedure to loop through all rows in SourceTable and insert them into the OrderItems table.
CREATE PROCEDURE LoopItems()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE var_OrderID INT;
    DECLARE var_Item VARCHAR(20);
    DECLARE var_Quantity SMALLINT;
    DECLARE ItemCursor CURSOR
        FOR SELECT OrderID,
            Item,
            Quantity
        FROM SourceTable;
    DECLARE CONTINUE HANDLER
        FOR NOT FOUND SET done = TRUE;
    OPEN ItemCursor;
    CursorStart: LOOP
    FETCH NEXT FROM ItemCursor
        INTO var_OrderID, var_Item, var_Quantity;
    IF Done THEN LEAVE CursorStart;
    END IF;
        INSERT INTO OrderItems (OrderID, Item, Quantity)
        VALUES (var_OrderID, var_Item, var_Quantity);
    END LOOP;
    CLOSE ItemCursor;
END;
            Call the stored procedure.
CALL LoopItems();
Select all rows from the OrderItems table.
SELECT * FROM OrderItems;
For the preceding example, the result looks as shown following.
OrderID Item Quantity 1 M8 Bolt 100 2 M8 Nut 100 3 M8 Washer 200
Summary
The following table summarizes the differences between MySQL Stored Procedures and SQL Server Stored Procedures.
| Feature | SQL Server | Aurora MySQL | Workaround | 
|---|---|---|---|
| General  | CREATE PROC|PROCEDURE <Procedure Name> @Parameter1 <Type>, ...n AS <Body> | CREATE PROCEDURE <Procedure Name> (Parameter1 <Type>,...n) <Body> | Rewrite stored procedure creation scripts to use  Rewrite stored procedure creation scripts to omit the  Rewrite stored procedure parameters to not use the  Rewrite stored procedure parameter direction  | 
| Security context | { EXEC | EXECUTE } AS { CALLER | SELF | OWNER | 'user_name' } | DEFINER = 'user' | CURRENT_USER in conjunction with SQL SECURITY {
DEFINER | INVOKER } | For stored procedures that use an explicit user name, rewrite the code from  For stored procedures that use the  For stored procedures that use the  Unlike SQL Server,  | 
| Encryption | Use the  | Not supported in Aurora MySQL. | |
| Parameter direction | 
                            | 
                            | Although the functionality of these parameters is the same for SQL Server and MySQL, make sure that you rewrite the code for syntax compliance. Use  Use  | 
| Recompile | Use the  | Not supported in Aurora MySQL. | |
| Table-valued parameters | Use declared table type user-defined parameters. | Not supported in Aurora MySQL. | See the preceding example for a workaround. | 
| 
                            | Use the output of the stored procedure as input to an  | Not supported in Aurora MySQL. | Use tables to hold the data or pass string parameters formatted as CSV, XML, JSON (or any other convenient format) and then parse the parameters before the  | 
| Additional restrictions | Use  | The LOAD DATA statement isn’t allowed in stored procedures. | |
| 
                            | 
                            | Not supported. | Use a standard  | 
For more information, see Stored Procedures and Functions
 
                            
                            
                        