Free tutorials & notes in Hindi & English · Clean code examples · Mobile friendly learning
MySQL + SQL · Lesson 98

PL/SQL vs MySQL Stored Programs

PL/SQL and MySQL Stored Programs Are Not the Same Language

PL/SQL is Oracle Database's procedural extension to SQL. MySQL has a different stored-program language used in stored procedures, stored functions, triggers and scheduled events. Both support variables, conditions, loops, cursors and error handling, but the grammar, database objects and runtime behavior differ.

Correct migration mindset: translate the business rule, not the text. First identify inputs, outputs, SQL effects, errors, transaction boundaries, security context and performance requirements. Then implement those requirements with the target database's supported features.

This page compares Oracle PL/SQL with MySQL 8.4 stored programs. It does not imply that PL/SQL is a generic name for every database's procedural SQL.

PL/SQL vs MySQL: Practical Difference Matrix

AreaOracle PL/SQLMySQL stored programs
Anonymous blockDECLARE ... BEGIN ... EXCEPTION ... END;No general stored anonymous PL/SQL block; create a routine or run SQL from the client
Assignmentv_total := 10;SET v_total = 10;
Procedure parameterp_id IN NUMBERIN p_id INT
String typeVARCHAR2VARCHAR
Boolean in stored codePL/SQL BOOLEANBOOLEAN is a synonym for TINYINT(1)
Error modelEXCEPTION WHEN ...DECLARE ... HANDLER, SIGNAL, RESIGNAL
Reusable modulePackage specification and bodyNo direct package equivalent
OutputDBMS_OUTPUT.PUT_LINEReturn a result set with SELECT or write structured logs
Row limitFETCH FIRST / ROWNUMLIMIT
Auto-numberingIdentity or sequenceAUTO_INCREMENT

Types must be mapped by range, precision, character semantics and nullability—not by similar-looking names alone.

Blocks, Declarations and Variables

An Oracle PL/SQL block has an optional declarative part, a required executable part and an optional exception-handling part:

DECLARE
  v_total NUMBER(10,2) := 0;
BEGIN
  SELECT COALESCE(SUM(total_amount), 0)
  INTO v_total
  FROM orders
  WHERE customer_id = 101;
  DBMS_OUTPUT.PUT_LINE(v_total);
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END;
/

In MySQL, declarations belong at the start of a BEGIN ... END compound block. The declaration order matters: local variables and conditions come before cursors, and cursors come before handlers.

DELIMITER //
CREATE PROCEDURE show_customer_total(IN p_customer_id INT)
BEGIN
  DECLARE v_total DECIMAL(12,2) DEFAULT 0;

  SELECT COALESCE(SUM(total_amount), 0)
    INTO v_total
  FROM orders
  WHERE customer_id = p_customer_id;

  SELECT v_total AS paid_total;
END //
DELIMITER ;
Delimiter is a client instruction: DELIMITER helps the mysql client send a compound definition containing semicolons. It is not part of the stored procedure itself and is not sent through every connector API.

Procedures, Functions and Parameters

Both systems provide named procedures and functions, but their details differ. MySQL procedure parameters place the mode before the name: IN p_id INT, OUT p_total DECIMAL(12,2). MySQL function parameters are inputs and the function declares RETURNS plus a RETURN statement.

-- MySQL procedure call
CALL customer_summary(101, @paid_total);
SELECT @paid_total;

-- MySQL stored function call
SELECT service_fee(1500.00);

Oracle PL/SQL supports richer package-level overloading and package state. Do not assume every overloaded Oracle subprogram can retain the same name in MySQL. Choose explicit routine names and signatures, and move session state to transaction-scoped tables or the application where appropriate.

Security also needs a fresh decision. MySQL routines support SQL SECURITY DEFINER or INVOKER; Oracle uses definer's-rights or invoker's-rights behavior through AUTHID. Recreate least privilege rather than copying owners blindly.

Exception Handling, Cursors and Diagnostics

Oracle routes an exception to an EXCEPTION section. MySQL declares handlers inside the block:

DECLARE duplicate_key CONDITION FOR 1062;
DECLARE EXIT HANDLER FOR duplicate_key
BEGIN
  ROLLBACK;
  SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = 'Order already exists';
END;

A MySQL CONTINUE handler continues execution; an EXIT handler leaves the compound block where it was declared. UNDO is not supported. Use GET DIAGNOSTICS when code needs structured condition details, and use RESIGNAL to preserve or augment the current error.

Both languages support explicit cursors, but syntax and attributes differ. MySQL cursors are asensitive, read-only and nonscrollable. A typical loop declares a CONTINUE HANDLER FOR NOT FOUND, then performs OPEN, FETCH and CLOSE. Set-based SQL should remain the first choice in both databases.

Packages and Oracle-Specific Features Need Redesign

Oracle packages group public declarations and private implementation, and can hold package variables and overloaded subprograms. MySQL 8.4 has no direct package specification/body object. A migration may use:

  • consistent routine prefixes such as billing_create_invoice;
  • a dedicated database schema only when its ownership and deployment model fit;
  • application modules for orchestration, external services and state;
  • tables for durable state, with explicit keys, locking and retention;
  • views and routines for narrow, permission-controlled database interfaces.
Do not emulate package state with ungoverned session variables. Pooling, retries and concurrent requests can make hidden session state unsafe.

Review Oracle features one by one: sequences, collections, records, %TYPE, %ROWTYPE, bulk collect, FORALL, autonomous transactions, ref cursors, database links, synonyms and Oracle built-ins do not have guaranteed one-line MySQL equivalents.

Worked Migration: Customer Spend Procedure

Suppose the requirement is: accept a customer ID, return paid-order count and total, and reject a missing ID. A MySQL implementation is:

DELIMITER //
CREATE PROCEDURE customer_spend(
  IN  p_customer_id INT,
  OUT p_order_count INT,
  OUT p_paid_total DECIMAL(12,2)
)
SQL SECURITY INVOKER
READS SQL DATA
BEGIN
  IF p_customer_id IS NULL THEN
    SIGNAL SQLSTATE '45000'
      SET MESSAGE_TEXT = 'customer_id is required';
  END IF;

  SELECT COUNT(*), COALESCE(SUM(total_amount), 0)
    INTO p_order_count, p_paid_total
  FROM orders
  WHERE customer_id = p_customer_id
    AND status = 'PAID';
END //
DELIMITER ;

CALL customer_spend(101, @orders, @total);
SELECT @orders AS paid_orders, @total AS paid_total;
paid_orders | paid_total 3 | 3350.00

The migrated routine preserves the business contract, not Oracle punctuation. The query is set-based, NULL input is explicit, output types have defined precision, and the caller's security context is intentional.

Production Migration Checklist

  1. Inventory every routine, package, trigger, job, dependency and caller.
  2. Record inputs, outputs, side effects, errors and transaction ownership.
  3. Map data types by range, precision, timezone, charset and collation.
  4. Replace Oracle-only SQL and built-ins with tested MySQL equivalents.
  5. Redesign packages, session state, autonomous work and bulk operations.
  6. Convert exception paths to named conditions, handlers and SIGNAL.
  7. Prefer set-based SQL; benchmark any cursor or per-row function.
  8. Rebuild privileges with a durable least-privileged definer or invoker.
  9. Test normal, boundary, NULL, concurrency, rollback and retry cases.
  10. Compare result sets and row changes against a controlled Oracle baseline.

Study MySQL stored procedures, stored functions, cursors and transactions before a production conversion.

Official References

Language structure and migration cautions were checked against the official Oracle PL/SQL and MySQL 8.4 manuals.

Frequently Asked Questions

Is PL/SQL available in MySQL?
No. PL/SQL is Oracle Database procedural SQL. MySQL implements its own stored-program language for procedures, functions, triggers and events; similar concepts do not make the syntax interchangeable.
What replaces an Oracle PL/SQL package in MySQL?
MySQL has no direct package specification and package body equivalent. Use naming conventions, schemas where appropriate, routines and application modules, then redesign package state instead of mechanically translating it.
What replaces DBMS_OUTPUT.PUT_LINE in MySQL?
For learning and diagnostics, a MySQL procedure can return a result set with SELECT. Production logging should write structured rows to an authorized log table or use application observability, not ad-hoc result output.
How are exceptions migrated from PL/SQL to MySQL?
Map named Oracle exceptions and SQLCODE logic to MySQL DECLARE CONDITION, DECLARE HANDLER, SIGNAL, RESIGNAL and GET DIAGNOSTICS. Test each business error and transaction path explicitly.
Can Oracle PL/SQL code be copied directly into MySQL?
Usually not. Data types, package features, parameter syntax, exception handling, sequences, autonomous transactions, dynamic SQL and built-in functions require review or redesign.
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.