update statement throw exception - delphi

I wrote this query:
Ado_All.Parameters.Clear;
Ado_All.SQL.Clear;
Ado_All.SQL.Add('update Tbl_Customer_Services set fk_Customer =:0, fk_Services =:1, Start_Date =:2, End_Date=:3');
Ado_All.SQL.Add(' ,Hesab =:4, Domain_Name =:5,Comments =:7 where Customer_Services_Id =:6 ');
Ado_CmbNames.MoveBy(Cmb_Customer.ItemIndex);
Ado_All.Parameters[0].Value := Ado_CmbNames.FieldByName('Customer_Id').AsString;
Ado_All.Parameters[1].Value := '1';
Ado_All.Parameters[2].Value := '10/10/2010';
Ado_All.Parameters[3].Value := '10/10/2010';
Ado_All.Parameters[4].Value :=Txt_Mali.Text;
Ado_All.Parameters[5].Value := Txt_Domin.Text;
Ado_All.Parameters[6].Value := ADOQuery2.FieldByName('Customer_Services_Id').AsString;
Ado_All.Parameters[7].Value := Txt_Domin.Text;
Ado_All.ExecSQL;
Ado_All is an AdoQuery. but it has following error:
Any idea?

I suspect that the colon characters (:) in the SQL statement are causing the problem. Try simply using = ? as the placeholders for the parameter values in the SQL text, e.g.
UPDATE Tbl_Customer_services SET fk_Customer = ?, fk_Services = ?, ...
and be sure to add the parameter values to the .Parameters collection in the exact order that they appear in the SQL statement.

Related

How to get the subitem value from a TRESTReponse in Delphi?

I need to get the subitem1 value of a LResponse that contains following JSON:
"Information": {
"subitem1": "2011",
"subitem2": "Test"
}
I am using this code to get the other values, it's working good, but when I try to get the Information, subitem1 or subitem2, it's returning a empty value.
var
LClient: TRESTClient;
LRequest: TRESTRequest;
LResponse: TRESTResponse;
begin
LClient := TRESTClient.Create(URL_API);
try
LRequest := TRESTRequest.Create(LClient);
try
LResponse := TRESTResponse.Create(LClient);
try
LRequest.Client := LClient;
LRequest.Response := LResponse;
LRequest.Method := rmGET;
LRequest.Params.AddHeader('Authorization','Bearer '+FToken);
LRequest.Params.ParameterByName('Authorization').Options := [poDoNotEncode];
LRequest.Params.AddHeader('Accept', 'application/json');
LRequest.Execute;
LResponse.GetSimpleValue('subitem1', FLogradouro);
{ ... }
GetSimpleValue is only able to read top level properties of JSON in response. It is also extremely inefficient, because it parses JSON upon every call to the method.
TRESTResponse already gives you access to parsed JSON via its JSONValue property. It allows you to query values within the whole structure using JSON path. Accessing JSONValue property will parse the response only once, but beware that it can return nil, if the response is empty or not a valid JSON.
Another point is that you don't have to create TRestResponse yourself. It is automatically created in LRequest.Execute. With that said the code to access values in the returned JSON would be:
if not Assigned(LRequest.Response.JSONValue) then
raise Exception.Create('Invalid response.');
ShowMessage(LRequest.Response.JSONValue.GetValue<string>('Information.subitem1'));
You can use square brackets in JSON path as array accessor to access items by index:
LRequest.Response.JSONValue.GetValue<string>('SomeStrings[0]');
You can do:
RESTResponse1.JSONValue.GetValue<string>('Information.subitem1');
or
var
LValue: string;
LJSONObject: TJSONObject;
begin
LJSONObject := RESTResponse1.JSONValue as TJSONObject;
LValue := LJSONObject.GetValue('subitem1').Value;
end;

Delphi sql search with both column

When i try to search both column, there is no filter. i want to list 5 and 30.05.2016 in dbgrid.
adoquery1.Close;
adoquery1.SQL.CLEAR;
adoquery1.SQL.Add('select * FROM Sheet11 ');
adoquery1.SQL.Add('where field9 like :blm and field12 like :blm1');
adoquery1.Parameters.ParamByName('blm').Value:='5';
adoquery1.Parameters.ParamByName('blm1').Value:='30.05.2016';
adoquery1.Open;
So what is exactly the question there ?
Using parameters is right, one better not use string splicing due to all kinds of fragility and unexpected side effects - http://bobby-tables.com
And use proper data types!
adoquery1.SQL.Text := 'select * FROM Sheet11 ' +
'where ( field9 = :_p_field9 ) ' +
' and ( field12 = :_p_field12 )';
with adoquery1.Parameters do begin
ParamByName('_p_field9').AsInteger := 5;
ParamByName('_p_field12').AsDateTime := EncodeDate( 2016, 05, 30 );
end;
adoquery1.Open;
You've got a pretty bad SQL error. LIKE does not work for any types other than strings (CHAR, VARCHAR, etc.). It does not work for numbers or dates. You're looking for = instead, for exact matches, or BETWEEN if you want something between two values.
This should work for you:
adoquery1.Close;
adoquery1.SQL.CLEAR;
adoquery1.SQL.Add('select * FROM Sheet11 ');
adoquery1.SQL.Add('where field9 = :blm and field12 = :blm1');
adoquery1.Parameters.ParamByName('blm').Value:= 5; // Notice no quotes
adoquery1.Parameters.ParamByName('blm1').Value:= '2016-05-30'; // Note no extra quotes
adoquery1.Open;

ZF2 retrieve out parameter from SP call

I have created a stored procedure with following declaration:
DELIMITER $$
DROP PROCEDURE IF EXISTS my_test$$
CREATE PROCEDURE my_test(input_number INT, OUT out_number text)
BEGIN
IF (input_number = 0) THEN
SET out_number='Errorrrr';
ELSE
SET out_number='Testing';
END IF;
END$$
DELIMITER ;
Following is my ZF2 code to call this SP:
$spResponse = 0;
$prepareStmt = $this->dbGateway->createStatement ();
$prepareStmt->prepare ( 'CALL my_test(?,?)' );
$prepareStmt->getResource ()->bindParam ( 1, $spRequest );
$prepareStmt->getResource ()->bindParam ( 2, $spResponse, \PDO::PARAM_STR, 2 );
$resultSet = $prepareStmt->execute ();
This code gives me following error:
Syntax error or access violation: 1414 OUT or INOUT argument 2 for routine zf2.my_test is not a variable or NEW pseudo-variable in BEFORE trigger
Can somebody advice where the issue is? Also, How can i retrieve value of "OUT" parameter.
Appreciate your response and help.
This low level code retrieves the base PDO connection object. This way you can work the results in PHP fashion

How to return ref_cursor from for loop from pl/sql procedure

i want to get back ref cursor for the below sp. But it's not working.. not getting any records.. So please help me for this.
DATA_INPUTLIST - it's collection type for two variables (mtn, mtnEffDate)
DATA_RESULTLIST - It's also a collection type for 3 variables (id, effDate, mtn)
CREATE OR REPLACE PROCEDURE proc1 (
pCustId IN NUMBER,
pAcctNo IN NUMBER,
pSearchCriteria IN DATA_INPUTLIST,
pRecordSet OUT SYS_REFCURSOR,
out_error_code OUT NUMBER,
out_error_message OUT VARCHAR2
) AS
--Variables
v_SUN_DATE DATE := TO_DATE('01/15/2011', 'mm/dd/yyyy');
vCount NUMBER := 0;
v_mtn NUM
BER;
v_mtn_eff_date DATE;
cMtnPricePlanInfo DATA_RESULTLIST;
BEGIN
SELECT COUNT(*) INTO vCount FROM TABLE (pSearchCriteria);
FOR i IN 1..vCount LOOP
SELECT MTN, TO_DATE(MTN_EFF_DATE, 'mm/dd/yyyy') into v_mtn, v_mtn_eff_date
FROM TABLE (pSearchCriteria)
WHERE
ROWNUM = i;
SELECT
A.PPLAN_ID, A.EFF_DATE, A.MTN INTO cMtnPricePlanInfo(i).PPLAN_ID, cMtnPricePlanInfo(i).EFF_DATE, cMtnPricePlanInfo(i).MTN
FROM CUST_ACCT_LINE_PPLAN A, CUST_ACCT_LINE_PPLAN_HIST B
WHERE
A.CUST_ID = pCustId
AND A.ACCT_NO = pAcctNo
AND A.MTN = v_mtn
AND A.MTN_EFF_DATE = v_mtn_eff_date
AND A.EFF_DATE >=
(SELECT MAX(EFF_DATE) FROM CUST_ACCT_LINE_PPLAN_HIST C
WHERE
C.CUST_ID = pCustId
AND C.ACCT_NO = pAcctNo
AND C.MTN = v_mtn
AND C.MTN_EFF_DATE = v_mtn_eff_date
AND C.EFF_DATE <= v_SUN_DATE)
AND A.CUST_ID = B.CUST_ID
AND A.ACCT_NO = B.ACCT_NO
AND A.MTN = B.MTN
AND A.MTN_EFF_DATE = B.MTN_EFF_DATE
AND A.PPLAN_ID = B.PPLAN_ID;
END LOOP;
OPEN pRecordSet FOR
SELECT * FROM TABLE (cMtnPricePlanInfo);
END;
/
The first things that stands out to me is the following:
SELECT MTN, TO_DATE(MTN_EFF_DATE, 'mm/dd/yyyy') into v_mtn, v_mtn_eff_date
FROM TABLE (pSearchCriteria)
WHERE
ROWNUM = i;
For i greater than 1 this will not return anything. For the reason why, see this question. In fact, because you're using SELECT ... INTO ..., you'll get a no data found error if i is greater than or equal to 2.
You don't need an SQL query just to fetch some values out of PL/SQL collections. Try replacing this query with
v_mtn := pSearchCriteria(i).MTN;
v_mtn_eff_date := TO_DATE(pSearchCriteria(i).MTN_EFF_DATE, 'mm/dd/yyyy');
I don't have your tables nor the data in them so I can't be sure why you're getting no data. I can only hazard at some obvious suggestions: is vCount zero? If you put suitable values for v_mtn and v_mtn_eff_date and run your query on its own, separate from this stored procedure, does it return any rows?

Sybase IN and OUT parameters

I'm going nuts about how the Sybase JDBC driver handles stored procedures with mixed IN and OUT parameters. Check out this simple stored procedure:
CREATE OR REPLACE PROCEDURE p (IN i1 INT, OUT o1 INT, IN i2 INT, OUT o2 INT)
BEGIN
set o1 = i1;
set o2 = i2;
END
And here's how I'd call it with JDBC:
CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(2));
System.out.println(c.getObject(4));
But this results in
1
null
What's going on?? Is that a really wicked bug in the JDBC driver or am I completely missing something? By trial and error, I found this to be a way how it works:
c.setInt(1, 1);
c.setInt(2, 2);
c.registerOutParameter(3, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));
Now the result is
1
2
Does the JDBC driver secretly re-order IN and OUT parameters??
I'm using SQL Anywhere 12 and jconn3.jar
Looks like a bug in the driver.
I suspect the buggy driver expects parameters to be passed/registered in the order (i.e. 1,2,3,4). When you do registerOut(2), the statement apparently forgets you did set(3) :-)
Or, may be, all OUT should be done after all IN. Then again, this is a bug in the driver.
UPDATE
Wait, you didn't change the procedure for the second variant? That result doesn't make any sense. Unless, as you said, driver does reordering. Which is unusual, to say the least.
UPDATE 2
I have decompiled the driver. It does some pretty funny games around out parameters, and with all this joggling I feel they have a fair potential for a bug there, but so far I do not see it plainly.
The only funny thing I noticed is that apparently if the parameter at position n is not out, the driver will scan parameters forward until it will find the value; if value is not found, it goes to the next row:
s.registerOutParameter(5,Types.INT);
...
// no out value at position 4, it will go to 5 and get the value
rs.getInteger(4);
UPDATE 3
It may be interesting to see the output of all 4 parameters in example 1, i.e.:
CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(1));
System.out.println(c.getObject(2));
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));
I tried this with Oracle 9.2 and it works as expected.. I think this problem is related to your JDBC driver, not to JDBC itself.
public static void main(String[] args) throws Exception {
Connection connection = getConnection();
CallableStatement c = connection.prepareCall("{ call p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(2));
System.out.println(c.getObject(4));
}
Output:
Connected to database
1
2
Below sybase stored procedure works for me
public String IDGEN(String tableName, Connection con , LOG _log)
{
String strReturnValue = "-1";
try
{
CallableStatement cs = con.prepareCall("{call usp_NEWPK_string_v6(?,?)}");
cs.registerOutParameter(2,java.sql.Types.NUMERIC);
cs.setString(1,tableName);
cs.setInt(2,0);
cs.execute();
strReturnValue = cs.getLong(2) + "";
} catch (Exception ex) {
_log.logInstance(" ERROR: [IDGEN] " + ex.getMessage());
}
return strReturnValue;
}
// abobjects.com
create proc usp_NEWPK_string_v6 (#tablename varchar(32) , #ID numeric output
)
as
declare #newValue numeric
declare #oldValue numeric
select #oldValue=IDGEN_ID from DB_IDGEN where IDGEN_TableName = #tablename
select #newValue=#oldValue + 1 from DB
_IDGEN where IDGEN_TableName = #tablename
update DB_IDGEN set IDGEN_ID = #newValue where IDGEN_TableName = #tablename
select #ID = #oldValue
return

Resources