I have the following API which takes a clob as one of it's arguments.
Receive_Order_API.Packed_Arrival(clob_,inParam1_,inParam2_);
When I use the debugger in our ERP, the api-call looks like this:
DECLARE
clob_ VARCHAR2(32000) := '!
$HEADER_START=TRUE
$SOURCE_REF1=45963
$SOURCE_REF2=1
$SOURCE_REF3=1
$SOURCE_REF4=
$SOURCE_REF_TYPE_DB=PURCHASE_ORDER
$CONV_FACTOR=1
$CONTRACT=3566
$DESCRIPTION=EX 1000V 3x95mm² AL
$LINE_END=TRUE
$HEADER_END=TRUE
';
inParam1_ VARCHAR2(32000) := '';
inParam2_ VARCHAR2(32000) := 'FALSE';
BEGIN
clob_ := Receive_Order_API.Packed_Arrival(clob_,inParam1_,inParam2_);
END;
What I am trying to do is to replace the data with my own values fetched from another table, something like this:
$SOURCE_REF1=:someOtherValue
$SOURCE_REF2=1
$SOURCE_REF3=1
$SOURCE_REF4=
$SOURCE_REF_TYPE_DB=PURCHASE_ORDER
$CONV_FACTOR=1
$CONTRACT=:someOtherValue
I guess somehow I need to escape the string to be able to replace the values but I can't figure out how and have been stuck on this for a while now.
Any help would be much appreciated!
Something like this?
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 clob_ VARCHAR2 (32000) := '!
3 $HEADER_START=TRUE
4 $SOURCE_REF1=45963
5 $SOURCE_REF2=1
6 $SOURCE_REF3=1
7 $SOURCE_REF4=
8 $SOURCE_REF_TYPE_DB=PURCHASE_ORDER
9 $CONV_FACTOR=1
10 $CONTRACT=3566
11 $DESCRIPTION=EX 1000V 3x95mm² AL
12 $LINE_END=TRUE
13 $HEADER_END=TRUE
14 ';
15
16 inParam1_ VARCHAR2 (32000) := '';
17 inParam2_ VARCHAR2 (32000) := 'FALSE';
18
19 l_source_ref1 NUMBER;
20 l_contract NUMBER;
21 BEGIN
22 SELECT 11111, 22222
23 INTO l_source_ref1, l_contract
24 FROM DUAL;
25
26 clob_ :=
27 REGEXP_REPLACE (clob_,
28 '\$SOURCE_REF1=\d+', --> escape $
29 '$SOURCE_REF1=' || l_source_ref1);
30 clob_ :=
31 REGEXP_REPLACE (clob_, '\$CONTRACT=\d+', --> escape $
32 '$CONTRACT=' || l_contract);
33
34 DBMS_OUTPUT.put_line (clob_);
35 END;
36 /
Result:
!
$HEADER_START=TRUE
$SOURCE_REF1=11111 --> new value here
$SOURCE_REF2=1
$SOURCE_REF3=1
$SOURCE_RE
F4=
$SOURCE_REF_TYPE_DB=PURCHASE_ORDER
$CONV_FACTOR=1
$CONTRACT=22222 --> and here
$DESCRIPTI
ON=EX 1000V 3x95mm2 AL
$LINE_END=TRUE
$HEADER_END=TRUE
PL/SQL procedure successfully completed.
SQL>
Related
I wrote a simple pl\sql procedure to read a value on db. For the same value I use two different function to have at the end to different value.
My code
begin
select TRIM(SUBSTR(RPAD(VAL,30,'N'),1,1)),DECODE(TRIM(SUBSTR(RPAD(VAL,30,'N'),2,2)),'S',TRUE,FALSE)
into va_flag, amount_zero
from ENV
where USER = 'C' and VARIABLE = 'FLAG_BALANCE';
exception
when others then
amount_zero := FALSE;
va_flag := 'N';
end;
When I compile the procedure, I've got the error message :"ORA-00904 "FALSE" Invalid Identifier" on decode function.
amount_zero is a boolean.
Unfortunately, it won't work straightforward; the first step will have to be a select into some other datatype (varchar2 whose value is Y/N or T/F; or a number with 1/0 ... pick any you want) and then switch to a Boolean, in a separate statement. For example:
SQL> declare
2 va_flag varchar2(1);
3 amount_zero boolean;
4 amount_zero_char varchar2(10);
5 begin
6 -- first select it into a VARCHAR2 variable ...
7 select decode(1, 1, 'T', 'F'),
8 'N'
9 into amount_zero_char,
10 va_flag
11 from env
12 where cuser = 'C'
13 and variable = 'FLAG_BALANCE';
14
15 -- ... then switch to Boolean
16 amount_zero := case when amount_zero_char = 'T' then true
17 else false
18 end;
19
20 -- display it
21 dbms_output.put_line(case when amount_zero then 'it is true'
22 else 'it is false'
23 end);
24 end;
25 /
it is true
PL/SQL procedure successfully completed.
SQL>
Oracle SQL cannot work directly with boolean data type (PL/SQL can but not SQL).
You should try to replace boolean literals with another data type for example VARCHAR2 (and adapt related code):
select
TRIM(SUBSTR(RPAD(VAL,30,'N'),1,1)),
DECODE(TRIM(SUBSTR(RPAD(VAL,30,'N'),2,2)),'S','TRUE','FALSE')
into va_flag, amount_zero
from ENV
I want insert a cursor into my custom tableObject, but it is not always found.
My RECORD:
create or replace type "RECORDRANKING" as object
(
-- Attributes
COL1 NUMBER,
COL2 VARCHAR(50),
COL3 NUMBER
-- Member functions and procedures
-- member procedure <ProcedureName>(<Parameter> <Datatype>)
)
This is object table:
CREATE OR REPLACE TYPE "TBRANKING" AS TABLE OF RECORDRANKING;
Now I go into creating a function (into a package):
CREATE OR REPLACE PACKAGE BODY PKLBOTTONI as
FUNCTION testlb
(
p_gapup IN NUMBER,
p_gadown IN NUMBER
)
RETURN SYS_REFCURSOR IS
cursor_ranking SYS_REFCURSOR;
position NUMBER ;
gap_ranking TBRANKING;
gaprecord RECORDRANKING;
upgap NUMBER;
downgap NUMBER;
BEGIN
select * into cursor_ranking from(
select pkranking.getRanking( 100 ) from dual);
LOOP
FETCH cursor_ranking INTO gap_ranking;
EXIT WHEN cursor_ranking%NOTFOUND;
INSERT INTO gap_ranking (COL1,COL2,COL3)
VALUES
(cursor_ranking.C1,
cursor_ranking.C2,
cursor_ranking.C3);
END LOOP;
return gap_ranking;
END;
END PKLBOTTONI;
I always get:
Compilation errors for PACKAGE BODY PKLBOTTONI
Error: PL/SQL: ORA-00942: table or view does not exist
Line: 32
Text: INSERT INTO gap_ranking
In the loop you're both fetching into "gap_ranking" and then trying to "insert into" it again. Insert into a collection is not a valid syntax. Fetch is ok, either in a loop or using bulk collect to fetch multiple records at once.
From your excerpt it doesn't look like you have a physical database table, so the way to do it in PL/SQL would be something like below.
For more help using collections you can check Oracle docs below too:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/collections.htm
SQL> set serveroutput on
SQL> declare
2 gap_ranking tbranking := tbranking(null); -- initialize
3 begin
4 gap_ranking.delete; -- clear empty record
5 for cur in
6 (select level as i from dual connect by level <= 5)
7 loop
8 -- insert empty
9 gap_ranking.extend;
10 -- attribute values
11 gap_ranking(gap_ranking.last) := recordranking(1000 + cur.i, 'TEST' || cur.i, 10 + cur.i);
12 end loop;
13 -- loop to print - just to illustrate
14 for j in gap_ranking.first .. gap_ranking.last
15 loop
16 dbms_output.put_line(gap_ranking(j).col1 || ',' ||
17 gap_ranking(j).col2 || ',' ||
18 gap_ranking(j).col3);
19
20 end loop;
21 -- same as...
22 for j in 1 .. gap_ranking.count
23 loop
24 dbms_output.put_line(gap_ranking(j).col1 || ',' ||
25 gap_ranking(j).col2 || ',' ||
26 gap_ranking(j).col3);
27
28 end loop;
29 end;
30 /
1001,TEST1,11
1002,TEST2,12
1003,TEST3,13
1004,TEST4,14
1005,TEST5,15
1001,TEST1,11
1002,TEST2,12
1003,TEST3,13
1004,TEST4,14
1005,TEST5,15
PL/SQL procedure successfully completed
SQL>
In my PL/SQL function, I m going to output a csv file for 14M million rows. There will be 3 fields in each row.
Im afraid the I/O process running time. I can create and output more than one csv file for this batch. I don want to use line by line output.
What is the best and quick way to writing file. For example, fetching data then filling into a record. And then write the file.
Thanks.
From Oracle 10g onwards, it is possible to write a CLOB to a file with a single call, using the DBMS_XSLPROCESSOR.CLOB2FILE procedure. In the following example, we will prepare a temporary CLOB with our data instead of writing it with UTL_FILE. When all source data has been added to the CLOB, we will write it to a flat-file in a single call.
SQL> DECLARE
2
3 v_file CLOB;
4 v_buffer VARCHAR2(32767);
5 v_name VARCHAR2(128) := 'clob2file_buffered.txt';
6 v_lines PLS_INTEGER := 0;
7 v_eol VARCHAR2(2);
8 v_eollen PLS_INTEGER;
9 c_maxline CONSTANT PLS_INTEGER := 32767;
10
11 BEGIN
12
13 v_eol := CASE
14 WHEN DBMS_UTILITY.PORT_STRING LIKE 'IBMPC%'
15 THEN CHR(13)||CHR(10)
16 ELSE CHR(10)
17 END;
18 v_eollen := LENGTH(v_eol);
19
20 DBMS_LOB.CREATETEMPORARY(v_file, TRUE);
21
22 FOR r IN (SELECT x || ',' || y || ',' || z AS csv
23 FROM source_data)
24 LOOP
25
26 IF LENGTH(v_buffer) + v_eollen + LENGTH(r.csv) <= c_maxline THEN
27 v_buffer := v_buffer || v_eol || r.csv;
28 ELSE
29 IF v_buffer IS NOT NULL THEN
30 DBMS_LOB.WRITEAPPEND(
31 v_file, LENGTH(v_buffer) + v_eollen, v_buffer || v_eol
32 );
33 END IF;
34 v_buffer := r.csv;
35 END IF;
36
37 v_lines := v_lines + 1;
38
39 END LOOP;
40
41 IF LENGTH(v_buffer) > 0 THEN
42 DBMS_LOB.WRITEAPPEND(
43 v_file, LENGTH(v_buffer) + v_eollen, v_buffer || v_eol
44 );
45 END IF;
46
47 DBMS_XSLPROCESSOR.CLOB2FILE(v_file, 'DUMP_DIR', v_name);
48 DBMS_LOB.FREETEMPORARY(v_file);
49
50 DBMS_OUTPUT.PUT_LINE('File='||v_name||'; Lines='||v_lines);
51
52 END;
53 /
File=clob2file_buffered.txt; Lines=1000000
PL/SQL procedure successfully completed.
Elapsed: 00:00:28.65
The CLOB-specific code is highlighted above and is self-explanatory (perhaps with the exception of the end-of-line character assignment on lines 13-17 which is different for Windows. UTL_FILE manages the port-specific end-of-line conversions for us, but with CLOBs we must manage this ourselves).
Of particular interest is the DBMS_XSLPROCESSOR call on line 47, which is our only write operation to the destination flat-file. We can see overall that this technique is similar in performance to our buffered UTL_FILE mechanism (the CLOB method was slightly quicker). We therefore have an alternative method for writing data, but there will be additional costs associated with using CLOBs (for example, temporary tablespace and buffer cache). If the volume of data to be dumped is high, then this method might put too much stress on our temporary tablespace and cause problems for other users (large sort operations, hash joins, global temporary tables etc).
Care should therefore be taken when using this method.
when using oracle forms to generate md5 hash, i get result that is different from the result given by tomcat.
when using tomcat digest, i get:
C:\apache-tomcat-6.0.26\bin>digest -a md5 mypass
mypass:a029d0df84eb5549c641e04a9ef389e5
while using oracle forms, i get:
a029d0dfbfeb5549c641e04abff3bfe5
this is the code:
Declare
v_checksum varchar2( 32 );
v_hex_value varchar2( 32 );
begin
v_checksum := SYS.DBMS_OBFUSCATION_TOOLKIT.MD5( input_string => 'mypass' );
SELECT LOWER( RAWTOHEX( v_checksum ) )
INTO v_hex_value
FROM dual;
:res := v_hex_value;
end;
why aren't they giving the same result ? is there something wrong with my code ?
which version of Oracle are you running ? Your code gives the good answer on 10.2.0.3.0:
SQL> VARIABLE res VARCHAR2(32);
SQL> Declare
2 v_checksum varchar2( 32 );
3 v_hex_value varchar2( 32 );
4 begin
5 v_checksum:=SYS.DBMS_OBFUSCATION_TOOLKIT.MD5(input_string=>'mypass');
6
7
8 SELECT LOWER( RAWTOHEX( v_checksum ) )
9 INTO v_hex_value
10 FROM dual;
11
12 :res := v_hex_value;
13 end;
14 /
PL/SQL procedure successfully completed
res
---------
a029d0df84eb5549c641e04a9ef389e5
Also I tried the other MD5 functions and they give the same answer:
SQL> DECLARE
2 l_input RAW(16) := utl_raw.cast_to_raw('mypass');
3 BEGIN
4 :res:=lower(rawtohex(dbms_obfuscation_toolkit.md5(input=>l_input)));
5 END;
6 /
PL/SQL procedure successfully completed
res
---------
a029d0df84eb5549c641e04a9ef389e5
Your code seems correct
I also get a029d0df84eb5549c641e04a9ef389e5 here http://md5hashgenerator.com/index.php
and also in sql server I get the same
SELECT CONVERT(VARCHAR(32),HashBytes('MD5', 'mypass'),2)
I have a stored procedure with an IN OUT parameter declared like follows:
create or replace PROCEDURE RIFATT_SEGN0_INS(pIdRifattSegn0 in OUT NUMBER,
pNumDossier IN VARCHAR2 ,
pNumConsegna IN NUMBER,
pDtConsegna IN DATE,
[..]
) AS
[..]
Whenever i call it from another procedure, how do i get the pIdRifattSegn0 parameter that is also out?
Your question isn't entirely clear. An IN OUT parameter is passed both ways, as its name implies. This means it has to be passed a variable, not a literal and you need a declare block to do that. For example:
declare
l_segn number;
begin
l_segn := 1;
-- procedure will have received value = 1
rifatt_segn0_ins(l_segn, 'x', 2, sysdate);
-- procedure may have changed value of l_segn from 1 to something else
dbms_output.put_line(l_segn);
end;
Here is an example:
SQL> create or replace PROCEDURE RIFATT_SEGN0_INS
2 ( pIdRifattSegn0 IN OUT NUMBER
3 , pNumDossier IN VARCHAR2
4 , pNumConsegna IN NUMBER
5 , pDtConsegna IN DATE
6 )
7 as
8 begin
9 dbms_output.put_line(pNumDossier);
10 dbms_output.put_line(to_char(pNumConsegna));
11 dbms_output.put_line(to_char(pDtConsegna,'yyyy-mm-dd'));
12 pIdRifattSegn0 := sqrt(pIdRifattSegn0);
13 end;
14 /
Procedure is aangemaakt.
SQL> create or replace procedure another_procedure
2 as
3 l_IdRifattSegn0 number := 4;
4 begin
5 rifatt_segn0_ins
6 ( pIdRifattSegn0 => l_IdRifattSegn0
7 , pNumDossier => '1A'
8 , pNumConsegna => 42
9 , pDtConsegna => sysdate
10 );
11 dbms_output.put_line('from another_procedure: l_IdRifattSegn0 = ' || to_char(l_IdRifattSegn0));
12 end;
13 /
Procedure is aangemaakt.
SQL> exec another_procedure
1A
42
2009-05-21
from another_procedure: l_IdRifattSegn0 = 2
PL/SQL-procedure is geslaagd.
Regards,
Rob.