Oracle Gotchas for An Experienced Newb

mysql, oracle, php, postgresql, sql-server

Solution

Note: I'm explaining only the gotchas here, i. e. situations when `Oracle` behaves not as other systems do. `Oracle` has numerous benefits over other `RDBMS`'s, but they are not the topic of the post.

You cannot `SELECT` without `FROM`.

SELECT  1

will fail, you need to:

SELECT  1
FROM    dual

Empty string and `NULL` are the same thing.

SELECT  *
FROM    dual
WHERE   '' = ''

returns nothing.

There are neither `TOP` nor `LIMIT`. You limit your results in the `WHERE` clause:

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        ORDER BY
                col
        )
WHERE   rownum < 10

exactly this way, using a subquery, since `ROWNUM` is evaluated before `ORDER BY`.

You cannot nest the correlated subqueries more than one level deep. This one will fail:

SELECT  (
        SELECT  *
        FROM    (
                SELECT  dummy
                FROM    dual di
                WHERE   di.dummy = do.dummy
                ORDER BY
                        dummy
                )
        WHERE   rownum = 1
        )
FROM    dual do

This is a problem.

`NULL` values are not indexed. This query will not use an index for ordering:

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        ORDER BY
                col
        )
WHERE   rownum < 10

, unless `col` is marked as `NOT NULL`.

Note than it's `NULL` values that are not indexed, not columns. You can create an index on a nullable column, and non-`NULL` values will get into the index.

However, the index will not be used when the query condition assumes that `NULL` values can possibly satisfy it.

In the example above you want all value to be returned (including `NULL`s). Then index doesn't know of non-`NULL` values, hence, cannot retrieve them.

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        ORDER BY
                col
        )
WHERE   rownum < 10

But this query will use the index:

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        WHERE   col IS NOT NULL
        ORDER BY
                col
        )
WHERE   rownum < 10

, since non-`NULL` values cannot ever satisfy the condition.

By default, `NULL`s are sorted last, not first (like in `PostgreSQL`, but unlike `MySQL` and `SQL Server`)

This query:

SELECT  *
FROM    (
        SELECT  1 AS id
        FROM    dual
        UNION ALL
        SELECT  NULL AS id
        FROM    dual
        ) q
ORDER BY
        id

will return

id
---
1
NULL

To sort like in `SQL Server` and `MySQL`, use this:

SELECT  *
FROM    (
        SELECT  1 AS id
        FROM    dual
        UNION ALL
        SELECT  NULL AS id
        FROM    dual
        ) q
ORDER BY
        id NULLS FIRST

Note that it breaks `rownum` order unless the latter is not used out of the subquery (like explained above)

`"MYTABLE"` and `"mytable"` (double quotes matter) are different objects.

SELECT  *
FROM    mytable -- wihout quotes

will select from the former, not the latter. If the former does not exist, the query will fail.

CREATE TABLE mytable

creates `"MYTABLE"`, not `"mytable"`.

In `Oracle`, all implicit locks (that result from `DML` operations) are row-level and are never escalated. That is no row not affected by the transaction can be implicitly locked.

Writers never block readers (and vice versa).

To lock the whole table, you should issue an explicit `LOCK TABLE` statement.

Row locks are stored on the datapages.

In `Oracle`, there are no "`CLUSTERED` indexes", there are "index-organized tables". By default, tables are heap organized (unlike `SQL Server` and `MySQL` with `InnoDB`).

In `Oracle` world, a "clustered storage" means organizing several tables so that the rows which share a common key (from several tables) also share a datapage.

A single datapage hosts multiple rows from multiple tables which makes joins on this key super fast.

Problem

What are some Oracle gotchas for someone new to the platform, but not new to relational databases (MySQL, MS SQL Server, Postgres, etc.) in general. Two examples of the kind of things I'm looking for Many relational database products handle creating an auto_increment key for you. Oracle does not, you must manually create the sequence, then create the trigger When INSERTING data via the SQL Developer interface, you have to manually commit the data Bonus points for PHP related gotchas, as that's the platform I'll this hypothetical experienced newb will be using.

Original source

Related problems