I have a problem with issuing a SQL statement. I know that the English value should be a string on its own and I've tried that but it keeps throwing me one of these errors
procedure TfrmPetersonGroup.btnEnglishClick(Sender: TObject);
var
sSqlQuery:string;
begin
//2.4
dmoBandB.qryQuery.SQL.Clear;
sSqlQuery:='DELETE FROM tblClients WHERE Nationality =' + ' English';
dmoBandB.qryQuery.SQL.Text := sSqlQuery;
dmoBandB.qryQuery.active := true;
end;
I suggest you get a safe query. As below:
procedure SafeDeleteReq(SQLQuery: TSQLQuery; del: string);
begin
SQLQuery.SQL.Text := 'DELETE FROM tblClients WHERE Nationality=:Nationality';
SQLQuery.ParamByName('Nationality').AsString := del;
SQLQuery.ExecSQL();
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SafeDeleteReq(SQLQuery1, 'English');
end;
You could change your sSql to
sSqlQuery:='DELETE FROM tblClients WHERE Nationality = ' + QuotedStr('English');
just to get it working, but that's not the best idea, see below.
Your version of it caused the error because, without quotes around it, the Sql parser thought that English was an identifier, e.g. another column name like Nationality.
Using QuotedStr around column values ensures that single-quote characters embedded in the value, like
O'Brien
are escaped correctly.
The other thing is that you should replace
dmoBandB.qryQuery.active := true;
by
dmoBandB.qryQuery.ExecSql;
The reason is that setting Active to True is equivalent to calling .Open, which is invalid in this context because .Open only works if the Sql query returns a result set and DELETE does not (sorry, I should have noticed this problem first time around). Once you've called ExecSql, you can reopen the table by setting qryQuery's Sql.Text to a valid SELECT statement and then calling .Open.
However, a betteer way to avoid your initial problem would be to get into the habit of using parameterised Sql statements - see http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_Parameters_in_Queries, which is applicable to all Sql DML statements (Insert, Delete, Update, Select, etc). Apart from anything else, this may help you avoid Sql Injection exploits (https://en.wikipedia.org/wiki/SQL_injection).
While executing a simple stored procedure getting a warning compiled but compilation error how to see.
Below is the query:
create procedure spgetdat
as
begin
select empis empname, empadd from tb1employees;
end;
While executing above query getting an error. Pls suggest what needs to be corrected.
Regards
Jitendra
Your Select statement inside the procedure is not correct. There should be into clause in the select statement inside the PL/SQL block.
It can be like below. You have to put a where condition for selection of one record or for best practice you can use cursor to fetch more then one record also.
create procedure spgetdat
as
v_empis tab1employees.empis%type;
v_empadd tab1employees.empadd%type;
begin
select empis empname ,empadd into v_empis,v_empadd from tb1employees where empis = 'given name' ;
end;
show errors;
Problem that I was facing is that I have to call one stored procedure from another stored procedure in DB2 database. Kind example that I am giving right below.
I have one stored procedure:
CREATE OR REPLACE PROCEDURE Proc1()
IS
Declare myName in varchar;
BEGIN
Select fname into myName from student where fname='x'; // is returning unique value
-- here call anoher proc2
END;
Now so this proc1 procedure is going to call this proc2 procedure.
Now I have second stored procedure:
CREATE OR REPLACE PROCEDURE Proc2(Name in varchar)
IS
BEGIN
-- do anything
END;
I solved this problem,
So solution is like If we want to execute proc using sql command then syntex is like below,
call Proc2('My Name');
We can use this same approach inside our proc also.
For that we have to follow some steps. Lets say that our above sql call is statement that we want to execute. we are going to convert that statement into String and pass necessary parameter by concating variable values. Then execute statement.
CREATE OR REPLACE PROCEDURE Proc1()
IS
Declare myName in varchar;
-- stmt variable is to execute our proc
STMT VARCHAR(4000);
BEGIN
Select fname into myName from student where fname='x'; // is returning unique value
-- this is our logic
STMT :='call Proc2('||myName||')';
EXECUTE IMMEDIATE STMT;
END;
In many tutorials i read how to select data from a database in a datasnap client, p.e. to complete a dbgrid.
But i need now to know how to insert or update a row, p.e "new client". Can everybody recommends me a book or tutorial?
I have an sqlconnection on a clientdatamodule on the clientside apart from clientclassesunit. I was prooving wuth an SQLQuery with an insert SQL Statement but it doen't function.
On the other han i have on the server side:
procedure TServerMethods1.nuevocheque(idcliente,numero,cuenta,idbanco : integer; fr,fc, titular:string ;importe:Double;cobrado:Boolean);
var
ucheque:integer;
begin
with qicheque do
begin
Open;
ParamByName('idcliente').AsInteger:=idcliente;
ParamByName('numero').AsInteger:=numero;
ParamByName('fr').AsDate:=StrToDate(fr);
ParamByName('fc').AsDate:=StrToDate(fc);
ParamByName('importe').AsFloat:=importe;
ParamByName('titular').AsString:=titular;
ParamByName('cobrado').AsBoolean:=cobrado;
ParamByName('cuenta').AsInteger:=cuenta;
ExecSQL();
end;
end;
With this method i try to insert, the statement is into SQL property of the component.
On the client side, i have a TSQLServerMethod wich calls "nuevocheque":
procedure TForm4.BGuardarClick(Sender: TObject);
var
idcliente,numero,cuenta,idbanco:integer;
titular:string;
cobrado:Boolean;
fr,fc:string;
importe:Double;
begin
ClientModule1.nuevocheque.Create(nil);
with ClientModule1.nuevocheque do
begin
idcliente:=1;
numero:=StrToInt(ENumero.Text);
cuenta:=StrToInt(Ecuenta.Text);
idbanco:=1;
titular:=ENombre.Text;
cobrado:=False;
importe:=StrToFloat(EMonto.Text);
fr:=EFechaEmision.Text;
fc:=EFechacobro.Text;
end;
end;
But it doesn´t function.
Thank for your help
Well, i achieve inserting data into mysql database i had desgined.
This is te code in delphi into a button:
procedure TForm4.BGuardarClick(Sender: TObject);
var
idcliente,numero,cuenta,idbanco:integer;
titular:string;
cobrado:Boolean;
fr,fc:string;
importe:Double;
a:TServerMethods1Client;
interes:Double;
begin
a:=TServerMethods1Client.Create(ClientModule1.SQLConnection1.DBXConnection);
begin
idcliente:=Unit3.id;
numero:=StrToInt(ENumero.Text);
cuenta:=StrToInt(Ecuenta.Text);
idbanco:=lcbbanco.KeyValue;
titular:=ENombre.Text;
cobrado:=False;
if (EP.Text<>'') then
begin
importe:=StrToFloat(EHC.Text);
end
else
begin
importe:=StrToFloat(EMonto.Text);
end;
fr:=EFechaEmision.Text;
fc:=EFechacobro.Text;
end;
a.nuevocheque(idcliente,numero,cuenta, idbanco,fr,fc,titular,importe,cobrado);
end;
I've called to method create() with the SQL component such as M Diwo said me.
Im too hapy. Thanks to all
I don't know what you use as database connection, for my own convenience I have slightly modified for dbGO (parameters passed by variant).
Also I have made a function from the server method, like this the client can be notified that there has been a problem (with the query, connection,...). Here is the server method:
//server
function TServerMethods1.NuevoCheque(idcliente, numero, cuenta,
idbanco: integer; fr, fc, titular: string; importe: Double;
cobrado: Boolean): Boolean;
begin
try
with qicheque, Parameters do
begin
Close;
ParamByName('idcliente').Value:=idcliente;
ParamByName('numero').Value:=numero;
ParamByName('fr').Value:=StrToDate(fr);
ParamByName('fc').Value:=StrToDate(fc);
ParamByName('importe').Value:=importe;
ParamByName('titular').Value:=titular;
ParamByName('cobrado').Value:=cobrado;
ParamByName('cuenta').Value:=cuenta;
ExecSQL();
end;
Result := true;
except
Result := false;
//raise; <-- uncomment if you want to handle this properly in your code
end;
end;
For the client I suppose you generated a proxy unit that generally creates an object called ServerMethods1 ?
You must pass the client dbx connection to this - I say this because I saw you put nil in your code.
// client
procedure TfrmClient.BGuardaClick(Sender: TObject);
var
sm : TServerMethods1Client; // <-- generated by proxy generator
idcliente,numero,cuenta,idbanco : integer;
fr,fc, titular : string ;
importe : Double;
cobrado : Boolean;
begin
sm := TServerMethods1Client.Create(SQL.DBXConnection);
if sm.nuevocheque(idcliente,numero,cuenta,idbanco, fr,fc, titular, importe, cobrado) then
// ok
else
// error
sm.Free;
end;
hth
You can use calls to remote methods, but they won't automatically update your data aware controls automatically. Datasnap is able to handle it. First, you need to add/update/remove data on the client. It happens in the local cache managed by the TClientDataset, even when you "Post".
When you're ready, you need to "apply" changes to the remote server calling the Apply() method.
When you call it, the provider component on the server receives a "delta" with the record to change from the client dataset, and will automatically generate the needed INSERT/UPDATED/DELETE SQL statements.
If you don't like them, or you need to perform more complex processing, you can use the provider events to perform the needed operations yourself for each changed record and then tell the provider you did it to avoid the automatic processing. Then the provider passes back the "delta" to the client, where it is used to updated the data aware controls. You can also modify the "delta" before it is passed back.
Read in the documentation the explanation of the Datasnap architecture - it's a multistep design where several components work to allow for a multi-tier implementation.
I am working on Delphi application which deals with stored procedures.I created stored procedure for insert statement and it works fine for my application.
Now,I wanted to create the same for select statement.
CREATE TYPE list_all_firstname AS ( first_name character varying);
CREATE FUNCTION select_sp()
RETURNS SETOF list_all_firstname AS
$$
DECLARE
rec record;
BEGIN
FOR rec IN (SELECT first_name FROM person) LOOP
RETURN NEXT rec;
END LOOP;
END;
$$ LANGUAGE plpgsql;
The call is:
SELECT * FROM select_sp();
Till this everything is fine in postgres.I wanted to access this stored procedure in my delphi application.
My code is:
with StoredProc2 do begin
StoredProcName :='select_sp';
ExecProc;
Edit5.Text:=ParamByName('list_all_firstname').AsString ;
end;
But i gets the error saying "Could not find object".How do i access return values of stored procedure in delphi??
I got the answer..could not find object is BDE error...
Next thing is accessing values,no need to use stored procedure component.We can use TQuery as below...:
Query1.SQL.Clear;
Query1.SQL.Add('SELECT * FROM select_sp()');
Query1.Active := True;
for i:=0 to Query1.RowsAffected-1 do
begin
sval:=Query1.FieldByName('first_name').AsString;
ShowMessage(sval);
Query1.Next;
end;