In production every now and then we get an ORA-0001 error when dequeuing a message. We use:
Solaris 10
Oracle 10g
C++ application
PROC*C with dbms_aq package for queuing operations
Queues with XML payload
We handle a large volume of messages (1K/min).
Any clue why would a dequeue result in an ORA-0001 (unique constraint) error?
Update: adding code per request.
EXEC SQL EXECUTE
DECLARE
message_properties dbms_aq.message_properties_t;
dequeue_options dbms_aq.dequeue_options_t;
message_payload xmltype;
tmpclob clob;
dynamic_sql_string varchar2(512);
BEGIN
dequeue_options.wait := :iReadTimeout;
dequeue_options.dequeue_mode := dbms_aq.REMOVE;
dequeue_options.visibility := dbms_aq.ON_COMMIT;
IF :iBuffered = 1 then
dequeue_options.delivery_mode := dbms_aq.buffered;
dequeue_options.visibility := dbms_aq.immediate;
:iNavigationMode := 0;
END IF;
IF :iDequeueOnly = 1 and :iQueueType <> 1 THEN
dequeue_options.dequeue_mode := dbms_aq.REMOVE_NODATA;
dequeue_options.wait := dbms_aq.NO_WAIT;
dequeue_options.msgid := hextoraw(:pszDequeueMsgId);
ELSE
IF :iNavigationMode = 0 THEN
dequeue_options.navigation := dbms_aq.FIRST_MESSAGE;
ELSE
dequeue_options.navigation := dbms_aq.NEXT_MESSAGE;
END IF;
END IF;
dequeue_options.deq_condition := :pszDeqCondition;
dbms_aq.dequeue(queue_name => :pszQueueName,
message_properties => message_properties,
dequeue_options => dequeue_options,
payload => message_payload,
msgid => :msgid );
IF dequeue_options.dequeue_mode <> dbms_aq.REMOVE_NODATA THEN
EXECUTE IMMEDIATE dynamic_sql_string USING OUT tmpclob, IN message_payload;
:gpoXmlClob := tmpclob;
ELSE
:gpoXmlClob := message_payload.getclobval();
END IF;
END;
Related
I run oracle reports 6i in bellow code
IF :Global.Report_id IN ('XB_RFMODSM_DESA') THEN
Add_Parameter(pl_login1,'P_MONTH',TEXT_PARAMETER,:BLK_REPORT.BILL_CYCLE_CODE);
Add_Parameter(pl_login1,'LOCATION_CODE',TEXT_PARAMETER, vvc_location);
Add_Parameter(pl_login1,'FEEDER_NO1',TEXT_PARAMETER,vch_feeder);
Rep_id := LTRIM(rtrim(:Global.Report_id));
Run_Product(REPORTS, Rep_id, SYNCHRONOUS, RUNTIME, FILESYSTEM, pl_login1, NULL);
END IF;
Now i want to run in oracle 10g.
What change i made for run oracle reports in 10g?
Thanks
The usual way of doing that is to use WEB.SHOW_DOCUMENT.
Here's a (slightly formatted) copy/paste (in case the link gets broken) of an example Sarah posted on OTN forums. See if it helps.
DECLARE
repid REPORT_OBJECT;
v_rep VARCHAR2(100);
rep_status VARCHAR2(20);
plid ParamList;
vParamValue number;
BEGIN
plid := Get_parameter_List('tmp');
IF NOT Id_Null(plid) THEN
Destroy_parameter_List( plid );
END IF;
plid := Create_parameter_List('tmp');
add_parameter(plid, 'p_parameter',text_parameter,to_char(:block.item));
add_parameter(plid, 'PARAMFORM', TEXT_parameter, 'NO');
repid := FIND_REPORT_OBJECT('REPORT6');
SET_REPORT_OBJECT_PROPERTY(repid,REPORT_COMM_MODE,SYNCHRONOUS);
SET_REPORT_OBJECT_PROPERTY(repid,REPORT_DESTYPE,cache);
SET_REPORT_OBJECT_PROPERTY(repid,REPORT_DESFORMAT,'PDF');
SET_REPORT_OBJECT_PROPERTY(repid,REPORT_OTHER, 'paramform=no');
v_rep := RUN_REPORT_OBJECT(repid,plid);
rep_status := REPORT_OBJECT_STATUS(v_rep);
WHILE rep_status in ('RUNNING','OPENING_REPORT','ENQUEUED')
LOOP
rep_status := report_object_status(v_rep);
END LOOP;
/*Display report in the browser*/
WEB.SHOW_DOCUMENT('http://Machine_name:Port/reports/rwservlet/getjobid' ||
substr(v_rep,instr(v_rep,'_',-1)+1) || '?' ||
'server=Report_server_name&P_parameter=' ||:block.item ||
'¶mform=no');
END;
Alternative to what #Littlefoot pointed out you may use Report conversion tool of Fusion Middleware. After processing with that tool Rp2Rro.pll should be attached through the forms' attached libraries part.
After all, you may add a ad-hoc Procedure as :
Procedure Pr_Print_Rp2Rro(
Rep_id in out varchar2,
i_param_name varchar2,
i_param_var varchar2,
i_param_frm varchar2, -- 'Yes','No'
i_repsrv varchar2,
i_desname varchar2,
i_destype varchar2 default 'FILE',
i_desformat varchar2 default 'PDF'
) Is
pl_login1 ParamList;
arr_param_name owa.vc_arr;
arr_param_var owa.vc_arr;
Begin
pl_login1 := Get_Parameter_List('REPPARAM');
if not Id_Null(pl_login1) then
Destroy_Parameter_List('REPPARAM');
end if;
pl_login1 := Create_Parameter_List('REPPARAM');
Add_Parameter(pl_login1, 'PARAMFORM', Text_Parameter, i_param_frm);
Add_Parameter(pl_login1, 'RP2RROREPORTSERVER', Text_Parameter, i_repsrv );
Add_Parameter(pl_login1, 'RP2RRODESTYPE', Text_Parameter, i_destype );
Add_Parameter(pl_login1, 'RP2RRODESNAME', Text_Parameter, i_desname );
Add_Parameter(pl_login1, 'RP2RRODESFORMAT', Text_Parameter, i_desformat );
for i in 1..100
loop
arr_param_name(i) := substr(i_param_name,instr(i_param_name,'|',1,i)+1,
instr(i_param_name,'|',1,1+i)-instr(i_param_name,'|',1,i)-1);
arr_param_var(i) := substr(i_param_var,instr(i_param_var,'|',1,i)+1,
instr(i_param_var,'|',1,1+i)-instr(i_param_var,'|',1,i)-1);
if length(arr_param_name(i)) > 0 then
Add_Parameter( pl_login1, arr_param_name(i) , Text_Parameter, arr_param_var(i) );
end if;
end loop;
Rep_id := ltrim(rtrim(:Global.Report_id));
Rp2rro.Rp2rro_Run_Product(Reports, Rep_id, Synchronous, Runtime,Filesystem, pl_login1,null);
End;
this could be called ( from a button as an example ) like :
declare
vvc_location tabFeederDesign.vvc_location%type;
vch_feeder tabFeederDesign.vch_feeder%type;
v_Rep_id varchar2(500):='Rep123';
v_server varchar2(500):='mySrv';
v_file varchar2(500):='file456';
begin
Pr_Print_Rp2Rro(v_Rep_id,'|P_MONTH|LOCATION_CODE|FEEDER_NO1|','|'||:BLK_REPORT.BILL_CYCLE_CODE||'|'||vvc_location||'|'||vch_feeder||'|','No',v_server,v_file);
end;
Good afternoon everybody.
I have the following problem, I am loading a query to the cursor "c_Pol_Vig_Ant" and after certain validations I save the results in a list
TYPE r_Pol_Vig_Ant IS RECORD(
NUMPOL USRAXVM00.Vm_Poliza.NUMPOL%TYPE,
IDEOBSER USRAXVM00.Vm_Obser_Poliza.IDEOBSER%TYPE,
NUMAVISO USRAXVM00.Vm_Obser_Poliza.NUMAVISO%TYPE,
FECINIVIG USRAXVM00.Vm_Poliza.FECINIVIG%TYPE,
FECFINVIG USRAXVM00.Vm_Poliza.FECFINVIG%TYPE,
FECVCT USRAXVM00.VM_GIROS_FINANCIAMIENTO.FECVCT%TYPE,
ORDEN USRAXVM00.VM_GIROS_FINANCIAMIENTO.NUMGIRO%TYPE,
IDGIRO USRAXVM00.VM_GIROS_FINANCIAMIENTO.IDGIRO%TYPE,
CODMONEDA USRAXVM00.VM_ACREENCIA.CODMONEDA%TYPE,
MTOACREMONEDA USRAXVM00.VM_ACREENCIA.MTOACREMONEDA%TYPE,
STSGIRO USRAXVM00.VM_GIROS_FINANCIAMIENTO.STSGIRO%TYPE,
CODPROD USRAXVM00.Vm_Poliza.CODPROD%TYPE,
PENDIENTE USRAXVM00.VM_ACREENCIA.MTOACREMONEDA%TYPE,
TOTAL USRAXVM00.VM_ACREENCIA.MTOACREMONEDA%TYPE,
COBRADO USRAXVM00.VM_ACREENCIA.MTOACREMONEDA%TYPE,
FECHAEMISAVISO USRAXVM00.Vm_Obser_Poliza.FECHA%TYPE,
CODCANAL USRAXVM00.Vm_Poliza.CODCANAL%TYPE,
CANAL USRAXVM00.Vm_Tercero.NOMTER%TYPE,
CODINTER USRAXVM00.Vm_Part_Inter_Pol.CODINTER%TYPE,
AGENTE USRAXVM00.Vm_Tercero.NOMTER%TYPE,
CODPLAN USRAXVM00.Vm_Cond_Financiamiento.CODPLAN%TYPE,
NOMPLAN USRAXVM00.VM_PLAN_FINANCIAMIENTO.NOMPLAN%TYPE,
ORIGEN VARCHAR2(4),
VIGENCIA VARCHAR2(20)
);
TYPE tab_Pol_Vig_Ant IS TABLE OF r_Pol_Vig_Ant;
TYPE tab_Lista IS TABLE OF r_Pol_Vig_Ant INDEX BY BINARY_INTEGER;
FOR x IN c_Pol_Vig_Ant LOOP
IF x.STSGIRO = 'CAS' OR x.STSGIRO = 'AND' THEN
v_Valor := USRAXVM00.PO_POL_REN_VIG_ANT.Depurar_And_Cas(x.NUMAVISO, x.IDGIRO, x.ORDEN);
IF v_Valor <> 1 THEN
v_Cont := v_Cont + 1;
p_Datos(v_Cont).NUMPOL := x.NUMPOL;
p_Datos(v_Cont).IDEOBSER := x.IDEOBSER;
p_Datos(v_Cont).NUMAVISO := x.NUMAVISO;
p_Datos(v_Cont).FECINIVIG := x.FECINIVIG;
p_Datos(v_Cont).FECFINVIG := x.FECFINVIG;
p_Datos(v_Cont).FECVCT := x.FECVCT;
p_Datos(v_Cont).ORDEN := x.ORDEN;
p_Datos(v_Cont).IDGIRO := x.IDGIRO;
p_Datos(v_Cont).CODMONEDA := x.CODMONEDA;
p_Datos(v_Cont).MTOACREMONEDA := x.MTOACREMONEDA;
p_Datos(v_Cont).STSGIRO := x.STSGIRO;
p_Datos(v_Cont).CODPROD := x.CODPROD;
p_Datos(v_Cont).PENDIENTE := x.PENDIENTE;
p_Datos(v_Cont).TOTAL := x.TOTAL;
p_Datos(v_Cont).COBRADO := x.COBRADO;
p_Datos(v_Cont).FECHAEMISAVISO := x.FECHAEMISAVISO;
p_Datos(v_Cont).CODCANAL := x.CODCANAL;
p_Datos(v_Cont).CANAL := x.CANAL;
p_Datos(v_Cont).CODINTER := x.CODINTER;
p_Datos(v_Cont).AGENTE := x.AGENTE;
p_Datos(v_Cont).CODPLAN := x.CODPLAN;
p_Datos(v_Cont).NOMPLAN := x.NOMPLAN;
p_Datos(v_Cont).ORIGEN := x.ORIGEN;
p_Datos(v_Cont).VIGENCIA := x.VIGENCIA;
END IF;
END IF;
END LOOP;
The error is the following, when making the query to a PIPELINE function sending as parameter my list I get the error expressions is of wrong type.
FOR x IN p_Datos.First..p_Datos.Last LOOP
SELECT COUNT(DISTINCT t.VIGENCIA)
INTO v_NroVigencias
FROM table(USRAXVM00.PO_POL_REN_VIG_ANT.F_Obtener_Datos(p_Listar => p_Datos)) t
WHERE t.NUMPOL = p_Datos(x).NUMPOL;
IF v_NroVigencias = 1 THEN
p_Datos.DELETE(x);
END IF;
END LOOP;
This is my function:
FUNCTION F_Obtener_Datos(p_Listar IN tab_Lista) RETURN tab_Pol_Vig_Ant PIPELINED IS
p_ListaDatos r_Pol_Vig_Ant;
BEGIN
IF p_Listar.Count > 0 THEN
FOR x IN p_Listar.First..p_Listar.Last LOOP
p_ListaDatos.NUMPOL := p_Listar(x).NUMPOL;
p_ListaDatos.NUMAVISO := p_Listar(x).NUMAVISO;
p_ListaDatos.FECINIVIG := p_Listar(x).FECINIVIG;
p_ListaDatos.FECFINVIG := p_Listar(x).FECFINVIG;
p_ListaDatos.FECVCT := p_Listar(x).FECVCT;
p_ListaDatos.ORDEN := p_Listar(x).ORDEN;
p_ListaDatos.IDGIRO := p_Listar(x).IDGIRO;
p_ListaDatos.CODMONEDA := p_Listar(x).CODMONEDA;
p_ListaDatos.MTOACREMONEDA := p_Listar(x).MTOACREMONEDA;
p_ListaDatos.STSGIRO := p_Listar(x).STSGIRO;
p_ListaDatos.CODPROD := p_Listar(x).CODPROD;
p_ListaDatos.PENDIENTE := p_Listar(x).PENDIENTE;
p_ListaDatos.TOTAL := p_Listar(x).TOTAL;
p_ListaDatos.COBRADO := p_Listar(x).COBRADO;
p_ListaDatos.FECHAEMISAVISO := p_Listar(x).FECHAEMISAVISO;
p_ListaDatos.CANAL := p_Listar(x).CANAL;
p_ListaDatos.CODINTER := p_Listar(x).CODINTER;
p_ListaDatos.AGENTE := p_Listar(x).AGENTE;
p_ListaDatos.CODPLAN := p_Listar(x).CODPLAN;
p_ListaDatos.NOMPLAN := p_Listar(x).NOMPLAN;
p_ListaDatos.ORIGEN := p_Listar(x).ORIGEN;
p_ListaDatos.VIGENCIA := p_Listar(x).VIGENCIA;
PIPE ROW(p_ListaDatos);
END LOOP;
END IF;
RETURN;
END F_Obtener_Datos;
Error: PLS-00382: expression is of wrong type
Line: 203
Text: FROM table(USRAXVM00.PO_POL_REN_VIG_ANT.F_Obtener_Datos(p_Listar => p_Datos)) t
Error: PLS-00306: wrong number or types of arguments in call to 'F_OBTENER_DATOS'
Line: 203
Text: FROM table(USRAXVM00.PO_POL_REN_VIG_ANT.F_Obtener_Datos(p_Listar => p_Datos)) t
Error: PL/SQL: ORA-00904: "USRAXVM00"."PO_POL_REN_VIG_ANT"."F_OBTENER_DATOS": invalid identifier
Line: 203
Text: FROM table(USRAXVM00.PO_POL_REN_VIG_ANT.F_Obtener_Datos(p_Listar => p_Datos)) t
Error: PL/SQL: SQL Statement ignored
Line: 201
Text: SELECT COUNT(DISTINCT t.VIGENCIA)
Thank you very much with everyone, I hope you can help me.
I am writing an application which required PL/SQL send the message to WebSocket. Currently, I am using UTL_TCP in order to connect with WebSocket.
My WebSocket server has different type of client, JavaScript, PHP, JAVA, Oracle PL/SQL. I am able to connect and send the message to all others except Oracle PL/SQL.
Any suggestion is appreciated,
Here is my PL/Sql code.
DECLARE
CONN UTL_TCP.CONNECTION;
RETVAL BINARY_INTEGER;
L_RESPONSE VARCHAR2(1000) := '';
L_TEXT VARCHAR2(1000);
content varchar2(4000) := '{"clientSession": "rmmd5kfcbv7i3h0jeel57a4o62","message": "Hi from oracle", "msgClient": "php"}';
BEGIN
CONN := UTL_TCP.OPEN_CONNECTION(
REMOTE_HOST => '127.0.0.1',
REMOTE_PORT => 5050,
TX_TIMEOUT => 10,
charset => 'UTF-8'
);
RETVAL := UTL_TCP.WRITE_LINE(CONN,'GET / HTTP/1.1');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Upgrade: websocket');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Connection: Upgrade');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Host: localhost');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Origin: localhost');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Sec-WebSocket-Key: TyPfhFqWTjuw8eDAxdY8xg==');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Sec-WebSocket-Version: 13');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Content-Type: application/json');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Content-Length: ' || length(content));
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Content: ' || content);
RETVAL := UTL_TCP.WRITE_LINE(CONN, '{"clientSession": "plloua8kg6nuqg53l2sv7m6do2","message": "Hi from oracle", "msgClient": "ora"}');
RETVAL := UTL_TCP.WRITE_LINE(CONN);
UTL_TCP.FLUSH(CONN);
DBMS_OUTPUT.PUT_LINE('Response from Socket Server : ' || L_RESPONSE);
UTL_TCP.CLOSE_CONNECTION(CONN);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20101,SQLERRM);
UTL_TCP.CLOSE_CONNECTION(CONN);
END;
check for data transfering WebSocket protocol
for exapmple:
HEXTORAW('810568656C6C6F'):
81 - byte for data begining
05 - length of text "hello"
68656C6C6F - "hello"
and of course don't raise exception before close connection.
DECLARE
CONN UTL_TCP.CONNECTION;
RETVAL BINARY_INTEGER;
begin
CONN := UTL_TCP.OPEN_CONNECTION(
REMOTE_HOST => '127.0.0.1',
REMOTE_PORT => 5050,
TX_TIMEOUT => 10,
charset => 'UTF-8'
);
RETVAL := UTL_TCP.WRITE_LINE(CONN,'GET / HTTP/1.1');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Upgrade: websocket');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Connection: Upgrade');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Host: 127.0.0.1:5050');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Origin: null');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Sec-WebSocket-Key: TyPfhFqWTjuw8eDAxdY8xg==');
RETVAL := UTL_TCP.WRITE_LINE(CONN,'Sec-WebSocket-Version: 13');
RETVAL := UTL_TCP.WRITE_LINE(CONN);
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE(UTL_TCP.GET_Line(conn, false)); -- read handshake result
END LOOP;
EXCEPTION
WHEN others THEN NULL;
END;
RETVAL := UTL_TCP.WRITE_RAW(conn,HEXTORAW('810568656C6C6F'));
UTL_TCP.FLUSH(CONN);
UTL_TCP.CLOSE_CONNECTION(CONN);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line( sqlerrm );
UTL_TCP.CLOSE_CONNECTION(CONN);
end;
I am using the following code block to update my front end segment.
But when i am compiling this
DECLARE
p_person_id NUMBER := NULL;
p_business_group_id NUMBER;
p_id_flex_num NUMBER;
------------------
p_analysis_criteria_id NUMBER := NULL;
p_person_analysis_id NUMBER := NULL;
p_per_object_version_number NUMBER := NULL;
v_err VARCHAR2 (1000) := NULL;
p_medical_id VARCHAR2 (100) := NULL;
BEGIN
FOR i IN (SELECT *
FROM xx_hr_upload_master_data_new
WHERE person_id IS NOT NULL
AND business_group_id IS NOT NULL
AND medical_id IS NOT NULL)
LOOP
p_id_flex_num := 50530;
BEGIN
SELECT sv.segment1, NVL (sit.object_version_number, 1),
sit.analysis_criteria_id, MAX (sit.person_analysis_id)
INTO p_medical_id, p_per_object_version_number,
p_analysis_criteria_id, p_person_analysis_id
FROM fnd_id_flex_structures_tl sttl,
fnd_id_flex_structures st,
per_person_analyses sit,
per_analysis_criteria sv
WHERE sttl.id_flex_structure_name = 'ISPs Medical Data'
AND sttl.LANGUAGE = USERENV ('LANG')
AND st.id_flex_code = sttl.id_flex_code
AND st.id_flex_num = sttl.id_flex_num
AND st.id_flex_num = sit.id_flex_num
AND st.id_flex_num = sv.id_flex_num
AND sit.analysis_criteria_id = sv.analysis_criteria_id
AND sit.person_id = i.person_id
--and sv.SEGMENT1 = '4602001140'
GROUP BY sv.segment1,
NVL (sit.object_version_number, 1),
sit.analysis_criteria_id;
EXCEPTION
WHEN OTHERS
THEN
p_medical_id := NULL;
p_per_object_version_number := 1;
p_person_analysis_id := NULL;
p_analysis_criteria_id := NULL;
p_person_analysis_id := NULL;
p_per_object_version_number := NULL;
p_person_id := NULL;
END;
BEGIN
------------------------------------------------
IF (p_medical_id IS NULL AND p_analysis_criteria_id IS NULL)
THEN
-- create a new record in the SIT (Special Information Type)table .
p_person_id := i.person_id;
p_medical_id := TO_CHAR (i.medical_id);
-----------------------------
hr_sit_api.create_sit
(p_validate => FALSE,
p_person_id => p_person_id,
p_business_group_id => i.business_group_id,
p_id_flex_num => p_id_flex_num,
p_effective_date => TRUNC (SYSDATE),
p_date_from => TRUNC (SYSDATE),
p_segment1 => p_medical_id,
p_analysis_criteria_id => p_analysis_criteria_id,
p_person_analysis_id => p_person_analysis_id,
p_pea_object_version_number => p_per_object_version_number
);
ELSE
-- employee has previous Billing_Acc_Num then update that number in the SIT table .
hr_sit_api.update_sit
(p_validate => FALSE,
p_person_analysis_id => p_person_analysis_id,
p_pea_object_version_number => p_per_object_version_number,
p_date_from => TRUNC (SYSDATE),
p_segment1 => p_medical_id,
p_analysis_criteria_id => p_analysis_criteria_id
);
END IF;
UPDATE xx_hr_upload_master_data_new xx
SET xx.error_msg = 'Done',
xx.emp_data = 'Done'
WHERE xx.business_group_id = i.business_group_id
AND xx.employee_number = i.employee_number;
EXCEPTION
WHEN OTHERS
THEN
p_analysis_criteria_id := NULL;
p_person_analysis_id := NULL;
p_per_object_version_number := NULL;
p_person_id := NULL;
p_medical_id := NULL;
v_err := NULL;
v_err := SQLERRM;
UPDATE xx_hr_upload_master_data_new xx
SET xx.error_msg = v_err
WHERE xx.business_group_id = i.business_group_id
AND xx.employee_number = i.employee_number;
END;
END LOOP;
COMMIT;
END;
Now when the select query is not fetching anything, the exception block is entered where all the variables are initiated to null.
I want that after this the begin where the create api is called inside the condition IF (p_medical_id IS NULL AND p_analysis_criteria_id IS NULL)
should be entered. But this is not happening and the program exits after this exception block after entering the exception block.
A hint might be:
The first select will not raise any exception if it gets no result. If it gets no result then the for-loop just won't be entered, so the only thing that will happen is the commit.
(The select inside the for-loop will raise an exception if it gets 0 rows or more than 1 row. The reason is 'select ... into ...': When using 'into' the select must return exact 1 row.)
I'm using Delphi 5 + BDE + Oracle. I have the following function:
class function TClientDataSetFactory.GetClientDataSet(
const qryGen: TDataSet): TClientDataSet;
var
dspDados: TDataSetProvider;
begin
Result := nil;
try
try
Result := TClientDataSet.Create(nil);
dspDados := TDataSetProvider.Create(Result);
dspDados.DataSet := qryGen;
qryGen.Active := True;
qryGen.First;
Result.Data := dspDados.Data;
Result.First;
except
on E: Exception do
begin
raise;
end;
end;
finally
end;
end;
so, when a run this:
var
qryGen: TQuery;
cdsGen: TClientDataSet;
begin
qryGen := nil;
try
try
qryGen := CriaQuery();
qryGen.SQL.Text :=
'SELECT SUM(TOTAL) AS TOTAL FROM MYTABLE';
cdsGen := TClientDataSetFactory.GetClientDataSet(qryGen);
ShowMessageFmt('Total: %f', [cdsGen.FieldByName('TOTAL').AsFloat]);
except
on E: Exception do
begin
raise;
end;
end;
finally
if Assigned(qryGen) then FreeAndNil(qryGen);
end;
end;
i got "159,00" but, if i run this:
ShowMessageFmt('Total: %f', [qryGen.FieldByName('TOTAL').AsFloat]);
i got "159,25".
can someone help me?
I solved the problem with another solution.
type
TInternalQuery = class(TQuery)
protected
procedure InternalInitFieldDefs; override;
public
constructor Create(AOwner: TComponent; const qryGen: TQuery); reintroduce;
end;
constructor TInternalQuery.Create(AOwner: TComponent; const qryGen: TQuery);
var
intCont: Integer;
begin
inherited Create(AOwner);
Self.DatabaseName := qryGen.DatabaseName;
Self.UpdateObject := qryGen.UpdateObject;
Self.SQL.Text := qryGen.SQL.Text;
for intCont := 0 to Self.ParamCount - 1 do
begin
Self.Params[intCont].Value := qryGen.Params[intCont].Value;
end;
end;
procedure TInternalQuery.InternalInitFieldDefs;
var
intCont: Integer;
begin
inherited InternalInitFieldDefs;
for intCont := 0 to FieldDefs.Count - 1 do
begin
if (FieldDefs[intCont].Size = 0) and (FieldDefs[intCont].DataType = ftBCD) then
begin
FieldDefs[intCont].Precision := 64;
FieldDefs[intCont].Size := 32;
end;
end;
end;
the problem is ((FieldDefs[intCont].Size = 0) and (FieldDefs[intCont].DataType = ftBCD)). when ClientDataSet is created, the field is truncated, because when oracle has a function like "SUM(TOTAL)" the result field is created with size 0, so the clientdataset handle the field as Integer field.
Try with
ShowMessageFmt('Total: %n', [cdsGen.FieldByName('TOTAL').AsFloat])
or this
cdsGen := TClientDataSetFactory.GetClientDataSet(qryGen);
**(cdsGen.FieldByName('Total') as TFloatField).DisplayFormat := '0.00';**
ShowMessageFmt('Total: %f', [cdsGen.FieldByName('TOTAL').AsFloat])