从Oracle PLSQL调用java时如何将参数传递给java
我试图从plsql调用一个java函数来在csv字符串中的某个索引处返回一个csv项目。 csv字符串还可以在引号内包含分隔符(基于此堆栈溢出问题)。
代码
set serverout on size 100000
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "XxpayCsv" AS
import java.io.ByteArrayInputStream;
public class XxpayCsv
{
public static String csv(String line, Integer idx)
{
String otherThanQuote = " [^"] ";
String quotedString = String.format(" " %s* " ", otherThanQuote);
String regex = String.format("(?x) "+ // enable comments, ignore white spaces
", "+ // match a comma
"(?= "+ // start positive look ahead
" (?: "+ // start non-capturing group 1
" %s* "+ // match 'otherThanQuote' zero or more times
" %s "+ // match 'quotedString'
" )* "+ // end group 1 and repeat it zero or more times
" %s* "+ // match 'otherThanQuote'
" $ "+ // match the end of the string
") ", // stop positive look ahead
otherThanQuote, quotedString, otherThanQuote);
String[] tokens = line.split(regex, -1);
//for(String t : tokens) {
// System.out.println("> "+t);
//}
return tokens[idx];
}
};
/
CREATE OR REPLACE
FUNCTION xxpay_csv_at(s varchar2, i number) RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'XxpayCsv.csv (s, i) return java.lang.String';
/
DECLARE
my_string clob; -- VARCHAR2(400 CHAR);
BEGIN
my_string := xxpay_csv_at('a,"b,c",d', 1);
dbms_output.put_line('The value of the string is: ' || my_string);
END;
/
给我的错误
DECLARE
*
ERROR at line 1:
ORA-29531: no method csv in class XxpayCsv
ORA-06512: at "APPS.XXPAY_CSV_AT", line 1
ORA-06512: at line 4
因为我不知道如何传递字符串和整数作为参数(我不是Java程序员)。 我究竟做错了什么?
您需要使用完整的java路径在函数说明中给出数据类型(而不是参数名称):
CREATE OR REPLACE FUNCTION xxpay_csv_at(s varchar2, i number) RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'XxpayCsv.csv ( java.lang.String, java.lang.Integer ) return java.lang.String';
/
(注意: java.lang.Integer
而不是int
以符合您在Java代码中的规范)
但你可能想要的只是在Oracle中实现它:
SQL小提琴
Oracle 11g R2架构设置 :
CREATE OR REPLACE FUNCTION xxpay_csv_at(
s varchar2,
i number
) RETURN VARCHAR2 DETERMINISTIC
IS
BEGIN
RETURN REGEXP_SUBSTR(
s,
'(^|,)(([^,"]*".*?")*[^,"]*)',
1,
i,
NULL,
2
);
END;
/
查询1 :
WITH table_name ( csv ) AS (
SELECT 'foo,bar,c;qual="baz,b""lurb",d;junk="quux,syzygy"' FROM DUAL
)
SELECT csv,
xxpay_csv_at( csv, 1 ) AS value1,
xxpay_csv_at( csv, 2 ) AS value2,
xxpay_csv_at( csv, 3 ) AS value3,
xxpay_csv_at( csv, 4 ) AS value4
FROM table_name
结果 :
| CSV | VALUE1 | VALUE2 | VALUE3 | VALUE4 |
|---------------------------------------------------|--------|--------|----------------------|----------------------|
| foo,bar,c;qual="baz,b""lurb",d;junk="quux,syzygy" | foo | bar | c;qual="baz,b""lurb" | d;junk="quux,syzygy" |
更新 :
有没有办法从regexp_substr获取匹配值的位置,这样我就不能只返回某个索引处的csv项目,而是返回原始csv字符串中开始和结束的字符位置?
使用REGEXP_INSTR
而不是REGEXP_SUBSTR
编写另一个函数。
或者使用下面的函数并分别返回CURR
和DPOS
作为开始和结束。
(注意:SQL中使用的函数只能返回单个值,因此您需要返回具有值,开始和结束属性的对象类型,或者对于子字符串,开始和结束有三个单独的函数。)
还希望能够添加分隔符和quoted_by作为参数并支持分隔符,如','(逗号后面有一个空格)。
是的,但不容易使用正则表达式。 像这样的东西(部分测试,但没有通过所有的边缘情况):
SQL小提琴
Oracle 11g R2架构设置 :
CREATE OR REPLACE FUNCTION xxpay_csv_at(
s varchar2,
i number,
delim VARCHAR2 DEFAULT ','
) RETURN VARCHAR2 DETERMINISTIC
IS
j PLS_INTEGER := 1;
curr PLS_INTEGER := 1;
dpos PLS_INTEGER;
qpos PLS_INTEGER;
BEGIN
WHILE TRUE LOOP
dpos := INSTR( s, delim, curr );
qpos := INSTR( s, '"', curr ); -- Start quote
WHILE qpos BETWEEN curr AND dpos LOOP
qpos := INSTR( s, '"', qpos + 1 ); -- End quote
IF qpos = 0 THEN
RAISE_APPLICATION_ERROR( -20000, 'Invalid String - No matching end-quote' );
END IF;
dpos := INSTR( s, delim, qpos + 1 );
qpos := INSTR( s, '"', qpos + 1 );
END LOOP;
IF dpos = 0 THEN
IF i = j THEN
RETURN SUBSTR( s, curr );
ELSE
RETURN NULL;
END IF;
ELSE
IF i = j THEN
RETURN SUBSTR( s, curr, dpos - curr );
ELSE
j := j + 1;
curr := dpos + LENGTH( delim );
END IF;
END IF;
END LOOP;
END;
/
查询2 :
WITH table_name ( csv ) AS (
SELECT ', foo,bar, c;qual="baz, b""lurb", d;junk="quux, syzygy", , ' FROM DUAL
)
SELECT csv,
xxpay_csv_at( csv, 1, ', ' ) AS value1,
xxpay_csv_at( csv, 2, ', ' ) AS value2,
xxpay_csv_at( csv, 3, ', ' ) AS value3,
xxpay_csv_at( csv, 4, ', ' ) AS value4,
xxpay_csv_at( csv, 5, ', ' ) AS value5,
xxpay_csv_at( csv, 6, ', ' ) AS value6
FROM table_name
结果 :
| CSV | VALUE1 | VALUE2 | VALUE3 | VALUE4 | VALUE5 | VALUE6 |
|-------------------------------------------------------------|--------|---------|-----------------------|-----------------------|--------|--------|
| , foo,bar, c;qual="baz, b""lurb", d;junk="quux, syzygy", , | (null) | foo,bar | c;qual="baz, b""lurb" | d;junk="quux, syzygy" | (null) | (null) |
原来的答案是:
CREATE OR REPLACE
FUNCTION xxpay_csv_at(s varchar2, i number) RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'XxpayCsv.csv (java.lang.String, int) return java.lang.String';
/
链接地址: http://www.djcxy.com/p/6305.html
上一篇: How to pass parameters to java when calling java from Oracle PLSQL