2

我想在 Oracle 对象类型中设置默认值,但它要求所有属性都需要在构造函数中传递。

无论如何,这样我就可以在需要默认值的构造函数中传递必需的属性。

请查看以下详细信息

    SQL> 创建类型 TYPE_SUB 作为对象(
      2 列 1 号,
      3 COL2 VARCHAR2(100)
      4)
      5 不是最终的
      6 /

    创建的类型。

    SQL> 创建或替换类型 TYPE_MAIN
      2 在 TYPE_SUB 下
      3 (
      4 COL3 varchar2(10),
      5 COL4 VARCHAR2(10),
      6 CONSTRUCTOR FUNCTION TYPE_MAIN(COL1 NUMBER,COL2 VARCHAR2,COL3 varchar2,COL4 VARCHAR2)返回自我作为结果)
      7 不是最终的
      8 /

    创建的类型。

    SQL> 创建或替换类型主体 TYPE_MAIN 是
      2 CONSTRUCTOR FUNCTION TYPE_MAIN (COL1 NUMBER, COL2 VARCHAR2, COL3 varchar2, COL4 VARCHAR2) 按结果返回自我
      3 开始
      4 SELF.COL1 := nvl(COL1,123);
      5 SELF.COL2 := nvl(COL2,'NA');
      6 SELF.COL3 := nvl(COL3,'NA');
      7 SELF.COL4 := nvl(COL4,NULL);
      8 返回;
      9 结束;
     10 结束;
     11 /

    创建的类型主体。

    SQL> 创建表 TAB_MAIN (
      2 个密钥号码,
      3 COLTEST VARCHAR2(100),
      4 COLNEW TYPE_MAIN)
      5 /

    表已创建。

    SQL> 插入 TAB_MAIN(PKEY) 值(1)
      2 /

    创建了 1 行。

    SQL> INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW) 值(1,'TESTCOL',TYPE_MAIN('1','2',NULL,NULL))
      2 /

    创建了 1 行。

    SQL> INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW) 值(1,'TESTCOL2',TYPE_MAIN('1',NULL,NULL,NULL))
      2 /

    创建了 1 行。

    SQL> SELECT * FROM TAB_MAIN
      2 /

          PKEY COLEST COLNEW(COL1、COL2、COL3、COL4)
    ---------- ---------- ------------------ ----------
             1
             1 TESTCOL TYPE_MAIN(1, '2', 'NA', NULL)
             1 TESTCOL2 TYPE_MAIN(1, 'NA', 'NA', NULL)

现在,在上面的例子中,如果我只在构造函数中传递 Col3 和 Col4 属性作为默认值,那么它就不起作用了。请看下面的例子。

    SQL> 创建类型 TYPE_SUB 作为对象(
      2 列 1 号,
      3 COL2 VARCHAR2(100)
      4)
      5 不是最终的
      6 /

    创建的类型。

    SQL> 创建或替换类型 TYPE_MAIN
      2 在 TYPE_SUB 下
      3 (
      4 COL3 varchar2(10),
      5 COL4 VARCHAR2(10),
      6 CONSTRUCTOR FUNCTION TYPE_MAIN(COL3 varchar2, COL4 VARCHAR2) 作为结果返回自身)
      7 不是最终的
      8 /

    创建的类型。

    SQL> 创建或替换类型主体 TYPE_MAIN 是
      2 CONSTRUCTOR FUNCTION TYPE_MAIN (COL3 varchar2, COL4 VARCHAR2) 按结果返回自我
      3 开始
      4 SELF.COL3 := nvl(COL3,'NA');
      5 SELF.COL4 := nvl(COL4,NULL);
      6 返回;
      7 结束;
      8 结束;
      9 /

    创建的类型主体。

    SQL> 创建表 TAB_MAIN (
      2 个密钥号码,
      3 COLTEST VARCHAR2(100),
      4 COLNEW TYPE_MAIN)
      5 /

    表已创建。

    SQL> 插入 TAB_MAIN(PKEY) 值(1)
      2 /

    创建了 1 行。

    SQL> INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW) 值(1,'TESTCOL',TYPE_MAIN('1','2',NULL,NULL))
      2 /

    创建了 1 行。

    SQL> INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW) 值(1,'TESTCOL2',TYPE_MAIN('1',NULL,NULL,NULL))
      2 /

    创建了 1 行。

    SQL> SELECT * FROM TAB_MAIN
      2 /

          PKEY COLEST COLNEW(COL1、COL2、COL3、COL4)
    ---------- ---------- ------------------ ----------
             1
             1 TESTCOL TYPE_MAIN(1, '2', NULL, NULL)
             1 TESTCOL2 TYPE_MAIN(1,空,空,空)

4

1 回答 1

5

在您的第二个代码块中,您没有调用只有两个参数的构造函数。传递一个空参数并不意味着您使用另一个构造函数,您正在使用四个参数调用(默认)构造函数,其中两个恰好是故意为空的。你正在有效地做:

TYPE_MAIN(col1 => '1', col2 => NULL, col3 => NULL, col4 => NULL)

不是

TYPE_MAIN(col3 => '1', col4 => NULL)

所以这有效:

INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW) VALUES(1,'TESTCOL2',TYPE_MAIN('3','4'))
/

...

      PKEY COLTEST         COLNEW                                           
---------- --------------- --------------------------------------------------
         1                                                                    
         1 TESTCOL         TYPE_MAIN(1,'2',NULL,NULL)           
         1 TESTCOL2        TYPE_MAIN(1,NULL,NULL,NULL)          
         1 TESTCOL2        TYPE_MAIN(NULL,NULL,'3','4')         

要使默认值按我认为您在第一个代码块中的意图工作,请将它们设置在构造函数参数中,而不是在构造函数的主体中:

CREATE OR REPLACE TYPE TYPE_MAIN
UNDER TYPE_SUB
(
COL3 varchar2(10),
COL4 VARCHAR2(10),
CONSTRUCTOR FUNCTION TYPE_MAIN(COL1 number default 123,
  COL2 VARCHAR2 default 'NA',
  COL3 varchar2 default 'NA',
  COL4 VARCHAR2 default null) RETURN SELF AS RESULT)
NOT FINAL
/

CREATE OR REPLACE TYPE BODY TYPE_MAIN  IS
CONSTRUCTOR FUNCTION TYPE_MAIN (COL1 number default 123,
  COL2 VARCHAR2 default 'NA',
  COL3 varchar2 default 'NA',
  COL4 VARCHAR2 default null) RETURN SELF AS RESULT IS
BEGIN
 SELF.COL1 := COL1;
 SELF.COL2 := COL2;
 SELF.COL3 := COL3;
 SELF.COL4 := COL4;
RETURN;
end;
END;
/

然后,当只传递一个参数时(或者任何时候你没有传递它们全部,或者你想要从 开始的顺序覆盖的前几个col1)你需要命名它,而不是传递null给其他参数,因为那样会只覆盖默认值。

INSERT INTO TAB_MAIN(PKEY) VALUES(1)
/

INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW)
VALUES(1,'TESTCOL',TYPE_MAIN(1,'2'))
/

INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW)
VALUES(1,'TESTCOL2',TYPE_MAIN(1))
/

INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW)
VALUES(1,'TESTCOL3',TYPE_MAIN(col3 => '3'))
/

INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW)
VALUES(1,'TESTCOL4',TYPE_MAIN(col4 => '4'))
/

      PKEY COLTEST         COLNEW                                           
---------- --------------- --------------------------------------------------
         1                                                                    
         1 TESTCOL         TYPE_MAIN(1,'2','NA',NULL)           
         1 TESTCOL2        TYPE_MAIN(1,'NA','NA',NULL)          
         1 TESTCOL3        TYPE_MAIN(123,'NA','3',NULL)         
         1 TESTCOL4        TYPE_MAIN(123,'NA','NA','4')         

要同时传递两者col3col4您仍然需要命名参数,否则它将假定您从以下位置开始col1

INSERT INTO TAB_MAIN(PKEY,COLTEST,COLNEW)
VALUES(1,'TESTCOL5',TYPE_MAIN(col3 => '3', col4 => '4'))
/

      PKEY COLTEST         COLNEW                                           
---------- --------------- --------------------------------------------------
         1                                                                    
         1 TESTCOL         TYPE_MAIN(1,'2','NA',NULL)           
         1 TESTCOL2        TYPE_MAIN(1,'NA','NA',NULL)          
         1 TESTCOL3        TYPE_MAIN(123,'NA','3',NULL)         
         1 TESTCOL4        TYPE_MAIN(123,'NA','NA','4')         
         1 TESTCOL5        TYPE_MAIN(123,'NA','3','4')          
于 2013-07-30T07:46:22.223 回答