所以我有一个名为 Mroom 的表,它看起来像这样:
CREATE Mroom(ID_ROOM NUMBER(3), CHAR_NAME NVARCHAR2(30), CHAR_VALUE NUMBER(20));
表格的内容如下:
1;冷气机; 1
1;池; 2
2;池; 1
这意味着 ID 1的房间有1个空调和2个游泳池。 ID 2的房间有一个游泳池。 我还创建了一个数据类型表,我称之为 c_chars :
CREATE OR REPLACE TYPE c_chars FORCE IS OBJECT (CHAR VARCHAR2(20), VALUE NUMBER(30));
/
CREATE OR REPLACE TYPE tab_chars FORCE IS TABLE OF c_chars;
/
我需要知道,例如,是否有任何房间至少有一个空调和一个游泳池。我目前的代码:
CREATE OR REPLACE PROCEDURE thisRoomOK(v_carateristicas IN tab_chars, lista OUT SYS_REFCURSOR)
IS BEGIN
OPEN lista FOR SELECT MRoom.ID_ROOM
FROM Mroom, TABLE(v_carateristicas) v_carateristicas
WHERE Mroom.CHAR_NAME = v_carateristicas.CHAR
AND Mroom.VALUE >= v_carateristicas.VALUE
GROUP BY Mroom.ID_ROOM
ORDER BY getSalas.Mroom.ID_ROOM;
END;
/
问题是如果我要求至少有一个空调和游泳池的房间。它将返回我的两个房间,因为rrom 2有一个游泳池(它的工作方式类似于 OR ,但我希望它像 AND 一样工作)。
如果可能,我希望收到更改程序的答案,而不是表格,尽管欢迎所有答案!
上面的代码是一个简化,这是完整的代码:
对象定义:
CREATE OR REPLACE TYPE c_valor FORCE IS OBJECT (CARATERISTICA VARCHAR2(20), VALOR NUMBER(30));
/
CREATE OR REPLACE TYPE tabc_valor FORCE IS TABLE OF c_valor;
/
步骤:
CREATE OR REPLACE PROCEDURE getSalas_Carateristicas(v_carateristicas IN tabc_valor, lista OUT SYS_REFCURSOR)
IS BEGIN
OPEN lista FOR SELECT getSalas.ID_SALA
FROM getSalas, TABLE(v_carateristicas) v_carateristicas
WHERE getSalas.NOME_CARATERISTICA = v_carateristicas.CARATERISTICA
AND getSalas.VALOR >= v_carateristicas.VALOR
GROUP BY getSalas.ID_SALA
ORDER BY getSalas.ID_SALA;
END;
/
根据@ XING的消化程序改变了程序
CREATE OR REPLACE PROCEDURE getSalas_Carateristicas(v_carateristicas IN tabc_valor, lista OUT SYS_REFCURSOR)
IS BEGIN
OPEN lista FOR SELECT getSalas.ID_SALA
FROM getSalas
INNER JOIN TABLE(v_carateristicas) v_carateristicas ON getSalas.NOME_CARATERISTICA = v_carateristicas.CARATERISTICA
AND getSalas.VALOR >= v_carateristicas.VALOR
GROUP BY getSalas.ID_SALA
ORDER BY getSalas.ID_SALA;
END;
/
答案 0 :(得分:0)
我想问题就在于你要求房间的方式。请参阅下面的内联演示和说明。
PROC:
CREATE OR REPLACE TYPE T541682.c_chars FORCE IS OBJECT (v_CHAR VARCHAR2(20), v_VALUE NUMBER(30));
/
CREATE OR REPLACE TYPE T541682.tab_chars FORCE IS TABLE OF c_chars;
/
CREATE OR REPLACE PROCEDURE T541682.thisRoomOK (
v_carateristicas IN tab_chars,
lista OUT SYS_REFCURSOR)
IS
BEGIN
OPEN lista FOR
SELECT MRoom.ID_ROOM
FROM Mroom
inner join TABLE (v_carateristicas) v_carateristicas
ON Mroom.CHAR_NAME = v_carateristicas.v_CHAR
AND Mroom.CHAR_VALUE = v_carateristicas.v_VALUE
GROUP BY Mroom.ID_ROOM
ORDER BY Mroom.ID_ROOM;
END;
/
declare
var tab_chars :=tab_chars();
type var1 is table of MRoom.ID_ROOM%type index by pls_integer;
var_out var1;
x sys_refcursor;
begin
var.extend(3);
-- This is the way i populate my object for which i want to match with the table. Am sure you are passing all rows same as your table hence its getting the all the rows.
var(1) := c_chars('air-conditioner',1);
var(2) := c_chars('pool',2);
-- Must be populating the third row as well. And as per your query both rows wil be picked up if you populate the object .
--var(3) := c_chars('pool',1);
-- Calling your procedure
thisRoomOK(v_carateristicas => var,lista => x);
fetch x bulk collect into var_out ;
--- displaying number of room
for i in 1..var_out.count
loop
dbms_output.put_line('Room Number - '||var_out(i));
end loop;
---passing the sys_refcursor result to another procedure
proc1(var_out);
end;
输出:
SQL> /
Room Number - 1
PL/SQL procedure successfully completed.