How do I check the status of a checkbox (checked or not checked) on my Form and then pass it on to my SQL insert query?
I've got the parameter in my stored procedure:
#p6 bit
However, in Delphi is the problem :
DataModule7.SP_INSERT.ParamByName('p6').AsBoolean := cxCheckbox1.Properties; //???
Does someone know how to do this?
What you need is
DataModule7.SP_INSERT.ParamByName('p6').AsBoolean := cxCheckbox1.Checked;
Assuming you are executing this code from the Form containing cxCheckBox1.
Related
We have some few packages where we need to resolve some SQL Injection issues. I need some help to rewrite sql statement or sanitize the inputs. Below is the line number where veracode throw the error.
open c_ccl (p_part_nr,p_ctry_cd);
// Source code
CREATE OR REPLACE EDITIONABLE PACKAGE BODY "schema"."Test_PKG" AS
v_data t_cla_class_data;
FUNCTION nat_eccn_cd( p_part_nr IN t_part_nr, p_ctry_cd IN t_ctry_cd )
RETURN t_us_eccn_cd IS
CURSOR c_ccl(p_part_nr CHAR, p_ctry_cd CHAR) IS
SELECT NAT_CCL_CD FROM CLSDBA.CLA_EXP_PART_CTRY e
WHERE e.PART_NR = p_part_nr AND e.CTRY_CD = p_ctry_cd
ORDER BY e.VAL_FROM_DT DESC;
v_ctry_cd char(4) := p_ctry_cd;
v_trf_cd char(4);
BEGIN
v_data.nat_eccn_cd := NULL;
open c_ccl (p_part_nr,p_ctry_cd);
fetch c_ccl INTO v_data.nat_eccn_cd;
close c_ccl;
return (trim(v_data.nat_eccn_cd));
exception when others then return NULL;
end;
I don't see any SQL injection issues with your code - there is no dynamic code where the user inputs could be evaluated and escape out of the expected code flow. Unless your code snippet is generated somewhere else, or one of the column names is really a function that calls dynamic SQL, your code looks safe.
You used the phrase "sanitize the inputs", which is terrible advice for database programming. As much as I love the comic strip XKCD, Randall got this one wrong.
Bind variables are the best solution to avoiding SQL injection. I'll take this opportunity to (poorly) change his comic:
This is the error I get when I run the code below. I'm not too sure what's wrong any help is appreciated
procedure TFSearchMember.btnSearchClick(Sender: TObject);
var buttonSelected:integer;
WhereTextSelection,WhereFieldSelection:string;
begin
WhereFieldSelection:=cboWhereField.Text;
WhereTextSelection:=txtWhere.Text;
adoQuery1.Parameters[0].Value:=WhereTextSelection;
adoQuery1.Open;
ADOQuery1.Requery;
txtWhere.Text:='';
cboWhereField.Text:='';
if ADOQuery1.RecordCount=0 then
begin
buttonSelected:=MessageDlg('Record not found.', mtError, [mbOK],0);
if buttonSelected = mrOK then
Exit;
end;
I also have this in the ADOQuery SQL property
Although your question doesn't say so, I'd suspect that you're trying to allow the user to both select the field to use in the WHERE (from cboWhereField) and the value (from txtWhere). If that's the case, you have to update the SQL first before you can assign the parameter, as both are changing.
Something like this should work (in a basic sense):
procedure TFSearchMember.btnSearchClick(Sender: TObject);
const
SQLBase = 'SELECT * FROM tblMembers WHERE %s = :SearchValue';
begin
if AdoQuery1.Active then
AdoQuery1.Close;
AdoQuery1.SQL.Text := Format(SQLBase, [cboWhereField.Text]);
AdoQuery1.Parameters.ParamByName('SearchValue').Value := txtWhere.Text;
AdoQuery1.Open;
txtWhere.Text:='';
cboWhereField.Text:='';
if not ADOQuery1.IsEmpty then
begin
// No need for if test here, as you're only offering one value.
// MessageDlg can't return anything other than mrOK
MessageDlg('Record not found.', mtError, [mbOk], 0);
Exit;
end;
// Your other code
end;
I assume that not all code is shown, because it seems that you try to create dynamic SQL where the "WhereFieldSelection" can be changed to whatever is shown in the combobox. If you change the SQL.Text property (e.g. to use "Forename") of the ADOQuery AFTER the parameter value is set, the value of the parameter is lost, and you will have to reset it. Also, the Requery, is not necessary, as Ken White mentioned.
I'm only a beginner in learning to use Parameterised Queries as I used to do a lot of concatentating before. I've been trying to get this query below to work. It is a simple 'Book' table, with a field called 'BookTitle'. I have a simple textbox where I invite the user to enter any title...and it should run the query below to find if that book exists. Below is my code that, when run, manages to compile. However, when an entry into the textbox is added and the button to run the query is pressed, a Debugger Exception Notification appears with the following statement.
Debugger Exception Notification: Project Project1.exe raised exception class EOleException with message 'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another'.
I then have the option to press 'Break' or 'Continue'. If I press 'Break', the line:
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
is filled with a purple/red colour (not sure what this means?).
That said, if I press 'Continue', the program will work as expected, and will continue to do so. Here is the code i've been testing.
procedure TForm4.btnRunQueryClick(Sender: TObject);
var BookEntry:string;
begin
BookEntry:=edtBookTitle.Text;
qbook.SQL.Text:='SELECT BookTitle FROM Book WHERE BookTitle = :BookTitle';
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
qbook.Parameters.ParamByName('BookTitle').Value := BookEntry;
qbook.Open;
end;
Further points to note: The components in my Delphi form are as follows
a TADOQuery named 'qbook',
a TDataSource,
a TDBGrid,
aTEdit into which the user enters their desired search criteria and
a TButton that once pressed, initiates the query.
With regards to the database, it is:
a MySQL database (Community Edition)
a table named 'Book', where BookID is the PK and is of INT data type.
a field entitled 'BookTitle' which i've set as VARCHAR(35). It is not part of the key. However, it is in the BookTitle field, that i want to apply my query.
NOTE: This answer was posted based on the original code in the question, which has been edited to match what is in my answer. See the question's revision history for the first version of the question on which my answer was based.
The solution you saw in the other post was correct; it was just for a standard TQuery and not TADOQuery. TADOQuery requires a couple of minor syntax changes:
Use Parameters.ParamByName() instead of Parameters
Set a DataType for each parameter before using it
Use .Value instead of .AsString
Here's a corrected version of your code (which also includes setting a value for BookTitle before using it.
procedure TForm4.btnRunQueryClick(Sender: TObject);
var
BookEntry:string;
begin
BookEntry := 'Some book title'; // or QueryEdit.Text or whatever
qbook.SQL.Text:='SELECT BookTitle FROM Book WHERE BookTitle = :BookTitle';
qbook.Parameters.ParamByName('BookTitle').DataType := ftString;
qbook.Parameters.ParamByName('BookTitle').Value := BookEntry;
qbook.Open;
end;
I have never known a string type query parameter need the datatype or whatever set, I would simply remove any reference to the datatype.
After all, if it hurts when you bang your head on a wall, just stop banging it.
I'm working with Oracle Forms. I have a field named SOLD_TO_CUST_PARTY_NAME. I have to execute a process if I detect a change in the field's value. I tried using when_validate, but it's executed even if you just click the field and move to another field (validation ALWAYS occurs whether you change the value or not). Is there anyway I can check :old and :new or something similar to execute a process only if the field is modified?
EDIT:
Can't use personalizations. It has to be done with pl/sql.
There is a property called database value that let you check if the field has been modified and if it has not you just have to exit the validation trigger.
Ex.
BEGIN
IF :BLOCK.ITEM = GET_ITEM_PROPERTY('BLOCK.ITEM', database_value) THEN
RETURN;
END IF;
/* VALIDATION */
END;
I have done right click on the SP and the right side has an embedded table that has the params but I can't seem to enter the params there. I was able to do what I needed in PL SQL but how do I run SP's now?
you can run via block of plsql code.
if you want to run only you can use following types of block--
declare
/*
parameter declaration .. just like your parameter types in SP.
like ..
*/
l_p_input_1 varchar2(980):= '<value you want to give>';
l_p_input_2 number := 33;
l_p_output_1 varchar2(889);
begin
sp_your_sP_name(l_p_input_1,
l_p_input_2,
l_p_output_1);
dbms_output.put_line('l_p_output_1 : '||l_p_output_1);
end;