Oracle Databaseでは、すべてのオブジェクト型に対してデフォルトのコンストラクタが自動的に提供されます。このコンストラクタを使用するには、コンストラクタに対するコールで、その型のすべての属性を引数として指定する必要があります。オブジェクトの新しいインスタンスが作成されると、その属性は引数リスト内の対応する値を取ります。このコンストラクタは、属性値コンストラクタと呼ばれます。SQL*Loaderでは、列オブジェクトのロード時に、デフォルトで属性値コンストラクタが使用されます。
1つ以上のユーザー定義コンストラクタを作成することによって、属性値コンストラクタを上書きできます。ユーザー定義コンストラクタを作成する場合、オブジェクトの新しいインスタンスが作成されると、常に、ユーザー定義論理を実行する型本体を指定する必要があります。ユーザー定義コンストラクタの引数リストは、属性値コンストラクタと同じ場合もありますが、型本体で実装される論理は異なります。
ユーザー定義コンストラクタのファンクションの引数リストが属性値コンストラクタの引数リストと一致する場合、従来型パスとダイレクト・パスではSQL*Loaderの動作が異なります。従来型パス・モードでは、ユーザー定義コンストラクタがコールされます。ダイレクト・パス・モードでは、属性値コンストラクタがコールされます。例11-7に、この違いを示します。
例11-7 一致するコンストラクタを使用した列オブジェクトのロード
オブジェクトの型定義
CREATE TYPE person_type AS OBJECT
(name VARCHAR(30),
ssn NUMBER(9)) not final;
CREATE TYPE employee_type UNDER person_type
(empid NUMBER(5),
-- User-defined constructor that looks like an attribute-value constructor
CONSTRUCTOR FUNCTION
employee_type (name VARCHAR2, ssn NUMBER, empid NUMBER)
RETURN SELF AS RESULT);
CREATE TYPE BODY employee_type AS
CONSTRUCTOR FUNCTION
employee_type (name VARCHAR2, ssn NUMBER, empid NUMBER)
RETURN SELF AS RESULT AS
--User-defined constructor makes sure that the name attribute is uppercase.
BEGIN
SELF.name := UPPER(name);
SELF.ssn := ssn;
SELF.empid := empid;
RETURN;
END;
CREATE TABLE personnel
(deptno NUMBER(3),
deptname VARCHAR(30),
employee employee_type);
制御ファイルの内容
LOAD DATA
INFILE *
REPLACE
INTO TABLE personnel
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(deptno INTEGER EXTERNAL(3),
deptname CHAR,
employee COLUMN OBJECT
(name CHAR,
ssn INTEGER EXTERNAL(9),
empid INTEGER EXTERNAL(5)))
BEGINDATA
1 101,Mathematics,Johny Q.,301189453,10249,
237,Physics,"Albert Einstein",128606590,10030,
注意:
例の左に付けた太字の数字は、次の注意事項と対応しています。
この制御ファイルが従来型パス・モードで実行された場合、名前フィールドのJohny Q.およびAlbert Einsteinは、両方とも大文字でロードされます。これは、従来型パス・モードではユーザー定義コンストラクタがコールされるためです。これに対し、この制御ファイルがダイレクト・パス・モードで実行された場合、名前フィールドは入力データに表示されているとおりにロードされます。これは、ダイレクト・パス・モードでは属性値コンストラクタがコールされるためです。
引数リストが属性値コンストラクタと一致しないユーザー定義コンストラクタの作成もできます。この場合は、従来型パス・モードおよびダイレクト・パス・モードの両方で、属性値コンストラクタがコールされます。例11-8に示す定義について考えてみます。
例11-8 一致しないコンストラクタを使用した列オブジェクトのロード
オブジェクトの型定義
CREATE SEQUENCE employee_ids
START WITH 1000
INCREMENT BY 1;
CREATE TYPE person_type AS OBJECT
(name VARCHAR(30),
ssn NUMBER(9)) not final;
CREATE TYPE employee_type UNDER person_type
(empid NUMBER(5),
-- User-defined constructor that does not look like an attribute-value
-- constructor
CONSTRUCTOR FUNCTION
employee_type (name VARCHAR2, ssn NUMBER)
RETURN SELF AS RESULT);
CREATE TYPE BODY employee_type AS
CONSTRUCTOR FUNCTION
employee_type (name VARCHAR2, ssn NUMBER)
RETURN SELF AS RESULT AS
-- This user-defined constructor makes sure that the name attribute is in
-- lowercase and assigns the employee identifier based on a sequence.
nextid NUMBER;
stmt VARCHAR2(64);
BEGIN
stmt := 'SELECT employee_ids.nextval FROM DUAL';
EXECUTE IMMEDIATE stmt INTO nextid;
SELF.name := LOWER(name);
SELF.ssn := ssn;
SELF.empid := nextid;
RETURN;
END;
CREATE TABLE personnel
(deptno NUMBER(3),
deptname VARCHAR(30),
employee employee_type);
例11-7で説明した制御ファイルがこれらの定義に従って使用された場合、名前フィールドは、入力データに表示されているとおりに(大文字と小文字の組合せで)ロードされます。これは、従来型パス・モードおよびダイレクト・パス・モードの両方で属性値コンストラクタがコールされるためです。
SQL式でユーザー定義コンストラクタを明示的に参照することによって、従来型パス・モードを使用してこの表をロードすることもできます。例11-9に、この方法を示します。
例11-9 コンストラクタが一致しない場合のSQLを使用した列オブジェクトのロード
制御ファイルの内容
LOAD DATA
INFILE *
REPLACE
INTO TABLE personnel
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(deptno INTEGER EXTERNAL(3),
deptname CHAR,
name BOUNDFILLER CHAR,
ssn BOUNDFILLER INTEGER EXTERNAL(9),
1 employee EXPRESSION "employee_type(:NAME, :SSN)")
BEGINDATA
1 101,Mathematics,Johny Q.,301189453,
237,Physics,"Albert Einstein",128606590,
注意:
例の左に付けた太字の数字は、次の注意事項と対応しています。
この制御ファイルが従来型パス・モードで実行された場合、名前フィールドのJohny Q.およびAlbert Einsteinは、両方とも大文字でロードされます。これは、従来型パス・モードではユーザー定義コンストラクタがコールされるためです。これに対し、この制御ファイルがダイレクト・パス・モードで実行された場合、名前フィールドは入力データに表示されているとおりにロードされます。これは、ダイレクト・パス・モードでは属性値コンストラクタがコールされるためです。
例11-9に示した制御ファイルがダイレクト・パス・モードで使用された場合は、次のエラーが通知されます。
SQL*Loader-951: Error calling once/load initialization ORA-26052: Unsupported type 121 for SQL expression on column EMPLOYEE.