PL/SQL & T-SQL
The business logic hiding in your database.
Packages, triggers, cursors and stored procedures hold fee formulas and status rules nobody remembers. PYD ENTERPRISES extracts them, with every table each one really changes.
Packages
64
Triggers
118
Cursor loops
402
- LOAN.FEE_BALwritten by 3 procs, 1 trigger
- LOAN.WATCH_FLAGwritten only by TRG_LOAN_FEE_GL
- GL_ENTRY11 writers, 9 of them triggers
- RATE_INDEXread-only from PL/SQL
Mutation lineage
Every table a procedure changes, including the ones it does not mention.
Toggle trigger side effects and dynamic SQL resolution to see how much of a procedure's real behavior lives outside its own body.
PL/SQL
PKG_LOAN.NIGHTLY_LATE_FEES
Cursor loop over active loans past due; assesses the greater of 15.00 or 5% of the payment when days late exceed product grace days.
- Tables written
- 4
- Outside the proc body
- 3
- READ
LOAN
CURSOR c_due
- READ
PRODUCT
CURSOR c_due (JOIN)
- INSERT
LOAN_FEE
line 12, per row
- ↳ INSERT
GL_ENTRY
TRG_LOAN_FEE_GL, AFTER INSERT ON LOAN_FEE
Credits 4410-LATE-FEE-INC. Not visible in the package source.
- ↳ UPDATE
LOAN
TRG_LOAN_FEE_GL, when amount > 100
Sets WATCH_FLAG = 'Y'. A second rule hidden in a trigger.
- UPDATE
LOAN
line 14, FEE_BAL
- ↳ INSERT
LOAN_AUDIT
TRG_LOAN_AUD, AFTER UPDATE ON LOAN
Fires for both LOAN updates above.
- COMMIT
(transaction)
line 18, once after loop
All fees for the night commit or roll back together.
1CREATE OR REPLACE PACKAGE BODY pkg_loan AS2 PROCEDURE nightly_late_fees(p_as_of IN DATE) IS3 CURSOR c_due IS4 SELECT l.loan_id, l.next_due_dt, l.pmt_amt, p.grace_days5 FROM loan l JOIN product p ON p.product_cd = l.product_cd6 WHERE l.status = 'A' AND l.next_due_dt < p_as_of;7 v_fee NUMBER(9,2);8 BEGIN9 FOR r IN c_due LOOP10 IF p_as_of - r.next_due_dt > r.grace_days THEN11 v_fee := GREATEST(15, ROUND(r.pmt_amt * 0.05, 2));12 INSERT INTO loan_fee (loan_id, fee_type, amount, assessed_dt)13 VALUES (r.loan_id, 'LATE', v_fee, p_as_of);14 UPDATE loan SET fee_bal = fee_bal + v_fee15 WHERE loan_id = r.loan_id;16 END IF;17 END LOOP;18 COMMIT;19 END nightly_late_fees;20END pkg_loan;
1CREATE OR REPLACE TRIGGER trg_loan_fee_gl2AFTER INSERT ON loan_fee3FOR EACH ROW4BEGIN5 INSERT INTO gl_entry (acct, dr_cr, amount, src_ref, posted_dt)6 VALUES ('4410-LATE-FEE-INC', 'C', :NEW.amount,7 'FEE:' || :NEW.loan_id, :NEW.assessed_dt);8 IF :NEW.amount > 100 THEN9 UPDATE loan SET watch_flag = 'Y' WHERE loan_id = :NEW.loan_id;10 END IF;11END;
ORACLE PL/SQL
One package, three rules, two of them elsewhere.
Rule 1, in the package. For active loans past due by more than the product's grace days, assess a late fee of GREATEST(15, ROUND(pmt_amt * 0.05, 2)).
Rule 2, in a trigger. Every late fee credits income account 4410. Move the package logic into a service without the trigger and the general ledger stops balancing.
Rule 3, also in the trigger. A fee above 100.00 puts the loan on a watch list. No package, screen or report mentions it.
The single COMMIT after the loop is recorded too: the night's fees are all-or-nothing today, and the target design has to decide whether to keep that.
Hidden transaction side effects
What a stored procedure does that its name does not say.
MICROSOFT T-SQL
Dynamic table names, resolved to candidates.
The INSERT target is built from @PayType. PYD ENTERPRISES matches the pattern against the DDL, lists Pay_CHK, Pay_EFT and Pay_WIR as candidates, links the reserve trigger, and flags the concatenated identifier for security review.
1CREATE PROCEDURE dbo.usp_ApplyClaimPayment2 @ClaimId INT, @Amount DECIMAL(12,2), @PayType CHAR(3)3AS4BEGIN5 SET NOCOUNT ON;6 BEGIN TRY7 BEGIN TRANSACTION;8 UPDATE dbo.ClaimReserve9 SET Outstanding = Outstanding - @Amount10 WHERE ClaimId = @ClaimId;11 IF @@ROWCOUNT = 012 THROW 50001, 'No reserve for claim', 1;13 DECLARE @sql NVARCHAR(400) =14 N'INSERT INTO dbo.Pay_' + @PayType + N' (ClaimId, Amount) VALUES (@c, @a)';15 EXEC sp_executesql @sql, N'@c INT, @a DECIMAL(12,2)', @c = @ClaimId, @a = @Amount;16 COMMIT TRANSACTION;17 END TRY18 BEGIN CATCH19 IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;20 THROW;21 END CATCH22END
COMMIT inside loops
Partial commit points that change failure semantics when the logic moves to a service.
Autonomous transactions
PRAGMA AUTONOMOUS_TRANSACTION blocks that persist even when the caller rolls back.
Trigger side effects
Writes performed by row and statement triggers, attributed to the statement that fired them.
File and queue output
UTL_FILE writes, DBMS_AQ enqueues and xp_cmdshell calls recorded as external effects.
Database links and synonyms
Remote writes over DB links and synonym chains resolved to the real object.
Scheduled entry points
DBMS_SCHEDULER jobs and SQL Agent steps linked to the procedures they run.
How stored procedure analysis works
Four passes over code and schema.
- 01
Parse with the DDL
Procedures, packages, functions and triggers are parsed against the schema DDL you export, so every column reference resolves to a typed column and every %ROWTYPE expands.
- 02
Bind triggers to statements
Each INSERT, UPDATE, DELETE and MERGE is linked to the row and statement triggers it fires, including triggers fired by triggers, with the column filters (UPDATE OF) that apply.
- 03
Resolve dynamic SQL
EXECUTE IMMEDIATE and sp_executesql strings are evaluated where they are built from literals and bounded parameters; candidate targets are listed, the rest flagged.
- 04
Separate rules from mechanics
Fee formulas, eligibility predicates and status transitions become rules; cursor housekeeping, logging tables and error wrappers are classified as plumbing.
Planning a move off procedures? See PL/SQL to microservices and T-SQL to .NET services.
FAQ
Database logic questions.
Do you need access to the production database?
No. PYD ENTERPRISES works from exported source and DDL: package specs and bodies, procedures, triggers, views and table definitions. Most teams export them with the tooling their DBAs already use and copy the files into the PYD ENTERPRISES ingest volume.
How are cursor loops turned into rules?
The loop body is analyzed per row with the cursor query as its input set. The WHERE clause becomes the population a rule applies to, and the statements inside become the rule's condition and effect, for example a late fee of the greater of 15.00 or 5% of the payment when days late exceed grace days.
Can PYD ENTERPRISES tell which procedures are still used?
It links procedures to their callers in application code that is part of the scan (COBOL EXEC SQL, Java JDBC, .NET ADO), to scheduler jobs and to triggers. Procedures with no caller in the scan are reported as orphans for your DBAs to confirm.
What about Informix 4GL and embedded SQL?
Informix 4GL programs, DB2 embedded SQL in COBOL and SQL in Java and .NET data access layers all feed the same lineage graph, so a column can be traced from the screen or batch program to every procedure and trigger that changes it.
Find the rules your DBAs inherited.
Run PYD ENTERPRISES on 100,000 lines of COBOL or Java in your private VPC and review OpenAPI specs and DMN tables tomorrow.