CHAPTER 6 • ORACLE SCHEMA OBJECT MANAGEMENT 230 addition of Oracle objects and partitioning, the format of the native database ROWID needed to be expanded, and the extended ROWID was born. Let’s look at each of these ROWID types in a bit more detail. Extended ROWIDs The extended ROWID is the native form of a ROWID in Oracle8i and was first intro- duced with Oracle8. Extended ROWIDs are relative only to a given tablespace. This is different from the relative ROWID that was present in Oracle7, which made every row in the database unique throughout the entire database. The extended ROWID is an 18-character value that represents four different values: Data object number This is a six-character representation of a 32-bit data object number. This number uniquely identifies the database segment. Each time an object changes, the data object number associated with this object changes as well. Thus, the data object number also serves as a version number for the object. Relative datafile number This is a three-character representation of the relative datafile number. The relative datafile number is relative to the tablespace to which that tablespace belongs. Thus, objects in different tablespaces will likely have different relative datafile numbers. Data block This is a six-character representation of the data block. This block number is relative to the tablespace to which it belongs. Row number in the block This is a three-character representation of the row in the block. An example of an extended ROWID is shown in the query below. SQL> SELECT rowid FROM test; ROWID ------------------ AAAAx/AABAAADhBAAA AAAAx/AABAAADhBAAB AAAAx/AABAAADhBAAC AAAAx/AABAAADhBAAD As you can see, the ROWID is a rather odd-looking thing. All of the different letters do not translate into anything usable by the DBA, except that they can be used directly in a SQL statement’s WHERE clause in certain cases (for example, if you store ROWIDs in a table). To effectively use an extended ROWID, you will probably need to employ the Oracle package DBMS_ROWID. This package has several functions that can be used to translate Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 231 the extended ROWID into its component parts, which can then be used to determine such things as which datafile or block the row is in. The DBMS_ROWID package also provides procedures and functions that can convert extended ROWIDs into restricted ROWIDs, and vice versa. Restricted ROWIDs The restricted ROWID can be determined from the extended ROWID, and an extended ROWID can be created from a restricted ROWID. The restricted ROWID has three components: • The first number in the restricted ROWID is an eight-digit number that repre- sents the block number that the row belongs in. This number relates to the V$LOCK column in the DBA_EXTENTS dictionary view. • The second number is a four-digit number that represents the row number in the block. The first row in each block is always a 0. • The last number is a four-digit number that represents the absolute datafile to which the row belongs. This number relates to the FILE_ID column in the DBA_EXTENTS data dictionary view. An example of a restricted ROWID looks something like this: 00000011.0000.0001 Each component of the restricted ROWID is separated by a dot, and unlike the extended ROWID, you do not need to use any package to determine the values being provided for each component. NOTE It is a common misconception that the restricted ROWID has been totally done away with. In fact, Oracle indexes still store restricted ROWIDs for each table row that they point to. Also, there are those who mistakenly suppose that there is some sort of ROWID conversion that occurs during a migration from Oracle 7.3 to Oracle8i. This is not the case, since the ROWIDs for tables are not stored in the database, but are generated on the fly when the ROWID pseudocolumn is used in a query. Creating Heap Tables To create a table, use the CREATE TABLE DDL statement. In its typical form, the CRE- ATE TABLE statement includes the following: • The table name MANAGING HEAP TABLES Oracle Database Administration PART II Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 6 • ORACLE SCHEMA OBJECT MANAGEMENT 232 • A list of column names, the datatype associated with the column, and certain constraints associated with that column (such as NOT NULL) • The tablespace that the table is assigned to • Table attributes such as PCTFREE and PCTUSED • The STORAGE clause associated with the table • Table attribute settings, such as CACHE or NOLOGGING To create a table in your own schema, you must have the CREATE TABLE privilege. If you want to create a table in another user’s schema, you need to have the CREATE ANY TABLE privilege. Also, you will need to have a sufficient QUOTA assigned to the tablespace(s) in which you will be creating tables (and any associated primary key indexes). If you create a primary key on the table, you also need to have the privileges to create an index, since the primary key is enforced through a unique index. NOTE A QUOTA is a limitation on how much space a user can use in a given tablespace. For example, if your quota is 0 (the default for new users), you will not be able to add any- thing to the tablespace. Users are assigned a QUOTA as a part of their configuration and setup. See Chapter 21 for more details on setting up user accounts. If you are using an Oracle TYPE in the table (we will discuss TYPEs in Chapter 8), you will need EXECUTE privileges on the TYPE you will be using, if your schema doesn’t own the TYPE. If you wish to grant access to the table to other users, you will need to have EXECUTE privileges on the TYPE with the ADMIN option. There are several miscellaneous types of settings that you may wish to consider when creating a table in Oracle. Table 6.1 lists these settings. TABLE 6.1: MISCELLANEOUS TABLE OPTIONS Option Default Purpose CACHE No Causes full table scans to be put on the head of the LRU list. This clause has been deprecated in favor of the use of the new KEEP BUFFER_POOL option. NOCACHE Yes Causes Oracle to follow the default full table scan behavior, by putting the blocks read for a full table scan on the tail of the LRU list. Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 233 TABLE 6.1: MISCELLANEOUS TABLE OPTIONS (CONTINUED) Option Default Purpose NOLOGGING No Reduces redo generated by DML activity on the table. Table data inserted after backup will not be recover- able. This can reduce the time required to create the table. LOGGING Yes Sets the table in normal mode. MONITORING No Causes Oracle to record DML activity on the table. You can then use the DBMS_STATS.GATHER STALE procedure to update the statistics of just the tables that have changed. NOMONITORING Yes Sets the default for this parameter. NOTE CACHE remains in Oracle only for backward compatibility. You should configure and use a keep buffer pool (described in Chapter 5) and assign an object to that buffer pool rather than use the CACHE option. Creating a Table Listing 6.1 shows a simple example of using the CREATE TABLE statement. Listing 6.1: Creating a Heap Table CREATE TABLE PARENT (parent_id NUMBER PRIMARY KEY, last_name VARCHAR2(30) NOT NULL, first_name VARCHAR2(30) NOT NULL, middle_int CHAR(1), sex CHAR(1), married_status CHAR(1) ) TABLESPACE users PCTFREE 10 PCTUSED 60 STORAGE(INITIAL 10m NEXT 10m PCTINCREASE 0); MANAGING HEAP TABLES Oracle Database Administration PART II Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 6 • ORACLE SCHEMA OBJECT MANAGEMENT 234 This creates a table named PARENT with six columns. The first column, PARENT_ID, is defined as a NUMBER datatype and the primary key of this table. Because the keyword PRIMARY KEY is included in the definition of the PARENT_ID column, an index will be created on this primary key column. Since we didn’t give the index a name in this CREATE TABLE statement, Oracle will assign a name to it by default. The system-generated name will always start with a SYS and then be followed by a series of numbers. Also, the primary key index will be created in the default tablespace of the user creating the table, and the index associated with the primary key will also have a system-generated name. The query and results below show the primary key created as a result of the creation of this table. SQL> SELECT table_name, index_name, tablespace_name 2 FROM user_indexes 3 WHERE table_name like ‘PARENT’; TABLE_NAME INDEX_NAME TABLESPACE_NAME ---------- -------------------- ---------------- PARENT SYS_C00780 USERS This shows that the system-generated index name is SYS_C00780. Also note that the primary key index has been assigned to the USERS tablespace, which is the default tablespace of the user who created the index. In the next section, you will see an example of how to give the primary key index a meaningful name and control where the primary key index is created. The LAST_NAME and FIRST_NAME columns in the table are VARCHAR2 datatypes that are sized to hold up to 30 characters each. The MIDDLE_INT, SEX, and MAR- RIED_STATUS columns are fixed-length CHAR datatypes, each holding 1 byte. Notice the NOT NULL keyword in the LAST_NAME and FIRST_NAME column defi- nitions. The NOT NULL keyword establishes a constraint on the table. A constraint is a rule. In this case, the NOT NULL constraint prohibits this column from having a NULL value in it at any time. Thus, you will need to provide a value for the column in each INSERT statement, by including it in the INSERT statement, through the use of a trigger (see Chapter 1 and Appendix F for more on triggers) or by defining a default value for the column. When you create a primary key, the columns of the primary key will be set to the NOT NULL status automatically. The other types of constraints you can create in Oracle are check, foreign key, NOT NULL, primary, and unique. When creating a table, you may define the various con- straints in the CREATE TABLE statement either for individual rows (check constraints) or a group of rows (primary keys). (See Chapter 7 for a detailed discussion of con- straints.) Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 235 Viewing the Table After you’ve created the table, you can query the DBA_TABLES view to see your table: SELECT owner, table_name, tablespace_name, initial_extent, next_extent FROM dba_tables WHERE owner = ‘SCOTT’ AND table_name LIKE ‘PARENT’; OWNER TABLE_NAME TABLESPACE_NAME INITIAL_EXTENT NEXT_EXTENT ----------- ------------ --------------- -------------- ----------- SCOTT PARENT USERS 10485760 10485760 Also, you can query the DBA_TAB_COLS data dictionary view and discover that you have rows in it for each of the columns in your table: SELECT owner, table_name, column_name, data_type, nullable 2 FROM dba_tab_columns 3 WHERE owner=’SCOTT’ 4 AND table_name=’PARENT’ OWNER TABLE_NAME COLUMN_NAME DATA_TYPE N --------- --------------- ------------------------------ ---------- - SCOTT PARENT PARENT_ID NUMBER N SCOTT PARENT LAST_NAME VARCHAR2 N SCOTT PARENT FIRST_NAME VARCHAR2 N SCOTT PARENT MIDDLE_INT CHAR Y SCOTT PARENT SEX CHAR Y SCOTT PARENT MARRIED_STATUS CHAR y The DBA_TABLES and DBA_TAB_COLS views are discussed in more detail in the “Viewing Table Information” section a bit later in this chapter. Specifying the Primary Key and Index Location Listing 6.2 shows another example of a CREATE TABLE statement. Listing 6.2: Creating a Table with Primary Key and Index Location Specifications CREATE TABLE children (child_id NUMBER CONSTRAINT pk_children PRIMARY KEY USING INDEX TABLESPACE indexes STORAGE (INITIAL 200k NEXT 200k), parent_id NUMBER, MANAGING HEAP TABLES Oracle Database Administration PART II Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 6 • ORACLE SCHEMA OBJECT MANAGEMENT 236 last_name VARCHAR2(30), first_name VARCHAR2(30), middle_int CHAR(1), medical_code VARCHAR2(30) CONSTRAINT children_check_upper CHECK (medical_code = UPPER(medical_code) ) ) TABLESPACE users PCTFREE 10 PCTUSED 60 STORAGE(INITIAL 10m NEXT 10m PCTINCREASE 0); This one looks a bit different from the CREATE TABLE statement in Listing 6.1. First, the second line, where the CHILD_ID column is being defined, includes a CONSTRAINT clause that names the primary key constraint. In this example, the primary key con- straint is named PK_CHILDREN. The associated index enforcing that primary key will also be called PK_CHILDREN. Next, the USING INDEX clause is associated with the first column. It is through this clause that you can control in which tablespace the primary key index is created, as well as define storage characteristics for that index with a separate STORAGE clause. Finally, note the check constraint in the definition of the MEDICAL_CODE col- umn. The definition of the constraint begins with the word CONSTRAINT, followed by the name of the constraint, then the keyword CHECK. Following the CHECK key- word is the actual constraint. This example uses the UPPER function to ensure that any values for MEDICAL_CODE are entered in uppercase. If someone tried to enter a lowercase medical code in this column, the transaction would fail and the following error would be returned: ORA-02290: check constraint (SCOTT.CHECK_UPPER) violated Creating a Two-Column Primary Key and Foreign Key Constraint Let’s look at another example of a CREATE TABLE statement. The example shown in Listing 6.3 re-creates the CHILD table with a two-column primary key and a foreign key constraint to the PARENT key. Listing 6.3: Creating a Table with a Two-Column Primary Key and For- eign Key Constraint CREATE TABLE children (child_id NUMBER, parent_id NUMBER, last_name VARCHAR2(30), Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 237 first_name VARCHAR2(30), middle_int CHAR(1), medical_code VARCHAR2(30) CONSTRAINT children_check_upper CHECK (medical_code = UPPER(medical_code) ), CONSTRAINT pk_children PRIMARY KEY (child_id, parent_id) USING INDEX TABLESPACE indexes STORAGE (INITIAL 10k NEXT 10k), CONSTRAINT fk_child_parent FOREIGN KEY (parent_id) REFERENCES parent (parent_id) ) TABLESPACE users PCTFREE 10 PCTUSED 60 STORAGE(INITIAL 10m NEXT 10m PCTINCREASE 0) Both the primary key constraint and the foreign key constraint are created in the same clause where the table columns are created. Since the example creates a two- column primary key, it adds a separate CONSTRAINT clause, rather than just the PRIMARY KEY clause at the end of each column. In other words, you cannot create a two-column primary key like this: CREATE TABLE children (child_id NUMBER PRIMARY KEY, parent_id NUMBER PRIMARY KEY, last_name VARCHAR2(30), first_name VARCHAR2(30), middle_int CHAR(1) ); This code would result in an error because you are incorrectly trying to define a two- column primary key. Creating a Table from an Existing Table Definition The CREATE TABLE AS SELECT (CTAS) command allows you to create a table from the definition of an existing table, or create a new table based on a join of one or more tables. This is handy to have for a variety of reasons. First, this is one method you can use to defragment a table. Also, you can use CTAS to create a separate table with a sample set of data. Listing 6.4 shows an example of using CTAS to create a table from two existing tables. Listing 6.4: Using the CREATE TABLE AS SELECT (CTAS) Command -- Using CTAS from an existing table (or tables in this case). -- We are also limiting the number of rows returned to 9. MANAGING HEAP TABLES Oracle Database Administration PART II Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. CHAPTER 6 • ORACLE SCHEMA OBJECT MANAGEMENT 238 CREATE TABLE create_view_table_one TABLESPACE users STORAGE (INITIAL 100k NEXT 100k BUFFER_POOL RECYCLE) AS SELECT a.parent_id AS parent_id, a.last_name AS parent_last_name, a.first_name AS paremt_first_name, b.last_name AS child_last_name, b.first_name AS child_first_name FROM parent a, children b WHERE a.parent_id=b.parent_id AND rownum < 10; You can also use CTAS to create a table using a view, as shown in Listing 6.5. This example executes this statement using a view as the source for the new table. Listing 6.5: Creating a Table Using a View with CTAS -- Create the view first CREATE VIEW v_parent_child AS SELECT a.parent_id AS parent_id, a.last_name AS parent_last_name, a.first_name AS parent_first_name, b.last_name AS child_last_name, b.first_name AS child_first_name FROM parent a, children b WHERE a.parent_id=b.parent_id; -- Now, create a table via CTAS using the view CREATE TABLE ctas_from_view_pc TABLESPACE data STORAGE (INITIAL 100k NEXT 100k ) AS SELECT * FROM v_parent_child; NOTE CTAS is particularly handy for use with LogMiner, which is discussed in Chapter 14. This is because some of the critical views that LogMiner populates with information are persistent only for the duration of the user session that created those views. Using CTAS to create a table allows you to retain the LogMiner results. Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 239 Creating a Temporary Table A temporary table is like a regular table in many ways. It is created by the use of the GLOBAL TEMPORARY keywords in the CREATE TABLE command. The data in a tem- porary table is visible to only the session that created that data, yet the temporary table is available for use by all transactions. The temporary table will persist until it is dropped; however, the data in the tem- porary table is not persistent. Using the ON COMMIT keywords, you can choose from two different options that control when the data in the temporary table is removed. If you create the temporary table using the ON COMMIT DELETE clause (the default), the session data in the table is removed as soon as the transaction completes. Using the ON COMMIT PRESERVE clause will cause that session’s data to be removed only after the session is disconnected. A temporary table uses temporary segments to store session data, and along with the data in the segments, the segments themselves are de-allocated. Since temporary tables use temporary segments, they use the temporary tablespace defined for the user who is using the temporary table. Therefore, no TABLESPACE clause, STORAGE clause, or physical attributes clauses are allowed in the CREATE TABLE statement. When an index is created on a temporary table, its data segments are temporary as well. There- fore, a USING INDEX clause is not permitted when creating a temporary table. The CONSTRAINT clause is allowed, but some constraints are not permitted. Here is a summary of the restrictions on temporary tables: • They can be only hash tables (so index-organized tables and clusters are not allowed as temporary tables). • You cannot partition a temporary table. • Most constraints are not supported, but you can specify check constraints and NOT NULL constraints. You can create temporary tables with primary keys, but foreign key relationships are not supported. • Temporary tables do not support nested tables or VARRAYs, which are part of Oracle’s object-oriented features. • Parallel DML and parallel queries are not supported on temporary tables. • You cannot use a temporary table as a part of a distributed transaction. Listing 6.6 shows an example of creating a temporary table. Listing 6.6: Creating a Temporary Table CREATE GLOBAL TEMPORARY TABLE temp_children (child_id NUMBER CONSTRAINT pk_temp_children PRIMARY KEY, parent_id NUMBER, MANAGING HEAP TABLES Oracle Database Administration PART II Copyright ©2002 SYBEX, Inc., Alameda, CA www.sybex.com Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... key to find the correct row Thus, stale guesses can cause significant performance impacts Therefore, guesses should be used only when a table will have little change activity You can use the ROWID pseudocolumn to select logical ROWIDs from an IOT The ROWIDs are a bit different in format than the physical extended or restricted ROWIDs, in that they contain both the primary key and the guess information . not stored in the database, but are generated on the fly when the ROWID pseudocolumn is used in a query. Creating Heap Tables To create a table, use the