Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: What's wrong with this SQL?

Re: What's wrong with this SQL?

From: Niall Litchfield <niall.litchfield_at_dial.pipex.com>
Date: 18 Jan 2005 01:47:21 -0800
Message-ID: <1106041641.056378.267930@c13g2000cwb.googlegroups.com>


ohaya wrote:
> Bent Stigsen wrote:

> Ok, I think I see.
>
> Synopsis:
>
> - By dropping the inline primary key, that means that the original
> "CREATE TABLE" won't cause the "sessionid" to be indexed, then

Pretty much. It is the declaration of the primary key that is causing Oracle to create an index. In the script that the vendor supplies the index will have a user-hostile name.

> - By eliminating the "CREATE INDEX", that will eliminate an index
being
> created, then
>

Absolutely.

> - By adding the "ALTER TABLE" with the add constraint, this will make
> "sessionid" the primary key AND create a CONSTRAINT named
> "XIE1ss_sessionspec5".

It will create the PRIMARY KEY named XIE1SS_SESSIONSPEC5 *and* an index of the same name.

> Questions:
>
> I'm assuming that when the "ALTER TABLE" makes "sessionid" the
primary
> key, that this creates an index. Is this correct?

Yes, but it doesn't have to, bear with me a bit, I'm going to try and expand things a bit below without over-complicating things, but hopefully also not by over-simplyfying.

> Also, in Oracle, is the constraint "XIE1ss_sessionspec5" that results
> from "ALTER TABLE" treated EXACTLY the same as if it were an INDEX
after
> that?

No. An index in and of itself is pretty much only used for accessing data more efficiently. The primary key constraint tells Oracle a lot more about the data in the sessionid column.

A primary key in any relational database is the column (or columns) that uniquely and completely identify a member of a set (a session in this case). That is to say that every session MUST have a session_id AND that session_id MUST EXIST.

When you tell oracle that a column is a primary key, that tells it that every row in the table must have a value (be NOT NULL) and that each value must be unique. Oracle achieves this by default by creating a NOT NULL constraint for the column and by creating a system named UNIQUE index.

You can see this for yourself below.

SQL> CREATE TABLE ss_sessionspec5 (

2        sessionid                        VARCHAR2(64),
3*       expirationtime       INTEGER DEFault 0 not null);

Table created.

SQL> desc ss_sessionspec5;

Name                                      Null?    Type
----------------------------------------- --------
----------------------------
SESSIONID                                          VARCHAR2(64)
EXPIRATIONTIME                            NOT NULL NUMBER(38)

SQL> select index_name from user_indexes where table_name='SS_SESSIONSPEC5';

no rows selected

SQL> DROP TABLE SS_SESSIONSPEC5; Table dropped.

SQL> CREATE TABLE ss_sessionspec5 (

2        sessionid                        VARCHAR2(64),
3        expirationtime       INTEGER DEFault 0 not null)
4 .

SQL> ED
Wrote file afiedt.buf

1 CREATE TABLE ss_sessionspec5 (

2        sessionid            VARCHAR2(64) primary key,
3*       expirationtime       INTEGER DEFault 0 not null)
SQL> .
SQL> / Table created.

SQL> desc ss_sessionspec5;

Name                                      Null?    Type
----------------------------------------- --------
----------------------------
SESSIONID                                 NOT NULL VARCHAR2(64)
EXPIRATIONTIME                            NOT NULL NUMBER(38)

SQL> select index_name from user_indexes where table_name='SS_SESSIONSPEC5';

INDEX_NAME



SYS_C006138 1 row selected.

SQL> select index_name,uniqueness
2 from user_indexes
3* where table_name = 'SS_SESSIONSPEC5'
SQL> /

INDEX_NAME                     UNIQUENES
------------------------------ ---------
SYS_C006138                    UNIQUE

1 row selected.

Now there is one further possibility and that is to use a non-unique index on the primary key. It is possible that this is what your vendor was trying to achieve with the create index statement, as the create index statement will NOT create a unique index.

SQL> drop table ss_sessionspec5;

Table dropped.

SQL> CREATE TABLE ss_sessionspec5 (

2        sessionid                        VARCHAR2(64),
3        expirationtime       INTEGER DEFAULT 0 NOT NULL);

Table created.

SQL> create index idx_sessionspec5
2* on ss_sessionspec5(sessionid);

Index created.

SQL> alter table ss_sessionspec5
2 add constraint pk_sessionspec5
3* primary key(sessionid);

Table altered.

SQL> select index_name,uniqueness
2 from user_indexes
3* where table_name='SS_SESSIONSPEC5'
SQL> /

INDEX_NAME                     UNIQUENES
------------------------------ ---------
IDX_SESSIONSPEC5               NONUNIQUE

1 row selected.

SQL> DESC SS_SESSIONSPEC5;

Name                                      Null?    Type
----------------------------------------- --------
------------------------
SESSIONID                                 NOT NULL VARCHAR2(64)
EXPIRATIONTIME                            NOT NULL NUMBER(38)

SQL> All of which rather begs the questions

  1. why would you use a non-unique index for a primary key, after all it is a unique column or column combination. and
  2. why issue two statements when one will do.

Well you will want to use a non-unique index for a deferrable constraint. This is used to provide updateable constraints see http://www.oracle.com/technology/oramag/oracle/03-nov/o63asktom.html for an example. Oracle also uses them for materialized views or snapshots, but that is probably irrelevant for now.

The answer to the second question can be answered by considering what happens if you disable a constraint - often used to speed data loads.

SQL> ed
Wrote file afiedt.buf

1 CREATE TABLE ss_sessionspec5 (

2        sessionid                        VARCHAR2(64),
3        expirationtime       INTEGER DEFAULT 0 NOT NULL,
4* constraint pk_ss_sessionspec5 primary key(sessionid)) SQL> .
SQL> / Table created.

SQL> DESC SS_SESSIONSPEC5;

Name                                      Null?    Type
----------------------------------------- --------
----------------------------
SESSIONID                                 NOT NULL VARCHAR2(64)
EXPIRATIONTIME                            NOT NULL NUMBER(38)

SQL> select index_name,uniqueness from user_indexes 2 where table_name='SS_SESSIONSPEC5';

INDEX_NAME                     UNIQUENES
------------------------------ ---------
PK_SS_SESSIONSPEC5             UNIQUE

1 row selected.

SQL> ALTER TABLE SS_SESSIONSPEC5 DISABLE CONSTRAINT PK_SS_SESSIONSPEC5; Table altered.

SQL> select index_name,uniqueness from user_indexes 2 where table_name='SS_SESSIONSPEC5';

no rows selected

SQL> DROP TABLE SS_SESSIONSPEC5; Table dropped.

SQL> CREATE TABLE ss_sessionspec5 (

2        sessionid                        VARCHAR2(64),
3        expirationtime       INTEGER DEFAULT 0 NOT NULL);

Table created.

SQL> CREATE UNIQUE INDEX PK_SESSIONSPEC5 2 ON SS_SESSIONSPEC5(SESSIONID); Index created.

SQL> ALTER TABLE SS_SESSIONSPEC5
2 ADD CONSTRAINT PK_SESSIONSPEC5 PRIMARY KEY (SESSIONID); Table altered.

SQL> DESC SS_SESSIONSPEC5;

Name                                      Null?    Type
----------------------------------------- --------
----------------------------
SESSIONID                                 NOT NULL VARCHAR2(64)
EXPIRATIONTIME                            NOT NULL NUMBER(38)

SQL> select index_name,uniqueness from user_indexes 2 where table_name='SS_SESSIONSPEC5';

INDEX_NAME                     UNIQUENES
------------------------------ ---------
PK_SESSIONSPEC5                UNIQUE

1 row selected.

SQL> ALTER TABLE SS_SESSIONSPEC5 DISABLE CONSTRAINT PK_SESSIONSPEC5; Table altered.

SQL> select index_name,uniqueness from user_indexes 2 where table_name='SS_SESSIONSPEC5';

INDEX_NAME                     UNIQUENES
------------------------------ ---------
PK_SESSIONSPEC5                UNIQUE

1 row selected.

SQL> so if we create the constraint inline and later disable it we lose the index, if we precreate the index and let the constraint use it we don't lose the index when we disable the constraint.

Hope that all helps rather than confuses

Niall Litchfield
Oracle DBA
http://www.niall.litchfield.dial.pipex.com Received on Tue Jan 18 2005 - 03:47:21 CST

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US