Search code examples
sqloracle-databaseuser-defined-types

How to find if a value exists within a VARRAY


I've created a VARRAY within a table (below) I would like to query whether or not a Title has a particular theme, eg. Show 'Action' games. I'm not to sure how to go about this...

CREATE OR REPLACE TYPE Theme_Game AS OBJECT
(Theme VARCHAR(20));
/ 
CREATE OR REPLACE TYPE Theme_Type AS VARRAY(3) OF Theme_Game;
/
CREATE OR REPLACE TYPE Game_Type AS OBJECT
(Title VARCHAR2(50),
GameTheme Theme_Type);
/
CREATE TABLE Game_Table of Game_Type
/
INSERT INTO Game_Table
VALUES('Star Wars' ,(Theme_Type(Theme_Game('Action'), Theme_Game('FPS'))))
/

Solution

  • You need to expose the nested table in the FROM clause using the table() function. You can then reference attributes of the collection:

    SQL> select g.title
      2  from game_table g
      3       , table(g.gametheme) gt
      4  where gt.theme = 'Action';
    
    TITLE
    --------------------------------------------------
    Star Wars
    
    SQL> 
    

    "what if I then needed to retrieve rows with multiple Themes i.e Action, FPS?"

    Apologies for the clunky solution but I need to go to work now. I may post a more elegant solution later.

    SQL> select * from game_table
      2  /
    
    TITLE
    --------------------------------------------------
    GAMETHEME(THEME)
    --------------------------------------------------------------------------------
    Star Wars
    THEME_TYPE(THEME_GAME('Action'), THEME_GAME('FPS'))
    
    Uncharted 3
    THEME_TYPE(THEME_GAME('Action'), THEME_GAME('Puzzle'))
    
    Commander Cody
    THEME_TYPE(THEME_GAME('Fun'), THEME_GAME('Puzzle'))
    
    
    SQL> select g.title
      2  from game_table g
      3       , table(g.gametheme) gt
      4       , table(g.gametheme) gt1
      5  where gt.theme = 'Action'
      6  and gt1.theme = 'FPS' ;
    
    TITLE
    --------------------------------------------------
    Star Wars
    
    SQL> 
    

    This alternative approach won't work with your current type because VARRAY does not support member of. But it would work if the collection was a Nested Table.

     select g.title
      from game_table g
      where  'Action' member of g.gametheme
      and 'FPS' member of g.gametheme