CREATE OR REPLACE FUNCTION sumNumbers(p VARCHAR2) RETURN NUMBER IS
...
SELECT sumNumbers('3 + 6 + 13 + 0 + 1') FROM dual;
所以輸出應該是:23
PL/SQL用「+」分割一個字符串並對其中的數字求和?
CREATE OR REPLACE FUNCTION sumNumbers(p VARCHAR2) RETURN NUMBER IS
...
SELECT sumNumbers('3 + 6 + 13 + 0 + 1') FROM dual;
所以輸出應該是:23
PL/SQL用「+」分割一個字符串並對其中的數字求和?
您可以使用一個 '竅門' 與XML和XPath評估要做到這一點,而無需手動tokenising字符串:
select * from xmltable('3 + 6 + 13 + 0 + 1' columns result number path '.');
RESULT
----------
23
或者:
select to_number(xmlquery('3 + 6 + 13 + 0 + 1' returning content).getStringVal()) as result
from dual;
RESULT
----------
23
這是作爲其他運營商可以使用更靈活:
select * from xmltable('2 * (5 + 7) - 3' columns result number path '.');
RESULT
----------
21
使用正常/
運營商,雖然它不喜歡分裂,你需要使用div
代替,所以你可能需要做您的源字符串替換,如果它可能包含一個斜槓:
select * from xmltable('2 * (5 + 7) div 3' columns result number path '.');
RESULT
----------
8
閱讀更多關於Oracle's XPath handling和。
你可以直接調用它,而不需要函數;但如果你特別想將其包裝在一個函數這是一個稍微複雜的XPath的必須固定在分析時,那麼你就需要使用動態SQL:
CREATE OR REPLACE FUNCTION sumNumbers(p VARCHAR2) RETURN NUMBER IS
l_result NUMBER;
BEGIN
execute immediate q'[select * from xmltable(']'
|| replace(p, '/', ' div ')
|| q'[' columns result number path '.')]'
into l_result;
return l_result;
END;
/
SELECT sumNumbers('3 + 6 + 13 + 0 + 1') FROM dual;
SUMNUMBERS('3+6+13+0+1')
---------------------------------------
23
我用the alternative quoting mechanism避免逃避聲明中的單引號,儘管我不確定它在這裏更清晰。並且我已經包含了replace()
以防需要分割,但它不需要那麼直接將p
直接連接到SQL語句中。有了替代你可以這樣做:
SELECT sumNumbers('2 * (5 + 7)/3') FROM dual;
如果你要允許其靈活的功能應該有不同的名稱...
不錯,從來沒有想過(錯) - 以這種方式使用XPath。 –
謝謝,但我應該如何實現你的代碼到我的函數? – andrasb
@andrasb - 添加了一個使用XMLTable方法的函數。 –
您可以用層次查詢和正則表達式中提取的數字,總結的結果。事情是這樣的:
WITH t AS (
SELECT '3 + 6 + 13 + 0 + 1' numbers FROM DUAL
)
SELECT SUM(TRIM(REGEXP_SUBSTR(numbers,'(?[[:digit:]]+ ?)',1,LEVEL)))
FROM t
CONNECT BY LENGTH(SUBSTR(numbers,DECODE(REGEXP_INSTR(numbers,'(?[[:digit:]]+ ?)',1,LEVEL),0,NULL,REGEXP_INSTR(numbers,'(?[[:digit:]]+ ?)',1,LEVEL)))) <= LENGTH(SUBSTR(numbers,DECODE(REGEXP_INSTR(numbers,'(?[[:digit:]]+ ?)',1,LEVEL),0,NULL,REGEXP_INSTR(numbers,'(?[[:digit:]]+ ?)',1,LEVEL))));
如果你只是想試用的表達,爲什麼不」你只是 - 好 - 評估它?
FUNCTION sumNumbers(p VARCHAR2) RETURN NUMBER IS
l_result NUMBER;
BEGIN
EXECUTE IMMEDIATE 'begin :n := ' || p || '; end;'
USING OUT l_result;
RETURN l_result;
END;
我在答案的第一個版本中採用了類似的方法,但確定SQL注入風險並不明智。啊,但我選擇了雙重結果;這在某種程度上更好,但是你仍然可以用'p'來做一些令人討厭的事情。你可以像'1;立即執行''drop table x''''例如? –
當然,我以爲你對快速和骯髒的解決方案感興趣。爲了避免SQL注入,我建議首先驗證表達式(例如使用正則表達式)。 Alex建議的xml技巧也應該是安全的 –
你是否一定要分裂它,或者你真的只是想要評估任何方式,你可以?它總是隻有加號,還是可以有其他操作符,括號等?數字總是正整數嗎? –