用于初始化IN参数的UPPER函数未按预期工作

uda*_*rH3 0 sql oracle oracle11g

CREATE OR REPLACE PROCEDURE appraisal
  (p_grade IN VARCHAR2 := UPPER(' '))
IS
 v_appraisal VARCHAR2(20) := '';
BEGIN
 v_appraisal := CASE p_grade
     WHEN 'A' THEN 'Excellent'
     WHEN 'B' THEN 'Very good'
     WHEN 'C' THEN 'Bad'
     ELSE 'No such grade!'
     END;
 DBMS_OUTPUT.PUT_LINE('Grade:-'||p_grade ||' Appraisal:-'|| v_appraisal);
END;
/

EXECUTE appraisal('a');
Run Code Online (Sandbox Code Playgroud)

输出:

Grade:-a Appraisal:-No such grade!"
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这不起作用 - 我做错了什么?

Ale*_*ole 5

The UPPER() function does return the uppercase version of whatever is passed to it, but in your default clause you're passing the literal ' ', which is a single space. Whitespace has no casing so there is no difference between lowercase space and uppercase space - the concept doesn't really make sense. You are not passing in the procedure's parameter value to that function.

The defaut clause is there to provide a default value if the caller doesn't supply one. So if you did execute appraisal; then within that procedure call the p_grade variable would have a value if a single space, which isn't helpful, and isn't what you want here. You don't really want a default at all.

As @DavidFaber said you need to get the uppercase equivalent of the parmeter value when you evaluate it, so you could do:

CREATE OR REPLACE PROCEDURE appraisal
  (p_grade IN VARCHAR2)
IS
 v_appraisal VARCHAR2(20);
BEGIN
 v_appraisal := CASE UPPER(p_grade)
     WHEN 'A' THEN 'Excellent'
     WHEN 'B' THEN 'Very good'
     WHEN 'C' THEN 'Bad'
     ELSE 'No such grade!'
     END;
 DBMS_OUTPUT.PUT_LINE('Grade:-'|| UPPER(p_grade)
  ||' Appraisal:-'|| v_appraisal);
END;
/
Run Code Online (Sandbox Code Playgroud)

Alternativley you could declare a local variable that is set to the uppercase value and use that:

 v_grade varchar2(1) := UPPER(p_grade);
Run Code Online (Sandbox Code Playgroud)

You shouldn't generally assume that whoever calls your procedure will display the dbms_output buffer. It's OK for debugging or experimenting where you have control of the calling environment, but not in real code, usually. You might actually want a function that returns the v_appraisal values, for example. Here's an SQL Fiddle demo of a simole function version. Or just a look-up table that holds the grades and their descriptions.