11.1 Create a view that defines a view named open_items that shows the invoices that haven’t been paid. This view should return four columns from the Vendors and Invoices tables: vendor_name, invoice_number, invoice_total, and balance_due (invoice_total – payment_total – credit_total). However, a row should only be returned when the balance due is greater than zero, and the rows should be in sequence by vendor_name. Then, run the script to create the view, and use SQL Developer to review the data that it returns. (You may have to click on the Refresh button in the Connections window after you click on the Views node to show the view you just created.) CREATE OR REPLACE VIEW open_items AS SELECT vendor_name, invoice_number, invoice_total, invoice_total - payment_total - credit_total AS balance_due FROM vendors JOIN invoices ON vendors.vendor_id = invoices.vendor_id WHERE invoice_total - payment_total - credit_total > 0 ORDER BY vendor_name 13.3 Write a script that creates a cursor consisting of vendor_name, invoice_number, and balance_due for each invoice with a balance due that’s greater than or equal to $5,000. The rows in this cursor should be sorted in descending sequence by balance due. Then, for each invoice, display the balance due, invoice number, and vendor name so it looks something like this: $19,351.18 P-0608 Malloy Lithographing Inc CONNECT ap/ap; SET SERVEROUTPUT ON; DECLARE CURSOR invoices_cursor IS SELECT vendor_name, invoice_number, invoice_total - payment_total - credit_total AS balance_due FROM vendors v JOIN invoices i ON v.vendor_id = i.vendor_id WHERE invoice_total - payment_total - credit_total >= 5000 ORDER BY balance_due DESC; invoice_row invoices%ROWTYPE; BEGIN FOR invoice_row IN invoices_cursor LOOP DBMS_OUTPUT.PUT_LINE( TO_CHAR(invoice_row.balance_due, '$99,999.99') || ' invoice_row.invoice_number || ' ' || invoice_row.vendor_name); END LOOP; END; / ' || 15.1 Create a stored procedure named insert_glaccount that lets a user add a new row to the General_Ledger_Accounts table in the AP schema. This procedure should have two parameters, one for each of the two columns in this table. Then, code a CALL statement that tests the procedure. (Note that this table doesn’t allow duplicate account descriptions.) CREATE OR REPLACE PROCEDURE insert_glaccount ( account_number_param NUMBER, account_description_param VARCHAR2 ) AS BEGIN INSERT INTO general_ledger_accounts VALUES (account_number_param, account_description_param); COMMIT; END; / CALL insert_glaccount(700, 'Internet Services'); 15.5 Modify the stored procedure that you created in exercise 1 and save it as insert_glaccount_with_test. This procedure should use the function that you created in step 3 to test whether the account description is going to be okay before it issues the INSERT statement. If the account description is a duplicate, this procedure should raise an application error with -20002 as the error number and an error message of Duplicate account description CREATE OR REPLACE PROCEDURE insert_glaccount_with_test ( account_number_param account_description_param NUMBER, VARCHAR2 ) AS BEGIN IF test_glaccounts_description(account_description_param) = 1 THEN RAISE_APPLICATION_ERROR(-20002, 'Duplicate account description.'); ELSE INSERT INTO general_ledger_accounts VALUES (account_number_param, account_description_param); COMMIT; END IF; END; / 16.2 Create a trigger named invoices_after_update_payment for the Invoices table that displays the vendor name, invoice number, and payment total in the output window whenever the payment total is increased. Then, test this trigger with an appropriate UPDATE statement. (A trigger like this could be modified so it stores the data in an audit table.) CREATE OR REPLACE TRIGGER invoices_after_update_payment AFTER UPDATE OF payment_total ON invoices FOR EACH ROW WHEN (new.payment_total > old.payment_total) DECLARE vendor_name_var VARCHAR2(50); BEGIN SELECT vendor_name INTO vendor_name_var FROM vendors WHERE vendor_id = :old.vendor_id; DBMS_OUTPUT.PUT_LINE('vendor_name: ' || vendor_name_var); DBMS_OUTPUT.PUT_LINE('invoice_number: ' || :new.invoice_number); DBMS_OUTPUT.PUT_LINE('payment_total: ' || :new.payment_total); END; / SET SERVEROUTPUT ON; UPDATE invoices SET payment_total = 100 WHERE invoice_id = 112; -- clean up UPDATE invoices SET payment_total = 0 WHERE invoice_id = 112;