How to find if a value exists within a VARRAY

后端 未结 3 1368
不思量自难忘°
不思量自难忘° 2020-12-22 00:35

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

相关标签:
3条回答
  • 2020-12-22 01:03

    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
    
    0 讨论(0)
  • 2020-12-22 01:15

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

    0 讨论(0)
  • 2020-12-22 01:19

    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 VARRAYs 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 |
    
    0 讨论(0)
提交回复
热议问题