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 abou
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
For multiple themes you could do something like
select g.Title
from game_table g, table(g.gameTheme) t
where t.Theme in ('FPS','Action')
group by g.Title having count(0) = 2;
This could also allow you to do things like get titles with exactly n matches, at least n matches, at most n matches...
You can use a collection and then compare multiple items using the SUBMULTISET
operator:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE OR REPLACE TYPE Theme_Game AS OBJECT
(Theme VARCHAR(20));
/
CREATE OR REPLACE TYPE Theme_Type AS TABLE OF Theme_Game;
/
CREATE OR REPLACE TYPE Game_Type AS OBJECT(
Title VARCHAR2(50),
GameTheme Theme_Type
);
/
CREATE TABLE Game_Table of Game_Type
NESTED TABLE GameTheme STORE AS GameTheme_Tab
/
INSERT INTO Game_Table
VALUES('Star Wars' ,(Theme_Type(Theme_Game('Action'), Theme_Game('FPS'))))
/
Query 1:
SELECT *
FROM game_table
WHERE Theme_Type(Theme_Game('Action'), Theme_Game('FPS'))
SUBMULTISET OF GameTheme
Results:
| TITLE | GAMETHEME |
|-----------|-------------------------------------------------------|
| Star Wars | oracle.sql.STRUCT@67e8dc0f,oracle.sql.STRUCT@795b6d4c |
However, why are you using the Theme_Game
object when it only has a single VARCHAR2
attribute? You can just use a VARRAY(3) OF VARCHAR2(20)
or TABLE OF VARCHAR2(20)
without the intermediate object:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE OR REPLACE TYPE Varchar20List AS TABLE OF VARCHAR2(20);
/
CREATE OR REPLACE TYPE Game_Type AS OBJECT(
Title VARCHAR2(50),
GameTheme Varchar20List
);
/
CREATE TABLE Game_Table of Game_Type
NESTED TABLE GameTheme STORE AS GameTheme_Tab
/
INSERT INTO Game_Table
VALUES('Star Wars' , Varchar20List('Action', 'FPS'))
/
Query 1:
SELECT *
FROM game_table
WHERE Varchar20List('Action','FPS')
SUBMULTISET OF GameTheme
Results:
| TITLE | GAMETHEME |
|-----------|------------|
| Star Wars | Action,FPS |
If you want to do it with VARRAY
s then:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE OR REPLACE TYPE Varchar20List AS VARRAY(3) OF VARCHAR2(20);
/
CREATE OR REPLACE TYPE Game_Type AS OBJECT(
Title VARCHAR2(50),
GameTheme Varchar20List
);
/
CREATE TABLE Game_Table of Game_Type
/
INSERT INTO Game_Table
VALUES('Star Wars' , Varchar20List('Action', 'FPS'))
/
Query 1:
SELECT *
FROM game_table g
WHERE 2 >= ( SELECT COUNT(*)
FROM TABLE( g.GameTheme ) a
INNER JOIN
TABLE( Varchar20List( 'Action', 'FPS' ) ) b
ON ( a.COLUMN_VALUE = b.COLUMN_VALUE )
)
Results:
| TITLE | GAMETHEME |
|-----------|------------|
| Star Wars | Action,FPS |
or:
Query 2:
SELECT *
FROM game_table g
WHERE 2 >= ( SELECT COUNT(*)
FROM TABLE( g.GameTheme ) a
WHERE a.COLUMN_VALUE IN ( 'Action', 'FPS' )
)
Results:
| TITLE | GAMETHEME |
|-----------|------------|
| Star Wars | Action,FPS |