Oracle PL/SQL Tutorial/Query Select/EXISTS

Материал из SQL эксперт
Перейти к: навигация, поиск

EXISTS and NOT EXISTS Versus IN and NOT IN

  1. EXISTS is different from IN.
  2. EXISTS just checks for the existence of rows, whereas IN checks actual values.
  3. EXISTS typically offers better performance than IN with subqueries.
  4. You should use EXISTS rather than IN wherever possible.
  5. When a list of values contains a null, NOT EXISTS returns true, but NOT IN returns false.



   <source lang="sql">

SQL> -- create demo table SQL> create table Employee(

 2    EMPNO         NUMBER(3),
 3    ENAME         VARCHAR2(15 BYTE),
 4    HIREDATE      DATE,
 5    ORIG_SALARY   NUMBER(6),
 6    CURR_SALARY   NUMBER(6),
 7    REGION        VARCHAR2(1 BYTE),
 8    MANAGER_ID    NUMBER(3)
 9  )
10  /

Table created. SQL> SQL> create table job (

 2    EMPNO         NUMBER(3),
 3    jobtitle      VARCHAR2(20 BYTE)
 4  )
 5  /

Table created. SQL> SQL> insert into job (EMPNO, Jobtitle) values (1,"Tester"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (2,"Accountant"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (3,"Developer"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (4,"COder"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (5,"Director"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (6,"Mediator"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (7,"Proffessor"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (8,"Programmer"); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (9,"Developer"); 1 row created. SQL> SQL> SQL> -- prepare data SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (1,      "Jason", to_date("19960725","YYYYMMDD"), 1234,              8767,         "E",    2)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (2,      "John",  to_date("19970715","YYYYMMDD"), 2341,              3456,         "W",    3)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (3,      "Joe",   to_date("19860125","YYYYMMDD"), 4321,              5654,         "E",    3)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (4,      "Tom",   to_date("20060913","YYYYMMDD"), 2413,              6787,         "W",    4)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (5,      "Jane",  to_date("20050417","YYYYMMDD"), 7654,              4345,         "E",    4)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (6,      "James", to_date("20040718","YYYYMMDD"), 5679,              6546,         "W",    5)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION, MANAGER_ID)

 2               values (7,      "Jodd",  to_date("20030720","YYYYMMDD"), 5438,              7658,         "E",    6)
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION)

 2               values (8,      "Joke",  to_date("20020101","YYYYMMDD"), 8765,              4543,         "W")
 3  /

1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, ORIG_SALARY, CURR_SALARY, REGION)

 2               values (9,      "Jack",  to_date("20010829","YYYYMMDD"), 7896,              1232,         "E")
 3  /

1 row created. SQL> SQL> SQL> SQL> -- display data in the table SQL> select * from Employee

 2  /
    EMPNO ENAME           HIREDATE  ORIG_SALARY CURR_SALARY R MANAGER_ID

--------------- --------- ----------- ----------- - ----------
        1 Jason           25-JUL-96        1234        8767 E          2
        2 John            15-JUL-97        2341        3456 W          3
        3 Joe             25-JAN-86        4321        5654 E          3
        4 Tom             13-SEP-06        2413        6787 W          4
        5 Jane            17-APR-05        7654        4345 E          4
        6 James           18-JUL-04        5679        6546 W          5
        7 Jodd            20-JUL-03        5438        7658 E          6
        8 Joke            01-JAN-02        8765        4543 W
        9 Jack            29-AUG-01        7896        1232 E

9 rows selected. SQL> select * from job

 2  /
    EMPNO JOBTITLE

--------------------
        1 Tester
        2 Accountant
        3 Developer
        4 COder
        5 Director
        6 Mediator
        7 Proffessor
        8 Programmer
        9 Developer

9 rows selected. SQL> SQL> SELECT empno, ename

 2  FROM employee
 3  WHERE NOT EXISTS (null);

WHERE NOT EXISTS (null)

                 *

ERROR at line 3: ORA-00928: missing SELECT keyword

SQL> SQL> SQL> -- clean the table SQL> drop table Employee

 2  /

Table dropped. SQL> drop table job

 2  /

Table dropped.</source>


exists in subquery

   <source lang="sql">

SQL> SQL> create table emp

 2  ( empno      NUMBER(4)    constraint E_PK primary key
 3  , ename      VARCHAR2(8)
 4  , init       VARCHAR2(5)
 5  , job        VARCHAR2(8)
 6  , mgr        NUMBER(4)
 7  , bdate      DATE
 8  , sal        NUMBER(6,2)
 9  , comm       NUMBER(6,2)
10  , deptno     NUMBER(2)    default 10
11  ) ;

Table created. SQL> insert into emp values(1,"Tom","N", "TRAINER", 13,date "1965-12-17", 800 , NULL, 20); 1 row created. SQL> insert into emp values(2,"Jack","JAM", "Tester",6,date "1961-02-20", 1600, 300, 30); 1 row created. SQL> insert into emp values(3,"Wil","TF" , "Tester",6,date "1962-02-22", 1250, 500, 30); 1 row created. SQL> insert into emp values(4,"Jane","JM", "Designer", 9,date "1967-04-02", 2975, NULL, 20); 1 row created. SQL> insert into emp values(5,"Mary","P", "Tester",6,date "1956-09-28", 1250, 1400, 30); 1 row created. SQL> insert into emp values(6,"Black","R", "Designer", 9,date "1963-11-01", 2850, NULL, 30); 1 row created. SQL> insert into emp values(7,"Chris","AB", "Designer", 9,date "1965-06-09", 2450, NULL, 10); 1 row created. SQL> insert into emp values(8,"Smart","SCJ", "TRAINER", 4,date "1959-11-26", 3000, NULL, 20); 1 row created. SQL> insert into emp values(9,"Peter","CC", "Designer",NULL,date "1952-11-17", 5000, NULL, 10); 1 row created. SQL> insert into emp values(10,"Take","JJ", "Tester",6,date "1968-09-28", 1500, 0, 30); 1 row created. SQL> insert into emp values(11,"Ana","AA", "TRAINER", 8,date "1966-12-30", 1100, NULL, 20); 1 row created. SQL> insert into emp values(12,"Jane","R", "Manager", 6,date "1969-12-03", 800 , NULL, 30); 1 row created. SQL> insert into emp values(13,"Fake","MG", "TRAINER", 4,date "1959-02-13", 3000, NULL, 20); 1 row created. SQL> insert into emp values(14,"Mike","TJA","Manager", 7,date "1962-01-23", 1300, NULL, 10); 1 row created. SQL> create table offerings

 2  ( course     VARCHAR2(6)
 3  , begindate  DATE
 4  , trainer    NUMBER(4)
 5  , location   VARCHAR2(8)
 6  ) ;

Table created. SQL> insert into offerings values ("SQL",date "2009-04-12",13,"DALLAS" ); 1 row created. SQL> insert into offerings values ("OAU",date "2009-08-10",4,"CHICAGO"); 1 row created. SQL> insert into offerings values ("SQL",date "2009-10-04",1,"SEATTLE"); 1 row created. SQL> insert into offerings values ("SQL",date "2009-12-13",1,"DALLAS" ); 1 row created. SQL> insert into offerings values ("JAV",date "2009-12-13",4,"SEATTLE"); 1 row created. SQL> insert into offerings values ("XML",date "2000-02-03",1,"DALLAS" ); 1 row created. SQL> insert into offerings values ("JAV",date "2000-02-01",11,"DALLAS" ); 1 row created. SQL> insert into offerings values ("PLS",date "2000-09-11",8,"DALLAS" ); 1 row created. SQL> insert into offerings values ("XML",date "2000-09-18",NULL,"SEATTLE"); 1 row created. SQL> insert into offerings values ("OAU",date "2000-09-27",13,"DALLAS" ); 1 row created. SQL> insert into offerings values ("ERM",date "2001-01-15",NULL, NULL ); 1 row created. SQL> insert into offerings values ("PRO",date "2001-02-19",NULL,"DALLAS" ); 1 row created. SQL> insert into offerings values ("RSD",date "2001-02-24",8,"CHICAGO"); 1 row created. SQL> SQL> select e.*

 2  from   emp e
 3  where  exists (select o.*
 4                 from   offerings o
 5                 where  o.course = "SQL"
 6                 and    o.trainer = e.empno);
    EMPNO ENAME    INIT  JOB             MGR BDATE             SAL       COMM

-------- ----- -------- ---------- ---------- ---------- ----------
   DEPTNO

        1 Tom      N     TRAINER          13 17-12-1965        800
       20
       13 Fake     MG                      4 13-02-1959       3000
       20

SQL> drop table offerings; Table dropped. SQL> drop table emp; Table dropped. SQL></source>


Exist with subquery

   <source lang="sql">

SQL> SQL> create table course_schedule

 2  ( course     VARCHAR2(6)
 3  , begindate  DATE
 4  , trainer    NUMBER(4)
 5  , location   VARCHAR2(20)) ;

Table created. SQL> SQL> SQL> insert into course_schedule values ("SQL",date "1999-04-12",1,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("OAU",date "1999-08-10",2,"CHICAGO"); 1 row created. SQL> insert into course_schedule values ("SQL",date "1999-10-04",3,"SEATTLE"); 1 row created. SQL> insert into course_schedule values ("SQL",date "1999-12-13",4,"DALLAS" ); 1 row created. SQL> insert into course_schedule values ("JAV",date "1999-12-13",5,"SEATTLE"); 1 row created. SQL> insert into course_schedule values ("XML",date "2000-02-03",6,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("JAV",date "2000-02-01",7,"DALLAS" ); 1 row created. SQL> insert into course_schedule values ("PLS",date "2000-09-11",8,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("XML",date "2000-09-18",NULL,"SEATTLE"); 1 row created. SQL> insert into course_schedule values ("OAU",date "2000-09-27",9,"DALLAS" ); 1 row created. SQL> insert into course_schedule values ("ERM",date "2001-01-15",10, NULL ); 1 row created. SQL> insert into course_schedule values ("PRO",date "2001-02-19",NULL,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("RSD",date "2001-02-24",8,"CHICAGO"); 1 row created. SQL> SQL> create table employees(

 2    empno      NUMBER(4)
 3  , ename      VARCHAR2(8)
 4  , init       VARCHAR2(5)
 5  , job        VARCHAR2(8)
 6  , mgr        NUMBER(4)
 7  , bdate      DATE
 8  , msal       NUMBER(6,2)
 9  , comm       NUMBER(6,2)
10  , deptno     NUMBER(2) ) ;

Table created. SQL> SQL> SQL> insert into employees values(1,"Jason", "N", "TRAINER", 2, date "1965-12-18", 800 , NULL, 10); 1 row created. SQL> insert into employees values(2,"Jerry", "J", "SALESREP",3, date "1966-11-19", 1600, 300, 10); 1 row created. SQL> insert into employees values(3,"Jord", "T" , "SALESREP",4, date "1967-10-21", 1700, 500, 20); 1 row created. SQL> insert into employees values(4,"Mary", "J", "MANAGER", 5, date "1968-09-22", 1800, NULL, 20); 1 row created. SQL> insert into employees values(5,"Joe", "P", "SALESREP",6, date "1969-08-23", 1900, 1400, 30); 1 row created. SQL> insert into employees values(6,"Black", "R", "MANAGER", 7, date "1970-07-24", 2000, NULL, 30); 1 row created. SQL> insert into employees values(7,"Red", "A", "MANAGER", 8, date "1971-06-25", 2100, NULL, 40); 1 row created. SQL> insert into employees values(8,"White", "S", "TRAINER", 9, date "1972-05-26", 2200, NULL, 40); 1 row created. SQL> insert into employees values(9,"Yellow", "C", "DIRECTOR",10, date "1973-04-27", 2300, NULL, 20); 1 row created. SQL> insert into employees values(10,"Pink", "J", "SALESREP",null,date "1974-03-28", 2400, 0, 30); 1 row created. SQL> SQL> SQL> SQL> select e.*

 2  from   employees e
 3  where  exists (select o.*
 4                 from   course_schedule o
 5                 where  o.course = "SQL"
 6                 and    o.trainer = e.empno);
    EMPNO ENAME    INIT  JOB             MGR BDATE           MSAL       COMM     DEPTNO

-------- ----- -------- ---------- --------- ---------- ---------- ----------
        1 Jason    N     TRAINER           2 18-DEC-65        800                    10
        3 Jord     T     SALESREP          4 21-OCT-67       1700        500         20
        4 Mary     J     MANAGER           5 22-SEP-68       1800                    20

SQL> SQL> drop table employees; Table dropped. SQL> SQL> drop table course_schedule; Table dropped. SQL></source>


not exists and subquery

   <source lang="sql">

SQL> SQL> create table offerings

 2  ( course     VARCHAR2(6)
 3  , begindate  DATE
 4  , trainer    NUMBER(4)
 5  , location   VARCHAR2(8)
 6  ) ;

Table created. SQL> insert into offerings values ("SQL",date "2009-04-12",13,"DALLAS" ); 1 row created. SQL> insert into offerings values ("OAU",date "2009-08-10",4,"CHICAGO"); 1 row created. SQL> insert into offerings values ("SQL",date "2009-10-04",1,"SEATTLE"); 1 row created. SQL> insert into offerings values ("SQL",date "2009-12-13",1,"DALLAS" ); 1 row created. SQL> insert into offerings values ("JAV",date "2009-12-13",4,"SEATTLE"); 1 row created. SQL> insert into offerings values ("XML",date "2000-02-03",1,"DALLAS" ); 1 row created. SQL> insert into offerings values ("JAV",date "2000-02-01",11,"DALLAS" ); 1 row created. SQL> insert into offerings values ("PLS",date "2000-09-11",8,"DALLAS" ); 1 row created. SQL> insert into offerings values ("XML",date "2000-09-18",NULL,"SEATTLE"); 1 row created. SQL> insert into offerings values ("OAU",date "2000-09-27",13,"DALLAS" ); 1 row created. SQL> insert into offerings values ("ERM",date "2001-01-15",NULL, NULL ); 1 row created. SQL> insert into offerings values ("PRO",date "2001-02-19",NULL,"DALLAS" ); 1 row created. SQL> insert into offerings values ("RSD",date "2001-02-24",8,"CHICAGO"); 1 row created. SQL> create table registrations

 2  ( attendee    NUMBER(4)
 3  , course      VARCHAR2(6)
 4  , begindate   DATE
 5  , evaluation  NUMBER(1)
 6  , constraint  R_PK        primary key(attendee,course,begindate)
 7  ) ;

Table created. SQL> SQL> insert into registrations values (2,"SQL",date "2009-04-12",4 ); 1 row created. SQL> insert into registrations values (14,"SQL",date "2009-04-12",5 ); 1 row created. SQL> insert into registrations values (6,"SQL",date "2009-04-12",4 ); 1 row created. SQL> insert into registrations values (11,"SQL",date "2009-04-12",2 ); 1 row created. SQL> insert into registrations values (8,"SQL",date "2009-10-04",NULL); 1 row created. SQL> insert into registrations values (9,"SQL",date "2009-10-04",3 ); 1 row created. SQL> insert into registrations values (13,"SQL",date "2009-10-04",4 ); 1 row created. SQL> insert into registrations values (13,"SQL",date "2009-12-13",NULL); 1 row created. SQL> insert into registrations values (6,"SQL",date "2009-12-13",NULL); 1 row created. SQL> insert into registrations values (3,"OAU",date "2009-08-10",4 ); 1 row created. SQL> SQL> select o.*

 2  from   offerings o
 3  where  not exists
 4        (select r.*
 5         from   registrations r
 6         where  r.course    = o.course
 7         and    r.begindate = o.begindate);

COURSE BEGINDATE TRAINER LOCATION


---------- ---------- --------

JAV 13-12-2009 4 SEATTLE XML 03-02-2000 1 DALLAS JAV 01-02-2000 11 DALLAS PLS 11-09-2000 8 DALLAS XML 18-09-2000 SEATTLE OAU 27-09-2000 13 DALLAS ERM 15-01-2001 PRO 19-02-2001 DALLAS RSD 24-02-2001 8 CHICAGO 9 rows selected. SQL> drop table offerings; Table dropped. SQL> drop table registrations; Table dropped. SQL></source>


Not Exist with subquery

   <source lang="sql">

SQL> SQL> create table course_schedule

 2  ( course     VARCHAR2(6)
 3  , begindate  DATE
 4  , trainer    NUMBER(4)
 5  , location   VARCHAR2(20)) ;

Table created. SQL> SQL> SQL> insert into course_schedule values ("SQL",date "1999-04-12",1,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("OAU",date "1999-08-10",2,"CHICAGO"); 1 row created. SQL> insert into course_schedule values ("SQL",date "1999-10-04",3,"SEATTLE"); 1 row created. SQL> insert into course_schedule values ("SQL",date "1999-12-13",4,"DALLAS" ); 1 row created. SQL> insert into course_schedule values ("JAV",date "1999-12-13",5,"SEATTLE"); 1 row created. SQL> insert into course_schedule values ("XML",date "2000-02-03",6,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("JAV",date "2000-02-01",7,"DALLAS" ); 1 row created. SQL> insert into course_schedule values ("PLS",date "2000-09-11",8,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("XML",date "2000-09-18",NULL,"SEATTLE"); 1 row created. SQL> insert into course_schedule values ("OAU",date "2000-09-27",9,"DALLAS" ); 1 row created. SQL> insert into course_schedule values ("ERM",date "2001-01-15",10, NULL ); 1 row created. SQL> insert into course_schedule values ("PRO",date "2001-02-19",NULL,"VANCOUVER" ); 1 row created. SQL> insert into course_schedule values ("RSD",date "2001-02-24",8,"CHICAGO"); 1 row created. SQL> SQL> create table registrations

 2  ( attendee    NUMBER(4)
 3  , course      VARCHAR2(6)
 4  , begindate   DATE
 5  , evaluation  NUMBER(1)) ;

Table created. SQL> SQL> SQL> insert into registrations values (1, "SQL",date "1999-04-12",4 ); 1 row created. SQL> insert into registrations values (2, "SQL",date "1999-12-13",NULL); 1 row created. SQL> insert into registrations values (3, "SQL",date "1999-12-13",NULL); 1 row created. SQL> insert into registrations values (4, "OAU",date "1999-08-10",4 ); 1 row created. SQL> insert into registrations values (5, "OAU",date "2000-09-27",5 ); 1 row created. SQL> insert into registrations values (6, "JAV",date "1999-12-13",2 ); 1 row created. SQL> insert into registrations values (7, "JAV",date "2000-02-01",4 ); 1 row created. SQL> insert into registrations values (8, "JAV",date "2000-02-01",5 ); 1 row created. SQL> insert into registrations values (9, "XML",date "2000-02-03",4 ); 1 row created. SQL> insert into registrations values (10,"XML",date "2000-02-03",5 ); 1 row created. SQL> insert into registrations values (1, "PLS",date "2000-09-11",NULL); 1 row created. SQL> insert into registrations values (2, "PLS",date "2000-09-11",NULL); 1 row created. SQL> insert into registrations values (3, "PLS",date "2000-09-11",NULL); 1 row created. SQL> SQL> SQL> SQL> select o.*

 2  from   course_schedule o
 3  where  not exists
 4        (select r.*
 5         from   registrations r
 6         where  r.course    = o.course
 7         and    r.begindate = o.begindate);

COURSE BEGINDATE TRAINER LOCATION


--------- ---------- --------------------

SQL 04-OCT-99 3 SEATTLE XML 18-SEP-00 SEATTLE PRO 19-FEB-01 VANCOUVER ERM 15-JAN-01 10 RSD 24-FEB-01 8 CHICAGO SQL> SQL> drop table course_schedule; Table dropped. SQL> SQL> drop table registrations; Table dropped. SQL> SQL></source>


Using the EXISTS Operator with subquery

   <source lang="sql">

SQL> CREATE TABLE empExam (

 2     empID  INT NOT NULL,
 3     ExamID     INT NOT NULL,
 4     Mark       INT,
 5     Taken   SMALLINT,
 6     Comments   VARCHAR(255),
 7     CONSTRAINT PK_empExam PRIMARY KEY (empID, ExamID));

Table created. SQL> SQL> SQL> INSERT INTO empExam (empID,ExamID,Mark,Taken,Comments) VALUES (1,1,55,1,"Satisfactory"); 1 row created. SQL> INSERT INTO empExam (empID,ExamID,Mark,Taken,Comments) VALUES (1,2,73,1,"Good result"); 1 row created. SQL> INSERT INTO empExam (empID,ExamID,Mark,Taken,Comments) VALUES (2,3,44,1,"Hard"); 1 row created. SQL> INSERT INTO empExam (empID,ExamID,Mark,Taken,Comments) VALUES (2,5,39,0,"Simple"); 1 row created. SQL> INSERT INTO empExam (empID,ExamID,Mark,Taken) VALUES (2,6,63,1); 1 row created. SQL> SQL> SQL> SQL> CREATE TABLE emp (

 2     empID INT NOT NULL PRIMARY KEY,
 3     Name      VARCHAR(50) NOT NULL);

Table created. SQL> INSERT INTO emp (empID,Name) VALUES (1,"Tom"); 1 row created. SQL> INSERT INTO emp (empID,Name) VALUES (2,"Jack"); 1 row created. SQL> INSERT INTO emp (empID,Name) VALUES (3,"Mary"); 1 row created. SQL> INSERT INTO emp (empID,Name) VALUES (4,"Bill"); 1 row created. SQL> INSERT INTO emp (empID,Name) VALUES (5,"Cat"); 1 row created. SQL> INSERT INTO emp (empID,Name) VALUES (6,"Victor"); 1 row created. SQL> SQL> SQL> SELECT empID, Name FROM emp s

 2  WHERE EXISTS (
 3     SELECT empID FROM empExam e
 4     WHERE Mark < 40 AND e.empID = s.empID);
    EMPID NAME

--------------------------------------------------
        2 Jack

1 row selected. SQL> SQL> SQL> SQL> drop table emp; Table dropped. SQL> drop table empExam; Table dropped.</source>