load data from database on date selection - delphi-xe2

I am trying to load database data by using dbplannercalender1.
procedure TForm1.DBPlannerCalendar1DaySelect(Sender: TObject;
SelDate: TDateTime);
begin
with absQuery2 do
begin
absQuery2.Close;
absQuery2.sql.Clear;
ABSQuery2.SQL.Text:='select * from log where date = :a1';
ABSQUERY2.PARAMS.ParamByName('a1').value:= DBPlannerCalendar1.Date;
ABSQuery2.ExecSQL;
end;
end;
I get the error "date string expected"YYYY-MM-DD",but "="found at line 1..."
What am I doing wrong ?

Use trunced value
adoQuery.Parameters.paramByName('DataDal').value := trunc(edDate.Date);

Use AsDateTime instead of Value, to let the driver convert it to the proper format:
AbsQuery2.Params.ParamByName('a1').AsDateTime := DBPlannerCalendar1.Date;
If Absolute doens't support AsDateTime for some reason, format the date yourself:
AbsQuery2.Params.ParamByName('a1').Value :=
FormatDateTime('yyyy-mm-dd`, DBPlannerCalendar1.Date);
The first method is the best choice, because it works more portably between database engines (it works for all of them, because the driverr does the formatting into the proper arrangement for dates). Using the second means that if the DB expects something different than YYYY-MM-DD, you have to change the code everywhere that uses dates.

Related

ORA-01722: invalid number When I try to execute an store procedure. Oracle error

I know ORA-01722 occurs when I try to convert an invalid character to number. For example: "a123". In this case I only try to make a where condition, where the parameter is the ID of the table and the parameter is defined based on table type.
PROCEDURE SP_CPR_AGRUPAR_COMPRA(ID_SOLICITUD IN cpr_solicitud.id%type, ID_GRUPO IN cpr_solicitud.ID_GRUPO%type ) AS
BEGIN
UPDATE cpr_solicitud
SET ID_GRUPO=ID_GRUPO
WHERE id=ID_SOLICITUD;
END SP_CPR_AGRUPAR_COMPRA;
I try to format the ID_SOLICITUD with TO_NUMBER function but the error continue. Something like this:
UPDATE cpr_solicitud
SET ID_GRUPO=ID_GRUPO
WHERE id=TO_NUMBER(ID_SOLICITUD);
I did a test passing directly the information and it works.
UPDATE cpr_solicitud SET ID_GRUPO = 18 WHERE id = 942000;
I did many test and the conclusion is that the error is related to the ID_SOLICITUD parameter. I don't why but if I pass the ID_GRUPO and I leave the ID_SOLICITUD it works.
It's works:
UPDATE cpr_solicitud
SET ID_GRUPO=ID_GRUPO
WHERE id=1
It's not works:
UPDATE cpr_solicitud
SET ID_GRUPO=1
WHERE id=TO_NUMBER(ID_SOLICITUD);
As stated in the documentation:
If a SQL statement references a name that belongs to both a column and either a local variable or formal parameter, then the column name takes precedence.
Caution: When a variable or parameter name is interpreted as a column name, data can be deleted, changed, or inserted unintentionally.
In your code,
SET ID_GRUPO=ID_GRUPO
clearly falls into that warning, as #Bob hinted. Every row that matched the filter would be updated with it's current value (i.e. nothing changes), not the value passed into the procedure. As you've confirmed in a comment that the table has a column called ID_SOLICITUD too, so does:
WHERE id=ID_SOLICITUD;
You are getting the error because it is implicitly converting the column value from ID_SOLICITUD - which is presumably not numeric - to a number so it can be compared with id. The ID_SOLICITUD parameter value is not being used, so its data type isn't relevant. You are effectively doing:
UPDATE cpr_solicitud
SET cpr_solicitud.ID_GRUPO=cpr_solicitud.ID_GRUPO
WHERE cpr_solicitud.id=cpr_solicitud.ID_SOLICITUD;
which clearly isn't what you intended. If you run that statement on its on you'll get the same error.
You can either prefix the variable names with the object they actually belong to:
PROCEDURE SP_CPR_AGRUPAR_COMPRA(ID_SOLICITUD IN cpr_solicitud.id%type, ID_GRUPO IN cpr_solicitud.ID_GRUPO%type ) AS
BEGIN
UPDATE cpr_solicitud
SET ID_GRUPO=SP_CPR_AGRUPAR_COMPRA.ID_GRUPO
WHERE id=SP_CPR_AGRUPAR_COMPRA.ID_SOLICITUD;
END SP_CPR_AGRUPAR_COMPRA;
or (more simply and safely, perhaps) change the names, e.g. with a simple prefix:
PROCEDURE SP_CPR_AGRUPAR_COMPRA(p_ID_SOLICITUD IN cpr_solicitud.id%type, p_ID_GRUPO IN cpr_solicitud.ID_GRUPO%type ) AS
BEGIN
UPDATE cpr_solicitud
SET ID_GRUPO=p_ID_GRUPO
WHERE id=p_ID_SOLICITUD;
END SP_CPR_AGRUPAR_COMPRA;

Validate Date FORMAT (not date string) using MomentJS?

I've seen that you can use an ".isValid()" function to check that a given string is in a date format:
moment('2007-05-05', 'YYYY-MM-DD', true).isValid()
But is there a way to confirm that the format is correct? For example:
'YYYY-MM-DD' should return true, but
'YYYY-MM-DDsadsadl' should return false since the characters at the end of the string aren't valid DateTime chars.
We're working on a tool that allows a user to input an existing date format, and then a second input to enter the desired format, but we need validation to ensure the string can properly parse and convert, but they aren't entering a specific date.
The application must accept any and all possible date formats.
Use the following function to validate your format.
validFormat = function(inputFormat){
var validation = moment(moment('2017-06-17').format(inputFormat), inputFormat).inspect();
if(validation.indexOf('invalid') < 0)
return true;
else
return false;
}
Do spend some time to understand this. This simply does a reverse verification using inspect(). The date 2017-06-17 can be replaced by any valid date.
This Moment Js Docs will help you identify the valid formats.
Just make a call to this function as
validFormat('YYYY MM DD')
const getIsValid = inputFormat => moment(moment().format(inputFormat), inputFormat).isValid()
Explanation:
moment().format(inputFormat) - Create a date string from the current time from that format
This is then wrapped with moment() to make that string a moment date object, defining the format to parse it with. Finally we call the isValid() property on that moment date object. This ensures we are able to both create and parse a moment with our custom format.

How to WRITE a structure?

How can I do the following:
data: ls_header type BAPIMEPOHEADER.
" fill it
write ls_header.
currently I'm getting an error because write can not parse the complex type to a string. Is there a simple way to get this code running in abap?
You could use something like:
DATA: g_struct TYPE bapimepoheader.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE g_struct TO FIELD-SYMBOL(<f>).
IF sy-subrc NE 0.
EXIT.
ENDIF.
WRITE: / <f>.
ENDDO.
Perhaps not exactly the answer you expect: If you list each field.
This can be done quite easy via the Pattern-mask in SE38:
Select the Write-pattern:
Enter the structure you want:
Select the fields
Confirm with "Copy"
Confirm and you get
WRITE: bapimepoheader-po_number,
bapimepoheader-comp_code,
bapimepoheader-doc_type,
bapimepoheader-delete_ind,
bapimepoheader-status,
bapimepoheader-creat_date,
bapimepoheader-created_by,
bapimepoheader-item_intvl,
bapimepoheader-vendor,
bapimepoheader-langu,
bapimepoheader-langu_iso,
bapimepoheader-pmnttrms,
bapimepoheader-dscnt1_to,
bapimepoheader-dscnt2_to,
bapimepoheader-dscnt3_to,
bapimepoheader-dsct_pct1,
bapimepoheader-dsct_pct2,
bapimepoheader-purch_org,
bapimepoheader-pur_group,
bapimepoheader-currency,
bapimepoheader-currency_iso,
bapimepoheader-exch_rate,
bapimepoheader-ex_rate_fx,
bapimepoheader-doc_date,
bapimepoheader-vper_start,
bapimepoheader-vper_end,
bapimepoheader-warranty,
bapimepoheader-quotation,
bapimepoheader-quot_date,
bapimepoheader-ref_1,
bapimepoheader-sales_pers,
bapimepoheader-telephone,
bapimepoheader-suppl_vend,
bapimepoheader-customer,
bapimepoheader-agreement,
bapimepoheader-gr_message,
bapimepoheader-suppl_plnt,
bapimepoheader-incoterms1,
bapimepoheader-incoterms2,
bapimepoheader-collect_no,
bapimepoheader-diff_inv,
bapimepoheader-our_ref,
bapimepoheader-logsystem,
bapimepoheader-subitemint,
bapimepoheader-po_rel_ind,
bapimepoheader-rel_status,
bapimepoheader-vat_cntry,
bapimepoheader-vat_cntry_iso,
bapimepoheader-reason_cancel,
bapimepoheader-reason_code,
bapimepoheader-retention_type,
bapimepoheader-retention_percentage,
bapimepoheader-downpay_type,
bapimepoheader-downpay_amount,
bapimepoheader-downpay_percent,
bapimepoheader-downpay_duedate,
bapimepoheader-memory,
bapimepoheader-memorytype,
bapimepoheader-shiptype,
bapimepoheader-handoverloc,
bapimepoheader-shipcond,
bapimepoheader-incotermsv,
bapimepoheader-incoterms2l,
bapimepoheader-incoterms3l.
Now you can make a simple replacement of bapimepoheader with ls_header and you have an output of all fields of the structure.
Maybe this is not elegant and you must adapt your report, if the structure changes. But I like this way, because often I don't need all fields and I can select the fields in an easy way.
I know two ways, one is procedural, the other is oop.
Here is the procedural approach.
Select the structure's fields (or whatever else You might need ) from the data-dictionary table DD03L into a local internal table.
Loop over the table into a work-area
Check, whether current field is a flat single datatype, and if so,
Assign component workarea-fieldname of structure ls_header into anyfieldsymbol
Write anyfieldsymbol
Do You need the code ?
Class CL_ABAP_CONTAINER_UTILITIES was specially introduced for that by SAP.
Use FILL_CONTAINER_C method for output the structure in a WRITE manner:
DATA: ls_header type BAPIMEPOHEADER.
CALL METHOD CL_ABAP_CONTAINER_UTILITIES=>FILL_CONTAINER_C
EXPORTING
IM_VALUE = ls_header
IMPORTING
EX_CONTAINER = DATA(container)
EXCEPTIONS
ILLEGAL_PARAMETER_TYPE = 1
others = 2.
WRITE container.
You can write your structure to a string and then output the string. Same method idoc segments are created.

How to pass in argument of type DATE to a function

I've got a function in an oracle database. I need to call it from delphi. I use the following code:
procedure TForm1.Run;
var
q:TADOQuery;
begin
q:=TADOQuery.Create(nil);
q.Connection:=ADOConnection1;
q.ParamCheck:=false;
q.SQL.Add('BEGIN');
q.SQL.Add(' :RES:=Search(:P_DATE);');
q.SQL.Add('END;');
q.Parameters.AddParameter.Name:='P_DATE';
q.Parameters.ParamByName('P_DATE').Direction:=pdInput;
q.Parameters.ParamByName('P_DATE').DataType:=ftDate;
q.Parameters.ParamByName('P_DATE').Value:=Now;
q.Parameters.AddParameter.Name:='RES';
q.Parameters.ParamByName('RES').DataType:=ftFloat;
q.Parameters.ParamByName('RES').Direction:=pdOutput;
q.Parameters.ParamByName('RES').Value:=1;
q.ExecSQL;
//...
I get ora-06550 error, saying invalid number or type of parameters. If I change the P_DATE parameter to sysdate, i.e. :RES:=Search(sysdate);, it works fine.
So how can I pass an "in" parameter of type DATE to an oracle function from delphi?
Found ORA-06550 when Oracle stored function is called.. However this relates to Kylix Pascal IDE. Am I expected to meet the same behaviour for delphi? Didn't try to use oracle procedure instead of a function. Maybe this issue can be solved some how else...
Oracle doesn't have a date type for bind variables - you need to explicitly convert the bind variable to a date:
:res := search(to_date(:p_date, 'dd/mm/yyyy'));
You should then be able to pass your variable as a string matching the date format you've specified.
Try to send this parameter as a string:
.........
q.SQL.Add('BEGIN');
q.SQL.Add(' :RES:=Search(TO_DATE(:P_DATE,''YYYYMMDD''));');
q.SQL.Add('END;');
q.Parameters.AddParameter.Name:='P_DATE';
q.Parameters.ParamByName('P_DATE').Direction:=pdInput;
q.Parameters.ParamByName('P_DATE').DataType:=ftString;
q.Parameters.ParamByName('P_DATE').Value:=FormatDateTime('yyyymmdd',Now);
..........
You're doing it wrong (and I think you had a previous question deleted as being a duplicate that asked this same question (different function, but same idea) just a couple of days ago).
You're calling the function wrong in the first place.
.........
q.SQL.Add('BEGIN');
q.SQL.Add(' SELECT Search(TO_DATE(:P_DATE,''YYYYMMDD'')) FROM System.Dual;');
q.SQL.Add('END;');
q.Parameters.AddParameter.Name:='P_DATE';
q.Parameters.ParamByName('P_DATE').Direction:=pdInput;
q.Parameters.ParamByName('P_DATE').DataType:=ftDate;
q.Parameters.ParamByName('P_DATE').Value:=Now;
q.Open;
if not q.IsEmpty then // or not q.Eof
Res := q.Fields[0].AsFloat;

Getting an Error “ORA-06502: PL/SQL: numeric or value error: character string buffer too small”

This is my query
begin
select ceq_specimens.numero as NUMERO,
analyseEffectuee.DESCRIPTION as analyseEffectuee
into out_rec.NUMERO_SPECIMEN3, out_rec.SPEC3_ANALYSE_EFFECTUE
from CEQ_FORMULAIRES_ANALYSES
inner join ceq_liste_choix analyseEffectuee on analyseEffectuee.ID_LISTE_CHOIX=CEQ_FORMULAIRES_ANALYSES.ID_ANALYSE_EFFECTUE
inner join ceq_specimens on ceq_specimens.ID_SPECIMEN=CEQ_FORMULAIRES_ANALYSES.ID_SPECIMEN and ceq_specimens.ID_SPECIMEN=vintIdSpecimen3
where CEQ_FORMULAIRES_ANALYSES.ID_FORMULAIRE=out_rec.ID_FORMULAIRE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
out_rec.NUMERO_SPECIMEN3 := ' ';
out_rec.SPEC3_ANALYSE_EFFECTUE := ' ';
END;
...
IF analyseEffectuee.DESCRIPTION as analyseEffectuee = Spécimen impossible à analyser: Préciser en commentaire(s)
I get error ''string buffer too small”
IF analyseEffectuee.DESCRIPTION as analyseEffectuee= Non
No problem in this case
Thanks for helping me!
I get Error ''string buffer too small” "
What that means is your variable out_rec.SPEC3_ANALYSE_EFFECTUE is not big enough to hold teh value Spécimen impossible à analyser: Préciser en commentaire(s).
The best way to define PL/SQL variables is to use the %TYPE keyword. This creates a variable which matches the column's definition.
Your code uses something called OUTREC. You haven't given us the definition of this, which makes it harder to correct your specfic problem but perhaps you should be doing something like this. Declare a PL/SQL record type which matches you're desired output, then declare a variable of that type:
type my_rec_t is record (
NUMERO_SPECIMEN1 ceq_specimens.numer%type,
SPEC1_ANALYSE_EFFECTUE analyseEffectuee.DESCRIPTION%type,
NUMERO_SPECIMEN2 ceq_specimens.numer%type,
SPEC2_ANALYSE_EFFECTUE analyseEffectuee.DESCRIPTION%type,
NUMERO_SPECIMEN3 ceq_specimens.numer%type,
SPEC3_ANALYSE_EFFECTUE analyseEffectuee.DESCRIPTION%type
);
out_rec my_rec_t;
ORA-02303: cannot drop or replace a type with type or table dependents
So this means you're using SQL Types, with inheritance. Sorting this out is a bit of a problem. There is some syntax which we can use with the ALTER TYPE command which allows us to handle dependent types. Find out more.

Resources