定义一种方法,通过从其他表中引用的字段对记录进行分组
Define a method to group records by a field referenced from other tables
我设计了一个Oracle数据库如下。我的问题是,如何在BodyModel_TYPE中定义一个函数来显示没有。每个车身模型中的单层巴士,而该功能必须接受特定的车身模型,如 input/parameter.
Diagram for the following database schema
我编码的方法是这样的:
ALTER TYPE BodyModel_TYPE
ADD MEMBER FUNCTION cal_single_deck_bus RETURN int
CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
MEMBER FUNCTION cal_single_deck_bus RETURN int IS
N int;
BEGIN
SELECT COUNT(t.BUSID) INTO N FROM SINGLEDECKBUS_TABLE T WHERE DEREF(t.BODYMODEL) = self;
RETURN N;
END cal_single_deck_bus;
END;
/
它没有输入,但返回的结果不是预期的。完整的sql代码如下:
-- Engine Model
create or replace type EngineModel_TYPE as object
(EngineModelID int,
EngineDescription varchar2(45),
EngineType varchar2(25),
EngineCapacity int);
/
create table EngineModel_TABLE of EngineModel_TYPE;
alter table EngineModel_TABLE
add constraint EngineModelID_PK primary key (EngineModelID);
-- Body Model
create or replace type BodyModel_TYPE as object
(ModelID int,
ModelName varchar2(45),
FloorType varchar2(5),
Manufacturer varchar2(45),
Length number(8,2),
Width number(8,2),
NoOfAxles int);
/
create table BodyModel_TABLE of BodyModel_TYPE;
alter table BodyModel_TABLE
add constraint BodyModelID_PK primary key (ModelID);
-- Bus
create or replace type Bus_TYPE as object
(BusID int,
RegistrationNo VARCHAR2(10),
RegistrationExpireDate date,
EngineModel REF EngineModel_TYPE,
BodyModel REF BodyModel_TYPE) NOT FINAL;
/
-- Single Decker Bus
CREATE OR REPLACE TYPE SingleDeckBus_type UNDER Bus_type
(NoOfDoors INT,
SeatingCapacity int,
StandingCapacity int);
/
CREATE TABLE SingleDeckBus_table OF SingleDeckBus_type;
ALTER TABLE SingleDeckBus_table
ADD CONSTRAINT SingleDeckBus_BusId_pk PRIMARY KEY (BusId);
-- Double Decker bus
CREATE OR REPLACE TYPE DoubleDeckBus_type UNDER Bus_type
(LowerDeckSeatingCapacity int,
LowerDeckStandingCapacity int,
LuggageCapacity number(8,2),
UpperDeckSeatingCapacity int);
/
CREATE TABLE DoubleDeckBus_table OF DoubleDeckBus_type;
ALTER TABLE DoubleDeckBus_table
ADD CONSTRAINT DoubleDeckBus_BusId_pk PRIMARY KEY (BusId);
-- Accessory
CREATE OR REPLACE TYPE Accessory_type AS OBJECT
(AccessoryId INT,
AccessoryName VARCHAR2(45),
AccessoryDescription VARCHAR2(45),
InstallDate DATE,
SingleDeckBus REF SingleDeckBus_type,
DoubleDeckBus REF DoubleDeckBus_type);
/
CREATE TABLE Accessory_table OF Accessory_type;
ALTER TABLE Accessory_table
ADD CONSTRAINT AccessoryId_pk PRIMARY KEY(AccessoryId);
-- 2. Insert record statements (3 records for each table that support testing of your queries)
insert into EngineModel_TABLE values
(1, 'Description 1', 'Type 1', 10);
insert into EngineModel_TABLE values
(2, 'Description 2', 'Type 2', 20);
insert into EngineModel_TABLE values
(3, 'Description 3', 'Type 3', 30);
insert into BodyModel_TABLE values
(1, 'name 1', 'Type1', 'manufac1', 10.1, 5.1, 10);
insert into BodyModel_TABLE values
(2, 'name 2', 'Type2', 'manufac2', 10.2, 5.2, 20);
insert into BodyModel_TABLE values
(3, 'name 3', 'Type3', 'manufac3', 10.3, 5.3, 30);
insert into SingleDeckBus_table
SELECT 1, 'SA01', '1-Jan-2020', REF(E), REF(B), 1, 20, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 1 AND B.MODELID = 1;
insert into SingleDeckBus_table
SELECT 2, 'SA02', '2-Jan-2020', REF(E), REF(B), 2, 25, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 2 AND B.MODELID = 2;
insert into SingleDeckBus_table
SELECT 3, 'SA03', '3-Jan-2020', REF(E), REF(B), 3, 30, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 3 AND B.MODELID = 3;
insert into SingleDeckBus_table
SELECT 55, 'SA03', '3-Jan-2020', REF(E), REF(B), 3, 30, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 3 AND B.MODELID = 3;
insert into DOUBLEDECKBUS_TABLE
SELECT 4, 'SA04', '4-Jan-2020', REF(E), REF(B), 20, 10, 30.15, 20 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 1 AND B.MODELID = 1;
insert into DOUBLEDECKBUS_TABLE
SELECT 5, 'SA05', '5-Jan-2020', REF(E), REF(B), 25, 10, 35.15, 25 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 2 AND B.MODELID = 2;
insert into DOUBLEDECKBUS_TABLE
SELECT 6, 'SA06', '6-Jan-2020', REF(E), REF(B), 30, 10, 40.15, 30 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 3 AND B.MODELID = 3;
insert into ACCESSORY_TABLE
SELECT 1, 'Acc1', 'AccDesc1', '1-Mar-2017', REF(S), REF(D) from SINGLEDECKBUS_TABLE S, DOUBLEDECKBUS_TABLE D
where s.BUSID = 1 AND d.BUSID = 4;
insert into ACCESSORY_TABLE
SELECT 2, 'Acc2', 'AccDesc2', '2-Mar-2017', REF(S), REF(D) from SINGLEDECKBUS_TABLE S, DOUBLEDECKBUS_TABLE D
where s.BUSID = 2 AND d.BUSID = 5;
insert into ACCESSORY_TABLE
SELECT 3, 'Acc3', 'AccDesc3', '3-Mar-2017', REF(S), REF(D) from SINGLEDECKBUS_TABLE S, DOUBLEDECKBUS_TABLE D
where s.BUSID = 3 AND d.BUSID = 6;
-- 3. Create a method in the appropriate class to display how many single deck buses in each body model.
ALTER TYPE BodyModel_TYPE
ADD MEMBER FUNCTION cal_single_deck_bus RETURN int
CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
MEMBER FUNCTION cal_single_deck_bus RETURN int IS
N int;
BEGIN
SELECT COUNT(t.BUSID) INTO N FROM SINGLEDECKBUS_TABLE T WHERE DEREF(t.BODYMODEL) = self;
RETURN N;
END cal_single_deck_bus;
END;
/
commit;
根据您显示的插入内容,您现有的方法函数似乎得到了正确的结果:
SELECT b.ModelID, b.ModelName, b.cal_single_deck_bus() AS single_deck_bus_count
FROM BodyModel_TABLE b;
MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- -------------------- ---------------------
1 name 1 1
2 name 2 1
3 name 3 2
这似乎是一种合理的方法。但是,如果您的作业指定该函数必须接受 body 模型——我不认为你的问题 3 的措辞是这样,除非你遗漏了其中的一部分——那么你可能想要 a static function, 不是成员函数:
-- remove your existing member function first
ALTER TYPE BodyModel_TYPE
DROP MEMBER FUNCTION cal_single_deck_bus RETURN int
CASCADE;
ALTER TYPE BodyModel_TYPE
ADD STATIC FUNCTION cal_single_deck_bus (p_bodymodel REF BodyModel_TYPE)
RETURN int CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
STATIC FUNCTION cal_single_deck_bus (p_bodymodel REF BodyModel_TYPE)
RETURN int IS
N int;
BEGIN
SELECT COUNT(t.BUSID) INTO N
FROM SINGLEDECKBUS_TABLE T
WHERE t.BODYMODEL = p_bodymodel;
RETURN N;
END cal_single_deck_bus;
END;
/
然后您可以将任何相关表的特定引用传递给静态函数,或者获取所有 body 类型的计数,例如:
SELECT b.ModelID, b.ModelName,
BodyModel_TYPE.cal_single_deck_bus(ref(b)) AS single_deck_bus_count
FROM BodyModel_TABLE b;
MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- -------------------- ---------------------
1 name 1 1
2 name 2 1
3 name 3 2
BodyModel_TYPE.cal_single_deck_bus(ref(b))
是一个静态调用,因为它针对的是类型本身而不是该类型的实例;与之前的 b.cal_single_deck_bus()
调用进行比较。在这两种情况下,b
都是 object 类型的实例。
您也可以从其他地方获取参考,例如以一种相当做作的方式:
SELECT d.BusID, d.UpperDeckSeatingCapacity,
deref(d.BodyModel).ModelID as ModelID,
deref(d.BodyModel).ModelName as ModelName,
BodyModel_TYPE.cal_single_deck_bus(d.BodyModel) AS single_deck_bus_count
FROM DoubleDeckBus_TABLE d
WHERE d.RegistrationNo = 'SA06';
BUSID UPPERDECKSEATINGCAPACITY MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- ------------------------ ---------- -------------------- ---------------------
6 30 3 name 3 2
如果您想传入模型 ID 而不是 object 引用,则需要在静态函数中将 body 模型和 single-decker 总线表连接在一起:
-- remove your existing member function first
ALTER TYPE BodyModel_TYPE
DROP STATIC FUNCTION cal_single_deck_bus (p_bodymodel REF BodyModel_TYPE) RETURN int
CASCADE;
ALTER TYPE BodyModel_TYPE
ADD STATIC FUNCTION cal_single_deck_bus (p_modelid int)
RETURN int CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
STATIC FUNCTION cal_single_deck_bus (p_modelid int)
RETURN int IS
N int;
BEGIN
SELECT COUNT(sd.BUSID) INTO N
FROM BODYMODEL_TABLE b
JOIN SINGLEDECKBUS_TABLE sd
ON sd.BODYMODEL = REF(b)
WHERE b.ModelID = p_modelid;
RETURN N;
END cal_single_deck_bus;
END;
/
那么你可以这样称呼它:
SELECT BodyModel_TYPE.cal_single_deck_bus(3) AS single_deck_bus_count FROM dual;
SINGLE_DECK_BUS_COUNT
---------------------
2
或者如果您还想显示相关信息:
SELECT b.ModelID, b.ModelName,
BodyModel_TYPE.cal_single_deck_bus(b.ModelID) AS single_deck_bus_count
FROM BodyModel_TABLE b;
MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- -------------------- ---------------------
1 name 1 1
2 name 2 1
3 name 3 2
我设计了一个Oracle数据库如下。我的问题是,如何在BodyModel_TYPE中定义一个函数来显示没有。每个车身模型中的单层巴士,而该功能必须接受特定的车身模型,如 input/parameter.
Diagram for the following database schema
我编码的方法是这样的:
ALTER TYPE BodyModel_TYPE
ADD MEMBER FUNCTION cal_single_deck_bus RETURN int
CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
MEMBER FUNCTION cal_single_deck_bus RETURN int IS
N int;
BEGIN
SELECT COUNT(t.BUSID) INTO N FROM SINGLEDECKBUS_TABLE T WHERE DEREF(t.BODYMODEL) = self;
RETURN N;
END cal_single_deck_bus;
END;
/
它没有输入,但返回的结果不是预期的。完整的sql代码如下:
-- Engine Model
create or replace type EngineModel_TYPE as object
(EngineModelID int,
EngineDescription varchar2(45),
EngineType varchar2(25),
EngineCapacity int);
/
create table EngineModel_TABLE of EngineModel_TYPE;
alter table EngineModel_TABLE
add constraint EngineModelID_PK primary key (EngineModelID);
-- Body Model
create or replace type BodyModel_TYPE as object
(ModelID int,
ModelName varchar2(45),
FloorType varchar2(5),
Manufacturer varchar2(45),
Length number(8,2),
Width number(8,2),
NoOfAxles int);
/
create table BodyModel_TABLE of BodyModel_TYPE;
alter table BodyModel_TABLE
add constraint BodyModelID_PK primary key (ModelID);
-- Bus
create or replace type Bus_TYPE as object
(BusID int,
RegistrationNo VARCHAR2(10),
RegistrationExpireDate date,
EngineModel REF EngineModel_TYPE,
BodyModel REF BodyModel_TYPE) NOT FINAL;
/
-- Single Decker Bus
CREATE OR REPLACE TYPE SingleDeckBus_type UNDER Bus_type
(NoOfDoors INT,
SeatingCapacity int,
StandingCapacity int);
/
CREATE TABLE SingleDeckBus_table OF SingleDeckBus_type;
ALTER TABLE SingleDeckBus_table
ADD CONSTRAINT SingleDeckBus_BusId_pk PRIMARY KEY (BusId);
-- Double Decker bus
CREATE OR REPLACE TYPE DoubleDeckBus_type UNDER Bus_type
(LowerDeckSeatingCapacity int,
LowerDeckStandingCapacity int,
LuggageCapacity number(8,2),
UpperDeckSeatingCapacity int);
/
CREATE TABLE DoubleDeckBus_table OF DoubleDeckBus_type;
ALTER TABLE DoubleDeckBus_table
ADD CONSTRAINT DoubleDeckBus_BusId_pk PRIMARY KEY (BusId);
-- Accessory
CREATE OR REPLACE TYPE Accessory_type AS OBJECT
(AccessoryId INT,
AccessoryName VARCHAR2(45),
AccessoryDescription VARCHAR2(45),
InstallDate DATE,
SingleDeckBus REF SingleDeckBus_type,
DoubleDeckBus REF DoubleDeckBus_type);
/
CREATE TABLE Accessory_table OF Accessory_type;
ALTER TABLE Accessory_table
ADD CONSTRAINT AccessoryId_pk PRIMARY KEY(AccessoryId);
-- 2. Insert record statements (3 records for each table that support testing of your queries)
insert into EngineModel_TABLE values
(1, 'Description 1', 'Type 1', 10);
insert into EngineModel_TABLE values
(2, 'Description 2', 'Type 2', 20);
insert into EngineModel_TABLE values
(3, 'Description 3', 'Type 3', 30);
insert into BodyModel_TABLE values
(1, 'name 1', 'Type1', 'manufac1', 10.1, 5.1, 10);
insert into BodyModel_TABLE values
(2, 'name 2', 'Type2', 'manufac2', 10.2, 5.2, 20);
insert into BodyModel_TABLE values
(3, 'name 3', 'Type3', 'manufac3', 10.3, 5.3, 30);
insert into SingleDeckBus_table
SELECT 1, 'SA01', '1-Jan-2020', REF(E), REF(B), 1, 20, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 1 AND B.MODELID = 1;
insert into SingleDeckBus_table
SELECT 2, 'SA02', '2-Jan-2020', REF(E), REF(B), 2, 25, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 2 AND B.MODELID = 2;
insert into SingleDeckBus_table
SELECT 3, 'SA03', '3-Jan-2020', REF(E), REF(B), 3, 30, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 3 AND B.MODELID = 3;
insert into SingleDeckBus_table
SELECT 55, 'SA03', '3-Jan-2020', REF(E), REF(B), 3, 30, 10 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 3 AND B.MODELID = 3;
insert into DOUBLEDECKBUS_TABLE
SELECT 4, 'SA04', '4-Jan-2020', REF(E), REF(B), 20, 10, 30.15, 20 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 1 AND B.MODELID = 1;
insert into DOUBLEDECKBUS_TABLE
SELECT 5, 'SA05', '5-Jan-2020', REF(E), REF(B), 25, 10, 35.15, 25 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 2 AND B.MODELID = 2;
insert into DOUBLEDECKBUS_TABLE
SELECT 6, 'SA06', '6-Jan-2020', REF(E), REF(B), 30, 10, 40.15, 30 from ENGINEMODEL_TABLE E, BODYMODEL_TABLE B
where E.ENGINEMODELID = 3 AND B.MODELID = 3;
insert into ACCESSORY_TABLE
SELECT 1, 'Acc1', 'AccDesc1', '1-Mar-2017', REF(S), REF(D) from SINGLEDECKBUS_TABLE S, DOUBLEDECKBUS_TABLE D
where s.BUSID = 1 AND d.BUSID = 4;
insert into ACCESSORY_TABLE
SELECT 2, 'Acc2', 'AccDesc2', '2-Mar-2017', REF(S), REF(D) from SINGLEDECKBUS_TABLE S, DOUBLEDECKBUS_TABLE D
where s.BUSID = 2 AND d.BUSID = 5;
insert into ACCESSORY_TABLE
SELECT 3, 'Acc3', 'AccDesc3', '3-Mar-2017', REF(S), REF(D) from SINGLEDECKBUS_TABLE S, DOUBLEDECKBUS_TABLE D
where s.BUSID = 3 AND d.BUSID = 6;
-- 3. Create a method in the appropriate class to display how many single deck buses in each body model.
ALTER TYPE BodyModel_TYPE
ADD MEMBER FUNCTION cal_single_deck_bus RETURN int
CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
MEMBER FUNCTION cal_single_deck_bus RETURN int IS
N int;
BEGIN
SELECT COUNT(t.BUSID) INTO N FROM SINGLEDECKBUS_TABLE T WHERE DEREF(t.BODYMODEL) = self;
RETURN N;
END cal_single_deck_bus;
END;
/
commit;
根据您显示的插入内容,您现有的方法函数似乎得到了正确的结果:
SELECT b.ModelID, b.ModelName, b.cal_single_deck_bus() AS single_deck_bus_count
FROM BodyModel_TABLE b;
MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- -------------------- ---------------------
1 name 1 1
2 name 2 1
3 name 3 2
这似乎是一种合理的方法。但是,如果您的作业指定该函数必须接受 body 模型——我不认为你的问题 3 的措辞是这样,除非你遗漏了其中的一部分——那么你可能想要 a static function, 不是成员函数:
-- remove your existing member function first
ALTER TYPE BodyModel_TYPE
DROP MEMBER FUNCTION cal_single_deck_bus RETURN int
CASCADE;
ALTER TYPE BodyModel_TYPE
ADD STATIC FUNCTION cal_single_deck_bus (p_bodymodel REF BodyModel_TYPE)
RETURN int CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
STATIC FUNCTION cal_single_deck_bus (p_bodymodel REF BodyModel_TYPE)
RETURN int IS
N int;
BEGIN
SELECT COUNT(t.BUSID) INTO N
FROM SINGLEDECKBUS_TABLE T
WHERE t.BODYMODEL = p_bodymodel;
RETURN N;
END cal_single_deck_bus;
END;
/
然后您可以将任何相关表的特定引用传递给静态函数,或者获取所有 body 类型的计数,例如:
SELECT b.ModelID, b.ModelName,
BodyModel_TYPE.cal_single_deck_bus(ref(b)) AS single_deck_bus_count
FROM BodyModel_TABLE b;
MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- -------------------- ---------------------
1 name 1 1
2 name 2 1
3 name 3 2
BodyModel_TYPE.cal_single_deck_bus(ref(b))
是一个静态调用,因为它针对的是类型本身而不是该类型的实例;与之前的 b.cal_single_deck_bus()
调用进行比较。在这两种情况下,b
都是 object 类型的实例。
您也可以从其他地方获取参考,例如以一种相当做作的方式:
SELECT d.BusID, d.UpperDeckSeatingCapacity,
deref(d.BodyModel).ModelID as ModelID,
deref(d.BodyModel).ModelName as ModelName,
BodyModel_TYPE.cal_single_deck_bus(d.BodyModel) AS single_deck_bus_count
FROM DoubleDeckBus_TABLE d
WHERE d.RegistrationNo = 'SA06';
BUSID UPPERDECKSEATINGCAPACITY MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- ------------------------ ---------- -------------------- ---------------------
6 30 3 name 3 2
如果您想传入模型 ID 而不是 object 引用,则需要在静态函数中将 body 模型和 single-decker 总线表连接在一起:
-- remove your existing member function first
ALTER TYPE BodyModel_TYPE
DROP STATIC FUNCTION cal_single_deck_bus (p_bodymodel REF BodyModel_TYPE) RETURN int
CASCADE;
ALTER TYPE BodyModel_TYPE
ADD STATIC FUNCTION cal_single_deck_bus (p_modelid int)
RETURN int CASCADE;
CREATE OR REPLACE TYPE BODY BodyModel_TYPE AS
STATIC FUNCTION cal_single_deck_bus (p_modelid int)
RETURN int IS
N int;
BEGIN
SELECT COUNT(sd.BUSID) INTO N
FROM BODYMODEL_TABLE b
JOIN SINGLEDECKBUS_TABLE sd
ON sd.BODYMODEL = REF(b)
WHERE b.ModelID = p_modelid;
RETURN N;
END cal_single_deck_bus;
END;
/
那么你可以这样称呼它:
SELECT BodyModel_TYPE.cal_single_deck_bus(3) AS single_deck_bus_count FROM dual;
SINGLE_DECK_BUS_COUNT
---------------------
2
或者如果您还想显示相关信息:
SELECT b.ModelID, b.ModelName,
BodyModel_TYPE.cal_single_deck_bus(b.ModelID) AS single_deck_bus_count
FROM BodyModel_TABLE b;
MODELID MODELNAME SINGLE_DECK_BUS_COUNT
---------- -------------------- ---------------------
1 name 1 1
2 name 2 1
3 name 3 2