i am trying to print specifics detail for a specific record from a database by the following code
procedure TReportsForm.BitBtn1Click(Sender: TObject);
begin
if edit1.Text = '' then
begin
ShowMessage('Please enter the serial number first');
Edit1.SetFocus;
end
else
begin
with AddIndividualsAccountADOQuery do
begin
SQL.Clear;
SQL.Add('Select * from IndividualAccount where [Serial Number]=:Sno');
Parameters.ParamByName('Sno').Value:=edit1.Text;
Open;
Active := True;
singlememberreportform.QuickRep1.Preview;
end;
if AddIndividualsAccountADOQuery.RecordCount = 0 then
begin
ShowMessage('Empty Jonathan database to view records.');
end
end;
end;
the problem is that when i run the program, the quickreport displays all the records in the database instead of printing only records with edit1.text.in other words the report that runs is similar to just typing
procedure TReportsForm.BitBtn1Click(Sender: TObject);
begin
singlememberreportform.QuickRep1.Preview;
end;
Any idea of the problem?
Related
suppose I have a list of procedures p1,p2,p3..pn , each procedure has only one output number parameter, basically each procedure is a constant number. How could I create a loop that runs all these procedures and the results are displayed on the screen? I tried with EXECUTE IMMEDIATE something like:
DECLARE
i number;
n number:=5;
print number;
begin
for i in 1 .. n loop
EXECUTE IMMEDIATE 'BEGIN p'||i||'('||print||') END;' ;
dbms_output.put_line(print);
end loop;
end;
I also tried the form [EXECUTE IMMEDIATE sql_stmt INTO print USING i]
but I still haven't done anything
It's BEGIN myprocedure; END; - you're missing the ";" after the procedure call. It's unclear what you want the "print" to do, that is not declared anywhere so it will just print an empty value.
CREATE OR REPLACE procedure p1
AS
BEGIN
dbms_output.put_line('this is 1');
END;
/
CREATE OR REPLACE procedure p2
AS
BEGIN
dbms_output.put_line('this is 2');
END;
/
DECLARE
n number:=2;
begin
for i in 1 .. n loop
EXECUTE IMMEDIATE 'BEGIN p'||i||'; END;' ;
end loop;
end;
/
this is 1
this is 2
This is the code I've got at the moment:
procedure TfrmLogin.performQuery;
begin
query.SQL.Text := 'SELECT * FROM LoginDatabase';
query.Open;
end;
procedure TfrmLogin.FormCreate(Sender: TObject);
begin
con := TFDConnection.Create(nil);
query := TFDQuery.Create(con);
con.LoginPrompt := false;
con.Open('DriverID=SQLite;Database=C:\Users\katiee\Documents\Embarcadero\' +
'Studio\Projects\ProgramDatabase;');
query.Connection := con;
performQuery;
username := query.FieldByName('Username').AsString;
passcode := query.FieldByName('Passcode').AsString;
end;
procedure TfrmLogin.btnLoginClick(Sender: TObject);
begin
if (edtUsername.Text = username) and (edtPasscode.Text = passcode) then
frmPayInfo.show
else
if MessageDlg('The username or password entered is incorrect.', mtWarning,
[mbOK, mbCancel], 0) = mrCancel then
frmLogin.Close;
end;
Right now the code, as it doesn't read all database entries, only allows the first database entry as correct answer.
I need to be able to enter any correct combination of username and pass-code from the database and open the form.
Why not call the .Locate method on the dataset? This way you will not be opening and closing the dataset, as you would need to with using a parameterised query.
Using the .Locate method will allow you to check (based off one, or many fields) if a certain record can be found.
If the record is found .Locate will return true.
For example.
if query.Locate('username;passcode', VarArrayOf([query.FieldByName('Username').AsString, query.FieldByName('Passcode').AsString]), [loPartialKey]) then
begin
frmPayInfo.show;
end
else
begin
Showmessage('User not found, or password incorrect');
end;
I haven't got Delphi on this machine, so syntax may not be 100%.
I have a little piece of code that gets a corresponding value from database when one is entered, that is, in a database like this
Code Name
1 A
2 B
3 C
When you enter 1 in the code area, it returns A, and if you enter B in the Name area, it returns 2.
I can get this to work just fine with the following code but an error message would pop out showing "Cannot perform this operation on a closed dataset"
Does anyone know how to solve this problem? Any help would be appreciated. Thanks
procedure TStock_Bookkeeping.Stock_Code_ValueChange(Sender: TObject);
begin
Price_Per_Share_Value.Text := GetCurrentPrice(Stock_Code_Value.text);
ExecuteSQL_CodeToName(Stock_Code_Value.Text);
end;
procedure TStock_Bookkeeping.Stock_Name_ValueChange(Sender: TObject);
begin
ExecuteSQL_NametoCode(Stock_Name_Value.Text);
end;
procedure TStock_Bookkeeping.ExecuteSQL_CodeToName(const inCode: string);
var
query : TFDQuery;
begin
query := TFDQuery.Create(nil);
try
ConnectToSQLite;
query.Connection := FDConnection1;
query.SQL.Text := 'SELECT * FROM Code_Name where Code =' + '"' + inCode + '"' ;
query.Active := True;
query.Open();
while not query.Eof do
begin
Stock_Name_Value.text := query.FieldByName('Name').AsString;
query.Next;
end;
finally
query.Close;
query.DisposeOf;
end;
end;
procedure TStock_Bookkeeping.ExecuteSQL_NameToCode(const inName: string);
var
query : TFDQuery;
memTable : TFDMemtable;
begin
query := TFDQuery.Create(nil);
try
ConnectToSQLite;
query.Connection := FDConnection1;
query.SQL.Text := 'SELECT * FROM Code_Name where Name ='+'"'+ inName+'"';
query.Active := True;
query.Open();
while not query.Eof do
begin
Stock_Code_Value.text := query.FieldByName('Code').AsString;
query.Next;
end;
finally
query.Close;
query.DisposeOf;
end;
end;
Set a breakpoint and walk the code (F7):
If the Stock_Code_ValueChange event is connected to the Stock_Code_Value edit box when you change the value of Stock_Code_Value.Text you are changing the value of Stock_Name_Value.Text which then fires the Stock_Name_ValueChange event but you have not completed the Stock_Code_ValueChange event.
Add a Stock_Name_ValueOnChange := nil as the first line of the Stock_Code_ValueChange procedure and a Stock_Name_ValueOnChange := Stock_Name_ValueChange as the last line of the procedure to stop the Stock_Name_ValueChange event from firing while the Stock_Code_ValueChange event is processing.
Then do the opposite for the Stock_Name_ValueChange event.
My query,when run takes about 7 seconds to do what is supposed to.But,since its inserting about 30 records,I think it is too slow.Now,either I am running the query that is not written well or it does actually takes this much time. But that would be strange. The underlying database is SQLite and the query looks like this :
procedure TForm1.cxButton1Click(Sender: TObject);
begin
with UNIquery2 do begin
Close;
SQL.Clear;
UNIQuery1.First;
while Uniquery1.EOF = false do begin
SQL.Text:= 'INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) VALUES (:a1,:a2,:a3,:a4)';
ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text;
ParamByName('a2').asString := UniTable1.FieldByName('FIELD2').asString;
ParamByName('a3').asString := Uniquery1.FieldByName(',FIELD3').asString;
ParamByName('a4').Value := Uniquery1.FieldByName('FIELD4').Value;//boolean field true/false
Uniquery1.Next;
ExecSQL;
end;
end;
end;
So can someone tell me if this is OK or am I missing something ?
All fields are text except the 'a4' which is boolean (true/false).
The answer,modified (based on suuggestion from LS_dev):
procedure TForm1.cxButton1Click(Sender: TObject);
begin
with UNIquery2 do begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) VALUES (:a1,:a2,:a3,:a4)');
SQL.Prepare;
UniTransaction.AddConnection(UniConnection2);
UniTransaction.StartTransaction;
try
UNIQuery1.First;
while Uniquery1.EOF = false do begin
Params[0].asString := AdvOfficeStatusBar1.Panels[0].Text;
Params[1].asString := UniTable1.FieldByName('FIELD2').asString;
Params[2].asString := Uniquery1.FieldByName(',FIELD3').asString;
Params[3].Value := Uniquery1.FieldByName('FIELD4').Value;//boolean field true/false
Uniquery1.Next;
ExecSQL;
end;
UniTransaction.Commit;
finally
if UNIquery2.Connection.InTransaction then
UNIquery2.Connection.Rollback;
end;
end;
end;
Don't know Delphi, but will suggest some improvements:
You are not using a transaction. You should have something like something like auto-commit disabled and COMMIT command after all insertions;
Your SQL.Text:=... should probably be out of while. If this property set compiles SQL statement, putting it out of while will prevent unnecessary VDBE compilations;
If your intent is copying rows from one table to another (with a static field), you may doing using a single SQL command like INSERT INTO MYTABLE SELECT :a1, FIELD2, FIEDL3, FIELD4 FROM source_table, setting ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text
This is generic DB usage improvement, hope gives you some direction.
Suggestion using unique SQL:
procedure TForm1.cxButton1Click(Sender: TObject);
begin
with UNIquery2 do
begin
SQL.Clear;
SQL.Add('INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) SELECT ?,FIELD2,FIELD3,FIELD4 FROM UNIquery1_source_table');
Params[0].asString := AdvOfficeStatusBar1.Panels[0].Text;
ExecSQL;
end;
end;
Suggestion using improved DB handling:
procedure TForm1.cxButton1Click(Sender: TObject);
begin
with UNIquery2 do
begin
Close;
SQL.Clear;
SQL.Add('INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) VALUES (:a1,:a2,:a3,:a4)');
SQL.Prepare;
UniTransaction.AddConnection(UniConnection2);
UniTransaction.StartTransaction;
UNIQuery1.First;
while Uniquery1.EOF = false do
begin
Params[0].asString := AdvOfficeStatusBar1.Panels[0].Text;
Params[1].asString := UniTable1.FieldByName('FIELD2').asString;
Params[2].asString := Uniquery1.FieldByName(',FIELD3').asString;
Params[3].Value := Uniquery1.FieldByName('FIELD4').Value;//boolean field true/false
Uniquery1.Next;
ExecSQL;
end;
UniTransaction.Commit;
end;
end;
If the SQL INSERT itself is slow, I recommend to test its execution speed in an interactive client first. Or write a simple test application which performs one hard-coded INSERT and measures its execution time.
Also you can use the debugger, logging or a profiler to find out the operation in your code which consumes time - it could be the Uniquery1.Next or the ExecSQL for example.
I am a bit new to Oracle and PL SQL. I have a procedure like the following.
{
CREATE OR REPLACE PROCEDURE MyProcedure (MyRecordset OUT SYS_REFCURSOR)
AS
BEGIN
DECLARE
CURSOR MyRecordset IS
select
...
from table1, table2, etc..
BEGIN
FOR Record in MyRecordset
LOOP
--Do something
END LOOP; -- IMPLICIT CLOSE OCCURS
-- THIS IS WHERE I NEED TO RETURN THE CURSOR. DOES THIS NOT OPEN IT AT BEGINNING AGAIN?
OPEN MyRecordset;
END;
END MyProcedure;
/
}
I need to return a SYS_REFCURSOR. Is this sufficient? When I try to test it with the following in Toad I get no output in the data grid.
{
DECLARE
type result_set is ref cursor;
BEGIN
BIZTALK.GetCustomerPaymentsDebug(:result_set);
END;
}
This example works for me. I think it should help you.
Declare cursor like:
TYPE genCurType IS REF CURSOR;
PROCEDURE return_in
( p_ime IN VARCHAR2
, po_seznam OUT genCurType
, po_errid OUT errorIdType
, po_errmsg OUT errorMsgType
)
IS
cc_module_name CONSTANT VARCHAR2(60):= 'return_ins';
BEGIN
OPEN po_seznam FOR SELECT IME, OPIS, NAZIV, OBRAZEC
FROM test
WHERE upper(IME) = upper(p_ime);
EXCEPTION
WHEN OTHERS THEN
po_errid := SQLCODE;
po_errmsg := 'Poizvedba ni bila uspešna! ('||SQLERRM||''||gc_package||'.'||cc_module_name||')';
END;