【问题标题】:Difference between CHAR and VARCHAR2 in PL/SQL function parametersPL/SQL函数参数中CHAR和VARCHAR2的区别
【发布时间】:2018-10-24 09:17:59
【问题描述】:

让我们考虑具有这些签名的四个函数:

FUNCTION my_func_1(pi_param CHAR) RETURN CHAR ...
FUNCTION my_func_2(pi_param CHAR) RETURN VARCHAR2 ...
FUNCTION my_func_3(pi_param VARCHAR2) RETURN VARCHAR2 ...
FUNCTION my_func_4(pi_param VARCHAR2) RETURN CHAR ...

假设他们都有你选择的相同身体。

您能否举一个涉及这些函数的示例,以说明使用其中一个函数的行为或优势有何不同?

我在 PL/SQL 代码中几乎到处都看到程序员更喜欢将字符串参数声明为 VARCHAR2,尽管文献中没有明显的理由提到这一点并且没有实际好处(因为 CHAR 至少有一个较短的名称) .

请省略对字符类型在常量或变量声明中的基本区别的解释 - 并专注于函数参数和返回类型的大小写。

【问题讨论】:

标签: string plsql parameters char varchar2


【解决方案1】:

您可以敲出自己的测试用例来证明这一点,这并不难。但是,既然你没有,这里有一个显示差异:

DECLARE
  v_input_str VARCHAR2(4) := 'abcd';
  v_p_char CHAR(10);
  v_p_vchar VARCHAR2(10);
  v_ret_char CHAR(20);
  v_ret_vchar VARCHAR2(20);

  FUNCTION my_func_1(pi_param CHAR) RETURN CHAR
  IS
    v_var CHAR(10);
  BEGIN
    v_var := pi_param;
    dbms_output.put_line('  my_func_1: length(pi_param) = '||LENGTH(pi_param));
    dbms_output.put_line('  my_func_1: length(v_var) = '||LENGTH(v_var));
    RETURN v_var;
  END my_func_1;

  FUNCTION my_func_2(pi_param CHAR) RETURN VARCHAR2
  IS
    v_var VARCHAR2(10);
  BEGIN
    v_var := pi_param;
    dbms_output.put_line('  my_func_2: length(pi_param) = '||LENGTH(pi_param));
    dbms_output.put_line('  my_func_2: length(v_var) = '||LENGTH(v_var));
    RETURN v_var;
  END my_func_2;

  FUNCTION my_func_3(pi_param VARCHAR2) RETURN VARCHAR2
  IS
    v_var VARCHAR2(10);
  BEGIN
    v_var := pi_param;
    dbms_output.put_line('  my_func_3: length(pi_param) = '||LENGTH(pi_param));
    dbms_output.put_line('  my_func_3: length(v_var) = '||LENGTH(v_var));
    RETURN v_var;
  END my_func_3;

  FUNCTION my_func_4(pi_param VARCHAR2) RETURN CHAR
  IS
    v_var CHAR(10);
  BEGIN
    v_var := pi_param;
    dbms_output.put_line('  my_func_4: length(pi_param) = '||LENGTH(pi_param));
    dbms_output.put_line('  my_func_4: length(v_var) = '||LENGTH(v_var));
    RETURN v_var;
  END my_func_4;
BEGIN
  v_p_char := v_input_str;
  v_p_vchar := v_input_str;

  dbms_output.put_line('length(v_p_char) = '||length(v_p_char));
  dbms_output.put_line('length(v_p_vchar) = '||length(v_p_vchar));

  v_ret_char := my_func_1(v_p_char);
  dbms_output.put_line('my_func_1, v_p_char input, char output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_1(v_p_char);
  dbms_output.put_line('my_func_1, v_p_char input, char output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_1(v_p_vchar);
  dbms_output.put_line('my_func_1, v_p_vchar input, char output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_1(v_p_vchar);
  dbms_output.put_line('my_func_1, v_p_vchar input, char output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_2(v_p_char);
  dbms_output.put_line('my_func_2, v_p_char input, varchar output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_2(v_p_char);
  dbms_output.put_line('my_func_2, v_p_char input, varchar output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_2(v_p_vchar);
  dbms_output.put_line('my_func_2, v_p_vchar input, varchar output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_2(v_p_vchar);
  dbms_output.put_line('my_func_2, v_p_vchar input, varchar output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_3(v_p_char);
  dbms_output.put_line('my_func_3, v_p_char input, varchar output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_3(v_p_char);
  dbms_output.put_line('my_func_3, v_p_char input, varchar output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_3(v_p_vchar);
  dbms_output.put_line('my_func_3, v_p_vchar input, varchar output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_3(v_p_vchar);
  dbms_output.put_line('my_func_3, v_p_vchar input, varchar output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_4(v_p_char);
  dbms_output.put_line('my_func_4, v_p_char input, char output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_4(v_p_char);
  dbms_output.put_line('my_func_4, v_p_char input, char output: length(v_ret_vchar) = '||length(v_ret_vchar));

  v_ret_char := my_func_4(v_p_vchar);
  dbms_output.put_line('my_func_4, v_p_vchar input, char output: length(v_ret_char) = '||length(v_ret_char));
  v_ret_vchar := my_func_4(v_p_vchar);
  dbms_output.put_line('my_func_4, v_p_vchar input, char output: length(v_ret_vchar) = '||length(v_ret_vchar));

END;
/

输出是:

length(v_p_char) = 10
length(v_p_vchar) = 4
  my_func_1: length(pi_param) = 10
  my_func_1: length(v_var) = 10
my_func_1, v_p_char input, char output: length(v_ret_char) = 20
  my_func_1: length(pi_param) = 10
  my_func_1: length(v_var) = 10
my_func_1, v_p_char input, char output: length(v_ret_vchar) = 10
  my_func_1: length(pi_param) = 4
  my_func_1: length(v_var) = 10
my_func_1, v_p_vchar input, char output: length(v_ret_char) = 20
  my_func_1: length(pi_param) = 4
  my_func_1: length(v_var) = 10
my_func_1, v_p_vchar input, char output: length(v_ret_vchar) = 10
  my_func_2: length(pi_param) = 10
  my_func_2: length(v_var) = 10
my_func_2, v_p_char input, varchar output: length(v_ret_char) = 20
  my_func_2: length(pi_param) = 10
  my_func_2: length(v_var) = 10
my_func_2, v_p_char input, varchar output: length(v_ret_vchar) = 10
  my_func_2: length(pi_param) = 4
  my_func_2: length(v_var) = 4
my_func_2, v_p_vchar input, varchar output: length(v_ret_char) = 20
  my_func_2: length(pi_param) = 4
  my_func_2: length(v_var) = 4
my_func_2, v_p_vchar input, varchar output: length(v_ret_vchar) = 4
  my_func_3: length(pi_param) = 10
  my_func_3: length(v_var) = 10
my_func_3, v_p_char input, varchar output: length(v_ret_char) = 20
  my_func_3: length(pi_param) = 10
  my_func_3: length(v_var) = 10
my_func_3, v_p_char input, varchar output: length(v_ret_vchar) = 10
  my_func_3: length(pi_param) = 4
  my_func_3: length(v_var) = 4
my_func_3, v_p_vchar input, varchar output: length(v_ret_char) = 20
  my_func_3: length(pi_param) = 4
  my_func_3: length(v_var) = 4
my_func_3, v_p_vchar input, varchar output: length(v_ret_vchar) = 4
  my_func_4: length(pi_param) = 10
  my_func_4: length(v_var) = 10
my_func_4, v_p_char input, char output: length(v_ret_char) = 20
  my_func_4: length(pi_param) = 10
  my_func_4: length(v_var) = 10
my_func_4, v_p_char input, char output: length(v_ret_vchar) = 10
  my_func_4: length(pi_param) = 4
  my_func_4: length(v_var) = 10
my_func_4, v_p_vchar input, char output: length(v_ret_char) = 20
  my_func_4: length(pi_param) = 4
  my_func_4: length(v_var) = 10
my_func_4, v_p_vchar input, char output: length(v_ret_vchar) = 10

CHAR 和 VARCHAR 之间的区别在于 CHAR 会将填充字符串间隔到变量/列的全宽。这可能对报告有用,但总的来说,这意味着您正在浪费内存来存储所有额外的空间。

从上面的输出中,您可以看到,当您将四个字符的字符串存储在 CHAR(20) 变量中时,该变量的长度为 20 - 您原来的四个字符,加上 16 个空格。 VARCHAR2(20) 变量中对应的字符串长度为 4。

我创建的函数将输入字符串(CHAR(10) 或 VARCHAR2(10))放入变量(CHAR(10) 或 VARCHAR2(10))中,然后将其传递给变量(CHAR(20) 或 VARCHAR2(20))。

您可以看到,在函数返回变量时,长度是 4 或 10,但是当保存返回值的变量的长度是 4、10 或 20 时。

您可以看到 VARCHAR2 变量不会改变变量的长度,但只要将 CHAR 变量添加到组合中,长度就会增加。

简而言之,只有在没有其他选择的情况下才使用 CHAR。否则,使用 VARCHAR2。

你说你只关心学习函数参数和返回类型,而不是变量,但它们是一回事!

【讨论】:

  • 感谢@Boneist 进行大量测试。我想我们都知道将变量声明为 VARCHAR2 和 CHAR 有什么区别,因为我在问题中提到了它。事实上,这些测试用例只显示了v_ret_char 和v_ret_vchar 变量本身的行为。我在我的问题中的意思是我们可以显示length(my_func_1('ABC')) 和length(my_func_2('ABC')) 等之间的差异吗?没有将结果分配给变量看起来都一样。
  • 我觉得你想多了。函数的输出返回什么并不重要,它返回的变量决定了结果字符串的样子。函数的返回值有一个类型,但它没有与之关联的长度 - 这是由返回变量决定的。
  • 例如,如果将 4 个字符的 CHAR 字符串传递给 my_func_1,则函数的返回值也将是 4 个字符,因为输入字符串决定了输出 CHAR 值的长度。但是您将该值返回到 CHAR(20) 变量中,现在结果将是 20 个字符的长度。这意味着,如果您想知道函数返回的变量的长度,则需要使用 VARCHAR2 变量,因为与 CHAR 不同,它不会人为地改变值的长度。
  • 我用一个例子编辑了我的答案,希望能让事情更清楚。基本上,函数的参数和返回值也是变量,所以它们遵循相同的规则。
猜你喜欢
  • 1970-01-01
  • 2017-09-25
  • 2017-05-26
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 2012-03-10
相关资源
最近更新 更多