Monitoring a table attribute with stored procdeure - stored-procedures

I am working on a stored procedure that monitors the Last_Extract_Ts value in the table that provides information about Extract Transform Load(ETL). Now I want to check whether the Last_Extract_ts value changed from the last time the procedure ran, but I can't quite figure out how to store the result of the last procedure run so that I can use it in the current one.
Below is my procedure
create or replace PROCEDURE MONITOR AS
v_count number:=0;
v_Last_Extract_Ts VARCHAR2(80) := '';
v_Last_ETL_Run VARCHAR2(80) := '';
BEGIN
select count(*) into v_count from oms_etl_config where ATTR_NM='last_extract_ts' and process_type='upd' and ATTR_VALUE<=to_char(sys_extract_utc(systimestamp)-5/1440,'YYYY-MM-DD HH24:MI:SS');
select Attr_value into v_Last_Extract_Ts from OMS_ETL_CONFIG where PROCESS_TYPE='upd' AND ATTR_NM='last_extract_ts';
Select MAX(START_TS) into v_Last_ETL_Run from OMS_ETL_AUDIT;
dbms_output.put_line(v_count);
dbms_output.put_line(v_Last_Extract_Ts);
dbms_output.put_line(v_Last_ETL_Run);
END;
I came across something like storing the result of the stored procedure in a temp table in Insert results of a stored procedure into a temporary table , Exec stored procedure into dynamic temp table but I can't quite see how it meets my needs.
Is what I am trying to achieve possible or I need to have a different approach.
Thanks in advance.
P.S. I am absolute beginner with PL/SQL and stored procedures so I am
not having any attempt in my post to show for the research I have done. Sorry for that.

The simplest way is to save the last results in a table.
create a table:
Create table monitor_results
(
last_run_date date
, last_Last_Extract_Ts varchar2(80)
, last_ETL_Run varchar2(80)
, last_count NUMBER
);
initialize values:
insert into monitor_results values (NULL, NULL, NULL, NULL);
commit;
in the stored procedure update the values in the table:
...
update monitor_results
set
last_run_date = SYSDATE
, last_Last_Extract_Ts = v_Last_Extract_Ts
, last_ETL_Run = v_Last_ETL_Run
, last_count = v_count
;
commit;

You can do this check using a trigger: See below:
CREATE OR REPLACE TRIGGER reporting_trigger
AFTER UPDATE ON <Table>
FOR EACH ROW
BEGIN
/**Your column which holds the record**/
IF :new.a = :old.a THEN
raise_application_error( -20001, 'This is a custom error' );
END IF;
END;

Related

Unable to retrieve multiple rows using cursor from database table using stored procedure DB2

I am trying to retrieve multiple rows from table using stored procedure and it doesn't work for me. My stored procedure is as follows,
CREATE OR REPLACE PROCEDURE E_Enquiry
(IN SourceQueue1 VARCHAR(30) ) LANGUAGE SQL
BEGIN
DECLARE C1 CURSOR FOR
select CreationTime
from ms.Exception_Message
where SourceQueue = SourceQueue1;
open c1;
END;
I am trying to call the stored procedure from Mule Anypoint Studio using the Database connector and have seen the result as null when I print the payload with a logger. If I try to modify the query as it returns a single row it works (without using cursor).
Please help to resolve this. Thanks.
What platform and version of DB2?
Try the adding
DYNAMIC RESULT SETS 1
WITH RETURN TO CLIENT
Like so:
CREATE OR REPLACE PROCEDURE E_Enquiry
(IN SourceQueue1 VARCHAR(30) )
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE C1 CURSOR WITH RETURN TO CLIENT FOR
select CreationTime
from ms.Exception_Message
where SourceQueue = SourceQueue1;
open c1;
END;

Insert partly existing data

I need to add extra data to my TEMP table shown at the bottom on button click.
I need all existing occurences of FROM - TO - DAYS in the table duplicated and inserted.
RATE_PRICE would be predetermined & and the same for all new inserts (when inserting).
and also inserted.
Example : I have an extra bed to add and it costs 15 euros.
Now I would like to, when I check a checkbox (and click on a button) to insert that value (15) in the TEMP table but
it must follow the displayed dates values in the grid.
I had in mind adding extra field in the TEMP table called EXTRA which would be invisible unless
checkbox checked. So when I check an option of adding an extra bed, the extra bed would follow the displayed.Rate price would be 15 then ...
dates.
How can I insert desired data ?
UPDATE
I did it on button click :
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
with ABSQuery4 do begin
ABSQuery4.Close;
ABSQuery4.SQL.Clear;
ABSQuery4.SQL.Text := 'INSERT INTO TEMP (extra,Date_From,Date_To,Rate_price,Days,Total) VALUES (:a1,:a2,:a3,:a4,:a5,:a6)';
ABSquery4.Params.ParamByName('a1').asString :='TT';
ABSquery4.Params.ParamByName('a2').value := cxDateEdit1.date;
ABSquery4.Params.ParamByName('a3').value := cxDateEdit2.date;
ABSquery4.Params.ParamByName('a4').value :='1';
ABSquery4.Params.ParamByName('a5').value :=Daysbetween(cxDateEdit1.Date,cxDateEdit2.Date);
ABSquery4.Params.ParamByName('a6').value := (ABSquery4.Params.ParamByName('a4').value)*(ABSquery4.Params.ParamByName('a5').value);
ABSquery4.ExecSQL ;
ABSquery2.Refresh;
end;
end;
Any more elegant way ?
You should new readers to point out to which, previous question (code), you are referring. Without this information, they can not understand your question. Hotel prices spanning multiple dates issue
Now to your Question.
Forget your with absquery4 do begin, there is an easier way.
With only 2 new lines of code added to your existing code.
Expand your price list to all the extras you need.
e.g. DBLMSExtraBed : 'Price:15,00`.
Add a new Button Caption:='Add Extras`.
clickEvent pointing to your CalculationButtonClick.
Test in CalculationButtonClick from wich button the event is fired.
Fill out ROOM_TYPE TEditfield with DBLMSExtraBed.
Add following WITH .. IF .. THEN
...
with sender As TButton do if name='DoCalc' then begin
above
ABSQuery2.Close;
ABSQuery2.SQL.Text:='DELETE from TEMP';
ABSQuery2.ExecSQL;
ABSQuery2.SQL.Text:='SELECT * from TEMP ORDER BY ID ';
ABSQuery2.Open;
and an end;
end;
If the Event is fired from AddExtrasButton . It will not clear your Temp-Table.
So the Table is still open and the new Data will be inserted.
Now you have 3 Rows, last is :
With the AddExtrasButton you can add as much extras you like, as long there are extras in the Pricelist.
Used Table:
CREATE DATABASE IF NOT EXISTS pricelist;
USE pricelist;
DROP TABLE IF EXISTS `room_rates`;
CREATE TABLE `room_rates` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`CENIK_ID` int(10) unsigned NOT NULL,
`ROOM_TYPE` varchar(45) NOT NULL,
`RATE_START_DATE` datetime NOT NULL,
`RATE_END_DATE` datetime NOT NULL,
`RATE_PRICE` decimal(5,2) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
/*!40000 ALTER TABLE `room_rates` DISABLE KEYS */;
INSERT INTO `room_rates` (`ID`,`CENIK_ID`,`ROOM_TYPE`,`RATE_START_DATE`,`RATE_END_DATE`,`RATE_PRICE`) VALUES
(1,1,'DBLMS','2013-01-02 00:00:00','2013-04-26 00:00:00','128.00'),
(2,1,'DBLMS','2013-10-22 00:00:00','2013-12-18 00:00:00','128.00'),
(3,1,'DBLMS','2013-04-26 00:00:00','2013-06-22 00:00:00','146.00'),
(4,1,'DBLMS','2013-09-21 00:00:00','2013-10-20 00:00:00','146.00'),
(5,1,'DBLMSExtraBed','2013-01-02 00:00:00','2013-06-22 00:00:00','15.00');
Update :
Only a Tipp:
Create in your Temp Table a Field EXTRAS.
procedure TForm1.AdvGlowButton1Click(Sender: TObject);
var
isExtra : Boolean;
[...]
with sender As TButton do if name='AdvGlowButton1' then
isExtra := False else
isExtra := True;
if NOT isExtra then begin
ABSQuery2.Close;
ABSQuery2.SQL.Text:='DELETE from TEMP';
ABSQuery2.ExecSQL;
ABSQuery2.SQL.Text:='SELECT * from TEMP ORDER BY ID ';
ABSQuery2.Open;
end;
[...]
if isExtra then
ABSQuery2.FieldByName('EXTRAS').AsString:=mem_ROOM_TYPE
else
ABSQuery2.FieldByName('ROOM_TYPE').AsString:=mem_ROOM_TYPE;

Get specific fields from sys_refcursor in stored proc?

I am running an Oracle 9i server at my office. I am working on a procedure that passes a sys_refcursor as an out parameter to another package (along with other in parameters). I was able to define a type as a record of the various columns that the called procedure returns in the cursor. I can then loop over with code like this:
LOOP
fetch o_results into v_rec;
exit when o_results%notfound;
dbms_output.put_line(v_rec.some_id);
end loop;
Is there a way to only pull one column and not have to declare an entire rowtype? I tried something like:
LOOP
fetch o_results.some_id into v_id;
exit when o_results%notfound;
dbms_output.put_line(v_id);
end loop;
But that didn't work. Any other ideas?
No, you cannot fetch a single column into a local variable other than a record if the cursor returns a result set with multiple columns. However, you do have a few alternatives.
If you declare a strongly-typed cursor rather than a weakly typed cursor, you could declare your local variable based on that cursor definition rather than declaring a new collection.
create or replace procedure cursor_proc
as
cursor emp_cur
is
select empno, ename
from emp;
l_row emp_cur%rowtype;
begin
open emp_cur;
loop
fetch emp_cur into l_row;
exit when emp_cur%notfound;
dbms_output.put_line( l_row.ename );
end loop;
close emp_cur;
end;
Alternately, if you know that the weakly typed ref cursor will always return all the columns in a particular object, you can anchor your local variable declaration to that object. You can always make this work by declaring a view that your cursor selects from. For example
create or replace view vw_emp
as
select ename, empno
from emp
create or replace procedure cursor_proc2
as
emp_cur sys_refcursor;
l_row vw_emp%rowtype;
begin
open emp_cur for select * from vw_emp;
loop
fetch emp_cur into l_row;
exit when emp_cur%notfound;
dbms_output.put_line( l_row.ename );
end loop;
close emp_cur;
end;
Finally, if you use an implicit cursor, Oracle will implicitly declare the collection type
create or replace procedure cursor_proc3
as
begin
for emp in (select ename, empno from emp)
loop
dbms_output.put_line( emp.ename );
end loop;
end;

delphi Ado (mdb) update records

I´m trying to copy data from one master table and 2 more child tables. When I select one record in the master table I copy all the fields from that table for the other. (Table1 copy from ADOQuery the selected record)
procedure TForm1.copyButton7Click(Sender: TObject);
SQL.Clear;
SQL.Add('SELECT * from ADoquery');
SQL.Add('Where numeracao LIKE ''%'+NInterv.text);// locate record selected in Table1 NInterv.text)
Open;
// iniciate copy of record´s
begin
while not tableADoquery.Eof do
begin
Table1.Last;
Table1.Append;// how to append if necessary!!!!!!!!!!
Table1.Edit;
Table1.FieldByName('C').Value := ADoquery.FieldByName('C').Value;
Table1.FieldByName('client').Value := ADoquery.FieldByName('client').Value;
Table1.FieldByName('Cnpj_cpf').Value := ADoquery.FieldByName('Cnpj_cpf').Value;
table1.Post;
table2.next;///
end;
end;
//How can i update the TableChield,TableChield1 from TableChield_1 and TableChield_2 fields at the same time?
do the same for the child tables
TableChield <= TableChield_1
TableChield1 <= TableChield_2
thanks
The fields will all be updated at the same time. The actual update is performed when you call post (or not even then, it depends if the Batch Updates are on or off).
But please reconsider your logic. It would be far more efficient to use SQL statements (INSERT) in order to insert the data to the other table
SQL.Clear;
SQL.Add('INSERT INOT TABLE_1(C, client, Cnpj_cpf)');
SQL.Add('VALUES(:C, :client, :Cnpj_cpf)');
Then just fill the values in a loop.
SQL.Parameters.ParamByName('C').Value := ADoquery.FieldByName('C').Value;
SQL.Parameters.ParamByName('client').Value := ADoquery.FieldByName('client').Value;
SQL.Parameters.ParamByName('Cnpj_cpf').Value := ADoquery.FieldByName('Cnpj_cpf').Value;
SQL.ExecSQL;
You can also do the Updade - Insert pattern if the data can alredy be in the target table.
Like This:
if SQL.ExecSQL = 0 then
begin
// no records were update, do an insert
end;
And also the indication that you are copying data from table 1 to table 2 could be a sign of design flaw. But I can't say that for sure without knowing more. Anyway data duplication is never good.
I believe the asker was thinking about the data integrity, that means, ensure that only all the tables will updated or none...
The way I know to achieve this with security is executing all this updates (or inserts, a.s.o.) using SQL commands inside a transition.

How can I use Integer Auto Increment Field in DBx4 with BlackFish?

I am trying to use auto incremental fields in dbx4 with a black fish database
I have a simple table Structure:
CREATE TABLE tblTABname (
ID int AUTOINCREMENT Primary Key,
Description varchar(100) NOT NULL );
Before Open I am doing the :
qryTAB.FieldByName( ‘ID’).AutoGenerateValue := arAutoInc;
cdsTAB.FieldByName( ‘ID’).AutoGenerateValue := arAutoInc;
After Open:
qryTab.FieldByName('ID').ProviderFlags := [pfInWhere, pfInKey];
cdsTab.FieldByName('ID').ProviderFlags := [pfInWhere, pfInKey];
If I do:
cdsTAB.Edit;
cdsTAB.FieldByName(‘Description’).value := ‘Test’;
cdsTAB.Post;
Or if I use this in a DBGRID, it fails with the error :
“Field ‘ID’ must have a value”
Witch should have been generated .
If I run an INSERT Query it works fine, with or without the “AutoGenerateValue := arAutoInc” lines.
How can I overcome this problem?
Instead of calling CDSTab.EDIT, call CDSTab.INSERT to add a new row, only call CDSTab.EDIT when your cursor is on a record already, and to edit the value of that record.

Resources