I have an updatable (and constantly changing) table that looks something like this (simplified):
I'm trying to create an automated process to send over the info to the users on the table.
I know how to send out emails but not sure how to create a process since Apex Automations only use SQL or PL/SQL Functions.
I also know that we could use 'subscriptions' using an Interactive Report but that sends out the complete report to all the users.
Any ideas on how to achieve this?
Thanks!
I'd create a stored procedure that reads that table and sends an e-mail.
Then schedule the procedure using DBMS_SCHEDULER built-in package.
In other words, avoid Apex for that matter; let the database itself handle it.
Use a pl/sql block to loop through the table and send and email for each entry (or for each distinct email adress). This would look something like this:
DECLARE
BEGIN
FOR r IN (SELECT * FROM <your_table) LOOP
apex_mail.send(p_to => r.email
...--other parameters for apex_mail.send
END LOOP;
END;
This block can be used as the source of an Apex Automation - in that case you can schedule the automation to run weekly. Alternatively you could put the code in a procedure (optionally within a package) and schedule it with dbms_scheduler
Note that it is possible to define an email template in your apex application, that is an easier way to create and maintain the text of the automated emails. apex_mail.send takes a template id as parameter (docs)
There are several blogs that show how to do this. Here is a blog showing how to use automations to send a reminder email based on the emp/dept sample dataset.
Related
Is there a way to retrieve output from PL/SQL continuously rather than wait until the SP completes its execution. Continuously mean as when it executes the execute immediate.
Any other mechanism to retrieve pl/sql output?
As per Oracle docs
Output that you create using PUT or PUT_LINE is buffered in the SGA. The output cannot be retrieved until the PL/SQL program unit from which it was buffered returns to its caller. So, for example, Enterprise Manager or SQL*Plus do not display DBMS_OUTPUT messages until the PL/SQL program completes.
As far as I know, there is a way, but not with DBMS_OUTPUT.PUT_LINE. Technique I use is:
create a log table which will accept values you'd normally display using DBMS_OUTPUT.PUT_LINE. Columns I use are
ID (a sequence, to be able to sort data)
Date (to know what happened when; might not be enough for sorting purposes because operations that take very short time to finish might have the same timestamp)
Message (a VARCHAR2 column, large enough to accept the whole information)
create a logging procedure which will be inserting values into that table. It should be an autonomous transaction so that you could COMMIT within (and be able to access data from other sessions), without affecting the main transaction
Doing so, you'd
start your PL/SQL procedure
call the logging procedure whenever appropriate (basically, where you'd put the DBMS_OUTPUT.PUT_LINE call)
in another session, periodically query the log table as select * from log_table order by ID desc
Additionally, you could write a simple Apex application with one report page which selects from the logging table and refreshes periodically (for example, every 10 seconds or so) and view the main PL/SQL procedure's execution.
The approach that Littlefoot has provided is what I normally use as well.
However, there is another approach that you can try for a specific use case. Let's say you have a long-running batch job (like a payroll process for example). You do not wish to be tied down in front of the screen monitoring the progress. But you want to know as soon as the processing of any of the rows of data hits an error so that you can take action or inform a relevant team. In this case, you could add code to send out emails with all the information from the database as soon as the processing of a row hits an error (or meets any condition you specify).
You can do this using the functions and procedures provided in the 'UTL_MAIL' package. UTL_MAIL Documentation from Oracle
For monitoring progress without the overhead of logging to tables and autonomous transactions. I use:
DBMS_APPLICATION.SET_CLIENT_INFO( TO_CHAR(SYSDATE, 'HH24:MI:SS') || ' On step A' );
and then monitor in v$session.client_infofor your session. It's all in memory and won't persist of course but it is a quick and easy ~zero cost way of posting progress.
Another option (Linux/UNIX) for centralised logging that is persistent and again avoids logging in the database more generally viewable that I like is interfacing to syslog and having Splunk or similar pick these up. If you have Splunk or similar then this makes the monitoring viewable without having to connect to the database query directly. See this post here for how to do this.
https://community.oracle.com/thread/2343125
With TSQL I'm used to putting some repeatable tests in for my stored procs. Typically this may include putting the db in a particular state, runnings the sproc, validating the state and rolling back. And contrived example might something like this"
BEGIN TRAN
--input for test case
DECLARE #TestName VARCHAR(10) = 'bob'
--insert test row
INSERT INTO tbl (data) values (#TestName)
--display initial state of target row
SELECT * FROM tbl WHERE data = #TestName
--do some useful test
EXEC MyProc
--display the final state of the target row
SELECT * FROM tbl WHERE data = #TestName
--put the db back where it started
ROLLBACK TRAN
Now I'm working with Oracle and PL/SQL and I'm trying to use a some similar pattern to test my work and not finding it obvious to me quite how to do that. I believe there are a few different ways I might accomplish it but haven't gotten anything to actually work. Ideally I would have a single script in which I could run multiple test cases and inspect the result.
I am trying to work in PL/SQL Developer at this point and understand that might have some differences from how it might work in Oracle SQL Developer or elsewhere.
In Oracle, using tools like SQL*Plus and GUI tools like SQL Developer, you have many options :
To execute the statements and procedures in a single session in an order, i.e. using procedural method of PL/SQL, write an anonymous plsql block and execute it as a script.
Most of the GUI based tools have an option like Execute as script or Test Window to execute your scripts individually or embedded in an anonymous block.
Using DBMS_SCHEDULER also you could achieve the same task.
As you are interested in PL/SQL Developer tool product of Allround Automations, you could simply use the test window to test individual objects.
I have documented few useful features of the PL/SQL Developer tool in my blog, please read http://lalitkumarb.wordpress.com/2014/08/14/plsql-developer-settings/
I need to capture Oracle stored procedures calls (with parameters) to trace an application (which uses JDBC to connect to the DB). I need something like sp_trace_setevent for Rpc:Completed event in MS SQL SERVER.
I do not have access to this application, but have mostly all rights in the database. I would like to stay in PL/SQL (and Oracle SQL Developer 3.2.20).
I have tried:
Oracle SQL Developer UI "Tools"/ "RealTime SQL Monitoring" and "Tools"/ "Sessions" instruments but can't understand how to enabling accumulating information instead of capturing moment snapshot.
exploring v$sql - it seems there are no sp calls.
v$sqlarea differences (Oracle: is there a tool to trace queries, like Profiler for sql server? , mdj3884 reply) - there I am able to find my test call, but without parameters...
Suggestion from Tom's article : http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:767025833873. Particularly, it is looping through v$sqltext_with_newlines, but I can't understand what is a script result. Something more like moment snapshot; isn't it? But then why they call it tracking?
use DBMS_APPLICATION_INFO - as I understand using this I can add custom info to V$SESSION and V$SESSION_LONGOPS - it can be useful for monitoring tasks but I can't imagine how it can be used for accumulating information about sp calls and theirs parameters.
use DBMS_MONITOR for enabling tracing into file. but I can't find option to enable tracing only sp call events, also it requires access to the server files.
DBMS_PROFILER - collects as I understand by default it collects only statistics (min, max time); there should be possibility to add custom information to plsql_profiler_runs but I can't find this table (when DBMS_PROFILER is in place).
What to see next? What I have missed?
P.S. If the only one way is to change SP body (those SP which need to be traced) then what is the quickest and safest way to log sp parameters from sp body in Oracle? It could be logging to custom table, but may be I could choose between generating another types of events (that are not rollbacked, something like SQL Server custom trace events)?
It would be easy to add some custom functionality to do this (see below for most of what is required) or you could use sqltrace or the enterprise manager reports and search through them:
create package p_audit as
type t_param_type is table of varchar2(50) index by binary_integer;
procedure p_audit (p_procedure varchar2, l_param_type t_param_type);
end;
create table audit_table (procedure_name varchar2(50), parameters varchar2(500))
create or replace package body p_audit is
procedure p_audit (p_procedure varchar2, l_param_type t_param_type) is
pragma autonomous_transaction;
begin
insert into audit_table values (p_procedure,l_param_type(1));
commit;
end;
end p_audit;
declare
l_param_type p_audit.t_param_type;
begin
l_param_type(1):='parameter 1';
p_audit.p_audit('test procedure',l_param_type);
end;
I used DBMS_AUDIT trail to determine what kind of procedures/functions/packages used when a client side application executed. I would really recommend you to use it once, it really helps, but problem is that you cannot analise deeper in a package hierarchy, its function/procedure called (calls), but only its usage. If you want to know dependency of the package you can use ALL_DEPENDENCIES. It can be helpful.
Is it possible to display comments to user while executing a procedure in a package. My package has 3 procedures. I am calling each one after other. I want to display comments on console like procedure xyz is executing, procedure executed successfully. I added comments inside procedure like DBMS_OUTPUT.PUT_LINE('PROCEDURE EXECUTED SUCCESSFULLY') but didn't worked for me.
FYI i am using oracle 11g in windows 7 system.
You can't use DBMS_OUTPUT to display information on a procedure while it is running. This is because DBMS_OUTPUT.put_line doesn't display data on screen, rather, the data is put in a queue that is later read by the calling client (This queue is also invisible outside of its transaction). If you use SQL*Plus the queue is read and displayed automatically at the end of the procedure if you have SET SERVEROUTPUT ON.
Other means exist to follow the progress of a procedure while it is running:
You could write to a file instead. UTL_FILE.put_line will write directly if the parameter autoflush is set to true.
You could set session variables with DBMS_APPLICATION_INFO. These variables can be read with another session by querying v$session.
You could use AUTONOMOUS_TRANSACTIONS to log progress information in a dedicated table. This table can be queried by another session simultaneously.
As you can see you would need another process to read the information while it is written. In some applications, this would be achieved by running the main batch job in a new separate process, for example by calling DBMS_JOB or DBMS_SCHEDULER while the calling transaction loops on the progress table or file until the job is complete.
SQL*Plus is not an interactive client, you will need some more sophisticated environment to achieve this functionality.
How can I update an Apex Tabular Form with pl/sql instead of using a multi-row update(MRU), is it even possible?
Thanks in advance.
Yes, it is possible. You can delete (or disable) the standard processes such as ApplyMRU, and replace them with your own PL/SQL processes to handle the tabular form arrays something like this:
for i in 1..apex_application.g_f02.count loop
update dept
set dname = apex_application.g_f03(i)
where deptno = apex_application.g_f02(i);
end loop;
However, it isn't simple and there is a fair bit you need to know to get this right, such as:
How the tabular form columns map to arrays like apex_application.g_f03 (view the page source and look for the names of the controls, e.g. "f03_0001").
How some item types like checkboxes a work differently to others
How to perform optimistic locking to prevent lost updates
There used to be a "how to" document on apex.oracle.com that described this in detail, but I haven't been able to locate it recently.