选择与表中所有项匹配的ID

时间:2017-01-25 22:57:48

标签: sql oracle stored-procedures plsql

所以我有一个名为 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 一样工作)。

编辑1:

如果可能,我希望收到更改程序的答案,而不是表格,尽管欢迎所有答案!

编辑2:

上面的代码是一个简化,这是完整的代码:

对象定义:

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;
/

1 个答案:

答案 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.