7.4 Rules and Restrictions on Set Operations
Other than the union compatibility
conditions discussed at the beginning of the chapter, there are some
other rules and restrictions that apply to the set operations. These
rules and restrictions are as follows:
Column
names for the result set are derived
from the first SELECT:
SELECT CUST_NBR "Customer ID", NAME "Customer Name"
FROM CUSTOMER
WHERE REGION_ID = 5
UNION
SELECT C.CUST_NBR, C.NAME
FROM CUSTOMER C
WHERE C.CUST_NBR IN (SELECT O.CUST_NBR
FROM CUST_ORDER O, EMPLOYEE E
WHERE O.SALES_EMP_ID = E.EMP_ID
AND E.LNAME = 'MARTIN');
Customer ID Customer Name
----------- ----------------------
1 Cooper Industries
2 Emblazon Corp.
3 Ditech Corp.
4 Flowtech Inc.
5 Gentech Industries
8 Zantech Inc.
6 rows selected.
Although both SELECTs use column aliases, the result set takes the
column names from the first SELECT. The same thing happens when we
create a view based on a set operation. The column names in the view
are taken from the first SELECT:
CREATE VIEW V_TEST_CUST AS
SELECT CUST_NBR "Customer ID", NAME "Customer Name"
FROM CUSTOMER
WHERE REGION_ID = 5
UNION
SELECT C.CUST_NBR, C.NAME
FROM CUSTOMER C
WHERE C.CUST_NBR IN (SELECT O.CUST_NBR
FROM CUST_ORDER O, EMPLOYEE E
WHERE O.SALES_EMP_ID = E.EMP_ID
AND E.LNAME = 'MARTIN');
View created.
DESC V_TEST_CUST
Name Null? Type
------------------------------- -------- ----
Customer_ID NUMBER
Customer_Name VARCHAR2(45)
If we want to use ORDER BY in a query involving set
operations, we must place the ORDER BY at the end of the entire
statement. The ORDER BY clause can appear only once at the end of the
compound query. The component queries can't have
individual ORDER BY clauses. For example:
SELECT CUST_NBR, NAME
FROM CUSTOMER
WHERE REGION_ID = 5
UNION
SELECT EMP_ID, LNAME
FROM EMPLOYEE
WHERE LNAME = 'MARTIN'
ORDER BY CUST_NBR;
CUST_NBR NAME
---------- ---------------------
1 Cooper Industries
2 Emblazon Corp.
3 Ditech Corp.
4 Flowtech Inc.
5 Gentech Industries
7654 MARTIN
6 rows selected.
Note that the column name used in the ORDER BY clause of this query
is taken from the first SELECT. We couldn't order
these results by EMP_ID. If we attempt to ORDER BY EMP_ID, we will
get an error, as in the following example:
SELECT CUST_NBR, NAME
FROM CUSTOMER
WHERE REGION_ID = 5
UNION
SELECT EMP_ID, LNAME
FROM EMPLOYEE
WHERE LNAME = 'MARTIN' ORDER BY EMP_ID;
ORDER BY EMP_ID
*
ERROR at line 8:
ORA-00904: invalid column name
The ORDER BY clause doesn't recognize the column
names of the second SELECT. To avoid confusion over column names, it
is a common practice to ORDER BY column positions:
SELECT CUST_NBR, NAME
FROM CUSTOMER
WHERE REGION_ID = 5
UNION
SELECT EMP_ID, LNAME
FROM EMPLOYEE
WHERE LNAME = 'MARTIN'
ORDER BY 1;
CUST_NBR NAME
---------- ---------------------
1 Cooper Industries
2 Emblazon Corp.
3 Ditech Corp.
4 Flowtech Inc.
5 Gentech Industries
7654 MARTIN
6 rows selected.
|
Unlike ORDER BY, we can use GROUP BY and HAVING clauses in component
queries.
|
|
Component queries are executed from top to bottom. If
we want to alter the sequence of execution, use parentheses
appropriately. For example:
SELECT * FROM SUPPLIER_GOOD
UNION
SELECT * FROM SUPPLIER_TEST
MINUS
SELECT * FROM SUPPLIER;
SUPPLIER_ID NAME
----------- --------------------------
4 Toshiba
Oracle performs the UNION between SUPPLIER_GOOD and SUPPLIER_TEST
first, and then performs the MINUS between the result of the UNION
and the SUPPLIER table. If we want the MINUS between SUPPLIER_TEST
and SUPPLIER to be performed first, and then the UNION between
SUPPLIER_GOOD and the result of MINUS, we must use parentheses to
indicate so:
SELECT * FROM SUPPLIER_GOOD
UNION
(SELECT * FROM SUPPLIER_TEST
MINUS
SELECT * FROM SUPPLIER);
SUPPLIER_ID NAME
----------- -------------------------
1 Sony
2 Samsung
3 Panasonic
4 Toshiba
The parentheses in this query forces the MINUS to be performed before
the UNION. Notice the difference in the result as compared to the
previous example.
The following list summarizes some simple rules, restrictions, and
notes that don't require examples:
Set operations are not permitted on columns of type BLOB, CLOB,
BFILE, and VARRAY, nor are set operations permitted on nested table
columns.
Since UNION, INTERSECT, and MINUS operators involve sort operations,
they are not allowed on LONG columns. However, UNION ALL is allowed
on LONG columns.
Set operations are not allowed on SELECT statements containing TABLE
collection expressions.
SELECT statements involved in set operations can't
use the FOR UPDATE clause.
The number and size of columns in the SELECT list of component
queries are limited by the block size of the database. The total
bytes of the columns SELECTed can't exceed one
database block.
|