Insert partly existing data - delphi

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;

Related

Monitoring a table attribute with stored procdeure

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;

How to get value of TDBLookupComboBox?

I have tables on my database Tb_barang and Tb_jenis. Tb_jenis the following columns kd_jenis (primary key) and jenis. I use TDBLookupComboBox to show the items from the Tb_jenis table. There are 6 items (Mie, Susu, etc). I want to save item selected as kd_jenis not jenis.
How to I save jenis in table to kd_jenis?
Sample data: Tb_jenis
jenis kd_jenis
Mie J1
Susu J2
Here it the code I've tried.
if (kd.Text='') or (jenis.Text='Pilih') then
ShowMessage('Data Tidak Lengkap, Silakkan Dilengkapi !')
else
begin
with dm.Qbarang do
begin
sql.Clear;
SQL.Add('select * from Tb_barang where kd_barang='+quotedstr(kd.text)+'');
open;
end;
if DM.Qbarang.Recordset.RecordCount > 0 then
ShowMessage('Data Sudah Ada, Silakkan Isi Yang Lain!')
else
begin
try
DM.koneksi.BeginTrans;
with DM.QU do
begin
close;
SQL.Clear;
SQL.Add('insert into Tb_barang values('+QuotedStr(kd.Text)+','
+QuotedStr(jenis.Text)+')');
ExecSQL;
end;
DM.koneksi.CommitTrans;
ShowMessage('Data Berhasil Disimpan');
except
DM.Qbarang.Close;
DM.Qbarang.Open;
FormShow(sender);
end;
end;
end;
As i understand you want to get Key Value of table from DBLookupComboBox.
so in it is 2 important property in DBLookupComboBox ListField and KeyField
if you set them correctly For Example KeyField set as kd_jenis and List Field Set as jenis then you will see Jenis on List and you can access to jenis in DBLookupCombobox.text and also you can access to KeyField (in this case kd_jenis) by DBLookupCombobox.KeyValue
you should fallow this steps.
Put a TADOConnection to your form for connecting to a database.
build connection string for connecting to Database.
add a ADO table to your form.
Set Connection property to AdoConnection1(Default Name Of ADOCOnnection).
On ADOTable open the Table name Property and select One of your database table and then set active property as true.
Add a DataSource to your form and set Dataset Property as ADOTable1(Default Name of ADOTable)
Add DBLookupCombobox to your form and Set ListSource as DataSource1(the default name of datasource)
Open ListField Property and Select witch field do you want to show in Combobox.
Open the keyField Property and Select witch field is Key field.
All of above Steps should done at Design time. for testing your application add to edit box on your form as edit1 and edit2 then write a small code for OnCloseUp Evwnt of DBLookupCombobox like this
Edit1.Text:=DBLookUpCombobox1.KeyValue;
Edit2.Text:=DBLookupCombobox1.Text;
If you have problems with DBLookupComboBox you may use normal combobox and fill it like the example here.
After someone selects something in your DBLookupComboBox...The cursor to the table is moved.
You can access the value directly:
jenis.ListSource.DataSet.FieldByName('kd_jenis').AsString
This assumes that jenis is a TDBLookupComboBox.
That ListSource.DataSet points to Tb_jenis.
As Craig stated...you have a serious bug in your code...you need a RollbackTrans on exception...other wise you will never release the lock...
DM.koneksi.CommitTrans;
ShowMessage('Data Berhasil Disimpan');
except
DM.koneksi.RollbackTrans;
DM.Qbarang.Close;
DM.Qbarang.Open;
FormShow(sender);
end;
I do something like this...if I need to guarantee saving info and rolling back if fails.
procedure TForm8.SaveData;
begin
Assert(not ADOQuery1.Connection.InTransaction, 'Code problem-We should not be in a Transaction');
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
finally
if ADOQuery1.Connection.InTransaction then
begin
{If you are here...your in an ErrorState...and didn't Commit your Transaction}
ADOQuery1.Connection.RollbackTrans;
HandleError(ADOQuery1);
end;
end;
end;

How can I use a DBLookupComboBox to select a foreign key value without immediately changing the target table? (Delphi 5 Pro)

Basic Scenario:
User clicks 'edit item'
Edit dialog opens
A combobox 'item type' should be populated with items form a table 'item_type'. The combobox should display 'item_type.name', but also know about 'item_type.id'
User edits other item stuff and selects an item type, then clicks ok
My program does some input validation
if everything is ok, get the 'item_type.id' from the selected combo item and save it to the foreign key column of the item table ('item.fk_item_type').
If I understand this component correctly, I should set DataSource to point to the destination table 'item' and DataField to 'item.fk_item_type'. But that would immediately edit my item table before I get a chance the validate all the other input.
It feels like I am missing something here. Somewhere I read that I need to use a classic ComboBox and fill it manually. But then I don't understand how to get to the id of the selected item.
Thank you for any pointers.
Edit:
I am starting to suspect that maybe I am missing a fundamental thing. All these DB* components, do they load values from that database automatically, but I have to call Post() myself? Meaning they do not automatically change values in the database?
If I understand you correctly, you want to use a DBLookupComboBox. You have to supply values for the following properties
datasource - linked to the table which you are editing, presumably 'items'
datafield - the name of the field in the table which you are editing, presumably 'item_type'
listsource - linked to the table which populated the combobox, presumably 'item_types'
list field - the name of the field from 'item_types' which you want to display, presumably 'name'
key field - the name of the field from 'item_types' which will be inserted into the items record, presumably 'item_type'
The table which populated the combobox is never edited.
You can validate the values before posting the new/edited 'items' record.
I can show you how to use a non-data aware combobox if necessary, but it's easier to use the data aware version.
Regarding validation, I use the following code template in edit dialogs.
Function TEditQuestion.Execute (n: longint): boolean;
var
gen: longint;
begin
sdsEditQuestion.params[0].asinteger:= n; // TSQLDataSet
with qEditQuestion do // TClientDataSet
begin
open;
if n = -1 then // new record
begin
caption:= 'New record';
insert;
fieldbyname ('alive').asinteger:= 1;
// initialise necessary fields in the dataset
end
else caption:= 'Editing record ' + inttostr (n);
edit;
if showmodal = mrOK then
begin
// validation code comes here. Set 'result' to true if everything is ok
if result then
begin
if n = -1 then
begin
with qGenID do
begin
open;
gen:= fields[0].asinteger; // get new value from generator
close
end;
FieldByName ('id').asinteger:= gen;
end;
post;
applyupdates (0)
end
else cancel // showmodal = OK, result = false
else // showmodal cancelled
begin
cancel;
result:= false
end;
end // with qEditQuestion
end;

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;

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