DBMS_OUTPUT.PUT_LINE 抛出 "PL/SQL: numeric or value error"

DBMS_OUTPUT.PUT_LINE throws "PL/SQL: numeric or value error"

我想使用 DBMS_OUTPUT.PUT_LINE 在 oracle pl/sql 中测试我的一个函数。我遇到的问题是,当我在我的函数中写入一个点号时,出现以下错误:

错误

ORA-06502: PL/SQL: numerischer oder Wertefehler: Fehler beim Konvertieren von Zeichen zu Zahl
ORA-06512: in Zeile 4 // line 4 is "v_net := pricecalculator(120.09)"
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.

这个有效

CREATE OR REPLACE FUNCTION Pricecalculator(net IN NUMBER, vat IN NUMBER DEFAULT 0.19)
    RETURN NUMBER
    IS
        Result NUMBER;
    BEGIN
        Result := net * (1 + vat);
        RETURN Result;
    END;
/

SET SERVEROUTPUT ON

DECLARE
    v_net NUMBER;
BEGIN
    v_net := Pricecalculator(120);
    DBMS_OUTPUT.PUT_LINE(v_net); // Prints (142.8)
END;
/

这不起作用(见错误)

SET SERVEROUTPUT ON

DECLARE
    v_net NUMBER;
BEGIN
    v_net := Pricecalculator(120.09);
    DBMS_OUTPUT.PUT_LINE(v_net); // When I delete this, v_net gets compiled but I wont see the result
END;
/

我是 oracle 的新手 pl/sql 并且对为什么第二种方法不起作用一无所知。

This seems to be a bug in SQL Developer. Looking at the statement log, your block is being converted to:

DECLARE SqlDevBind1Z_1 VARCHAR2(32767):=:SqlDevBind1ZInit1;  BEGIN DECLARE
    v_net NUMBER;
BEGIN
    v_net := Pricecalculator(TO_NUMBER( SqlDevBind1Z_1));
    DBMS_OUTPUT.PUT_LINE(v_net);
END;
 :AUXSQLDBIND1:=SqlDevBind1Z_1;  END;

and this part:

TO_NUMBER( SqlDevBind1Z_1)

is doing an implicit conversion. That will use your NLS_NUMERIC_CHARTACTERS setting, as @Zilog80 suggested, so it's only a problem when that is set to ',.' - i.e. with a comma as the decimal separator.

You can work around it by doing:

alter session set nls_numeric_characters = '.,'

but then your implicitly-converted output will be 142.9071 not 142,9071. If you want the comma separator in the output you would then need an explicit conversion:

DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_net, '99990.9999', 'nls_numeric_characters='',.'''));

... except SQL Developer is also borking that; which is why you showed periods in your question, presumably. Hopefully that is what you want to see...