複合主キー (WORK_DATE、EMP_ID) の正確な昇順で Oracle 行をソートしたいと考えています。SQL Server では、クラスタ化インデックスを簡単に作成すると、魔法のように問題が解決します。一見、Oracle の ORGANIZATION INDEX (または IOT) は実行可能なソリューションを提供するように見えましたが、そうではありません。
次の DDL は、この問題を示しています。データを可能な限り現実的なものにしました。特に、行ごとにサイズが異なるかなり大きな VARCHAR フィールドがあるという事実です (おそらく、Oracle が行のストレージを並べ替えるのを思いとどまらせます)。
アドホック ユーザーが「ORDER BY 1, 2」を追加しなくても、クエリ #2 の出力と同じように行が格納されるようにするソリューションを探しています。ORDER BY ステートメントを追加するのを忘れて、最新の WORK_DATE を取得していると考えて、一番下にCTRL+を追加する不器用なユーザーがいます。END埋め込みの ORDER BY ステートメントを含むビューを作成して、これを解決したくありません。DDL ステートメントの修正を提案できますか? おそらく、「ORGANIZATION INDEX」キーワードの後に追加の句またはパラメーターが必要ですか? ご協力ありがとうございます。
CREATE TABLE EMPLOYEE_HOURS (
WORK_DATE DATE NOT NULL
, EMP_ID VARCHAR2(15) NOT NULL
, HOURS_WORKED NUMBER(22) NOT NULL
, WORK_COMMENT VARCHAR2(150) NOT NULL
, ROW_INSERT_DATE TIMESTAMP DEFAULT SYSTIMESTAMP
, CONSTRAINT EMPLOYEE_HOURS_PK PRIMARY KEY (WORK_DATE, EMP_ID)
) ORGANIZATION INDEX;
/* create test data that mimics my real world data */
BEGIN
FOR loop_id IN 1 .. 10000
LOOP
INSERT INTO EMPLOYEE_HOURS VALUES (
TRUNC(SYSDATE) - TRUNC(dbms_random.value(-150, 150))
, UPPER(dbms_random.string('A', 3))
|| TRUNC(dbms_random.value(1000, 999999))
, dbms_random.value(0.5, 18.5)
, regexp_replace(SUBSTR(LOWER(dbms_random.string('A', 100))
, 1
, TRUNC(dbms_random.value(4, 100))), '(.....)', '\1 ')
, SYSTIMESTAMP);
COMMIT WORK;
END LOOP;
END;
/* compare these queries and notice that the sort order in the first query does not
conform to the expected order of the IOT composite index (WORK_DATE, EMP_ID) */
/* Query #1 */
SELECT * FROM EMPLOYEE_HOURS;
/* Query #2 */
SELECT * FROM EMPLOYEE_HOURS ORDER BY 1, 2;