为什么视图列的类型与相应的函数结果类型不匹配?

Why type of a view column does not match corresponding function result type?

假设有一个函数 my_pkg.get_prop_of,即 return 类型 CHAR(5) 的值。 另外让我们声明一个视图 my_view,其中有一列 prop,从这个函数调用中获取它的值。

create or replace package my_pkg AS

  subtype short_string is CHAR(5);

  function get_prop_of(pi_name char)
    return short_string;    
end;    

create or replace package body my_pkg AS

  function get_prop_of(pi_name char)
    return short_string is
  begin
    return substr(pi_name || 'abcde', 1, 5);
  end;    
end;
---

create or replace view my_view as
select 
       my_pkg.get_prop_of('x') as prop
  from dual;

您能否解释一下为什么数据字典将该列类型显示为 VARCHAR2(4000),这种行为的目的是什么?

select table_name, data_Type, data_length
  from all_tab_cols
 where table_name = 'MY_VIEW';

----------------------------------------------------
 TABLE_NAME | COLUMN_NAME | DATA_TYPE | DATA_LENGTH
----------------------------------------------------
   MY_VIEW  |  PROP       |  VARCHAR2 |    4000

看起来数据字典包含让编译器在视图编译时应用它所需的数据。但不知为什么它不会那样做。

select object_name, package_name, data_type, data_length, in_out
  from all_arguments
 where object_name = 'GET_PROP_OF';

-----------------------------------------------------------------
  OBJECT_NAME  | PACKAGE_NAME | DATA_TYPE | DATA_LENGTH | IN_OUT
-----------------------------------------------------------------
  GET_PROP_OF  |    MY_PKG    |   CHAR    |      5      |  OUT     <- return type
  GET_PROP_OF  |    MY_PKG    |   CHAR    |             |  IN

我想以一种清晰的方式获得列类型和函数结果类型的匹配。

据了解,像CAST(val AS CHAR(5))这样的硬铸造可以暂时解决问题, 但是有没有更优雅的方法,它还可以处理更改函数 return 类型的情况,而无需更改列中各处的 CAST 表达式,调用该函数。

因为在创建 VIEW 时,Oracle 不知道从 function 返回的 function 结果的最大值,但它知道数据类型。

此外,事实是 --> function 的任何返回值都不能包含 data precision.

您仍然可以通过使用 CAST 控制 VIEW 查询中的数据类型和精度来实现您想要的效果,如下所示:

SQL>
SQL> CREATE OR REPLACE VIEW MY_VIEW AS
  2      SELECT
  3          CAST(MY_PKG.GET_PROP_OF('x') AS VARCHAR2(5)) AS PROP
  4      FROM
  5          DUAL;

View created.

SQL> DESC MY_VIEW;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 PROP                                               VARCHAR2(5)

SQL>

干杯!!

因为您使用函数创建视图

create or replace view my_view as
select 
       substr(my_pkg.get_prop_of('x'),0,5) q
  from dual;

  select table_name, data_Type, data_length
  from dba_tab_cols
 where table_name = 'MY_VIEW';



MY_VIEW VARCHAR2    5