SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

HRzine Day(エイチアールジン・デイ)は、人が活き会社が成長する人事のWebマガジン「HRzine」が主催するイベントです。毎回、人事の重要課題を1つテーマに設定し、識者やエキスパードが持つ知見・経験を、参加者のみなさんと共有しています。

直近開催のイベントはこちら!

HRzine×SmartHR 人材・組織活性化フォーラム

2024年12月6日(金)13:00~15:30

主要製品スペック一覧

人事業務の効率・確度・精度を高めるために欠かせないHRテクノロジー。その主な製品の機能を分野ごとに比較できる資料群です。製品検討の参考資料としてご活用ください。

eラーニング・LMS<br>主要製品スペック一覧 2024

eラーニング・LMS
主要製品スペック一覧 2024

その他のスペック一覧

人事労務管理システム<br>主要製品スペック一覧 2023

人事労務管理システム
主要製品スペック一覧 2023

タレントマネジメントシステム<br>主要製品スペック一覧 2023

タレントマネジメントシステム
主要製品スペック一覧 2023

落とし穴はこれで回避! Oracle DB 12c SQL基礎 弱点克服スクール | 第10回

データ定義言語(DDL)の概要

  • Facebook
  • X
  • Pocket
  • note
  • hatena

制約

制約には、次の表に示すものがありました。

表1:制約
制約 説明
NOT NULL 列にNULLを入力できない
UNIQUE 列または列の組み合わせに対して、表内の各行の値が一意でなければならない(重複してはいけない)
PRIMARY KEY 列または列の組み合わせに対して、表内の各行の値を識別できるように、一意でありなおかつNULL以外でなければならない
FOREIGN KEY 列または列の組み合わせが、参照先の列または列の組み合わせによる値と一致しなければいけない
CHECK 指定した条件を満たさなければいけない

さて、これらの制約を定義するときの注意事項にはどんなことがあったでしょう。

問3

あなたは次のような列の仕様とデータ型でORDER_ITEMS表を作成しようと考えています。目的の表を作成するにはどのSQL文を使用しますか。2つ選択しなさい。

  • ORDER_ID : 数値
  • PROD_ID : 数値、PRODUCTS表のPROD_ID列に存在する値のみを入力可能とする
  • ORDER_DATE : 日付、入力が省略された場合は現在の日付を設定する
  • QTY : 数値、1以上でなければならない
  • ORDER_IDとPROD_IDの組み合わせの値を一意にして、NULL値は設定できないようにする
  • a. CREATE TABLE order_items
    (order_id NUMBER NOT NULL
    ,prod_id NUMBER NOT NULL REFERENCES products(prod_id)
    ,order_date DATE DEFAULT SYSDATE
    ,qty NUMBER CHECK (qty >= 1)
    ,CONSTRAINTS oi_uk UNIQUE(order_id ,prod_id));
  • b. CREATE TABLE order_items
    (order_id NUMBER NOT NULL UNIQUE
    ,prod_id NUMBER NOT NULL UNIQUE
    ,order_date DATE DEFAULT SYSDATE
    ,qty NUMBER CHECK (qty >= 1)
    ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));
  • c. CREATE TABLE order_items
    (order_id NUMBER
    ,prod_id NUMBER
    ,order_date DATE DEFAULT SYSDATE
    ,qty NUMBER CHECK (qty >= 1)
    ,CONSTRAINTS oi_pk PRIMARY KEY(order_id ,prod_id)
    ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));
  • d. CREATE TABLE order_items
    (order_id NUMBER
    ,prod_id NUMBER
    ,order_date DATE
    ,qty NUMBER
    ,CONSTRAINTS oi_df DEFAULT (order_date = SYADATE)
    ,CONSTRAINTS oi_ck CHECK (qty >= 1)
    ,CONSTRAINTS oi_pk PRIMARY KEY(order_id ,prod_id)
    ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));
  • e. CREATE TABLE order_items
    (order_id NUMBER
    ,prod_id NUMBER
    ,order_date INTERVAL YEAR TO MONTH DEFAULT SYSDATE
    ,qty NUMBER CHECK (qty >= 1)
    ,CONSTRAINTS oi_nn NOT NULL (order_id ,prod_id)
    ,CONSTRAINTS oi_uk UNIQUE (order_id ,prod_id)
    ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));

設問から、正しい選択肢を見つける要素は「データ型」と「制約」であることが分かります。

データ型に関しては、桁数の指定が明記されていなければ、数値型の場合はNUMBERで十分です。

文字型は、固定長が最適だと読み取れるならCHAR、そうでなければVARCHAR2が使用してあるものを選択すればいいでしょう。 格納するデータのサイズが大きければ、LONGCLOBですが、問1で説明したようにLONGは制限事項が多いので、それを匂わすことが書いてあればCLOBが正解になるはずです。

日付型には、DATETIMESTAMPINTERVALがありますが、設問中にタイムゾーンを意識する必要があることが書いてない限り、DATEを選択すれば正解です。INTERVALは問2で説明したように期間を扱うデータ型ですから、「注文日は○年○月○日」を管理するのには使わないですね。よって、この時点で選択肢eは不正解と判断しましょう。

制約については、次の点に着目して正解を見つけましょう。

  • 列制約と表制約のどちらで宣言されているか
  • 列制約と表制約の構文の違い

では、実行例を見ながら、各選択肢を確認していきます。

選択肢a

まず、「列制約と表制約のどちらで宣言されているか」を確認してみましょう。 「ORDER_IDPROD_IDの組み合わせの値を一意にして、NULL値は設定できないようにする」にはPRIMARY KEY制約を使用するのが最適だと思いますが、UNIQUE制約とNOT NULL制約の組み合わせでも実現できます。選択肢aは組み合わせる方法を使っています。

このとき、注意するべきことは、NOT NULL制約は、列制約でのみ宣言ができるということです。言い換えると、表制約でNOT NULL制約を宣言している選択肢は不正解だということです(選択肢eは不正解)。 そして、複数の列を組み合わせて制約を設定する場合は、表制約を使用しなければいけません。選択肢aは「ORDER_IDPROD_IDの組み合わせの値を一意」にするためには表制約が使用されています。

次に「列制約と表制約の構文の違い」を確認します。 まず、表制約ではすべての列を宣言した後に制約を定義するので、制約タイプの後に、制約を定義する列を明記する必要があります。 例えば、制約タイプがUNIQUE、制約を定義する列が(order_id,prod_id)の場合、表制約の記述はUNIQUE(order_id,prod_id)となります。

さらに、FOREIGN KEY制約に関しては、列制約ではFOREIGN KEYという制約のタイプを表すキーワードは不要で、参照先(references 表名(列名))のみ指定します。

選択肢aは以上のことが満たされており、CHECK制約とDEFAULTの定義も適切なので、正解です。

SQL> --選択肢a
SQL> CREATE TABLE order_items
  2  (order_id   NUMBER NOT NULL
  3  ,prod_id    NUMBER NOT NULL REFERENCES products(prod_id)
  4  ,order_date DATE DEFAULT SYSDATE
  5  ,qty        NUMBER CHECK (qty >= 1)
  6  ,CONSTRAINTS oi_uk UNIQUE(order_id ,prod_id));

表が作成されました。

選択肢b

選択肢bで着目する点は、2つあります。 1つは、FOREIGN KEY制約が表制約で定義してあることです。選択肢aの解説で述べたように、表制約の場合にはFOREIGN KEYという制約のタイプを表すキーワードが必要です。

次に着目する点は、1つの列に対して2つの制約を同時に列制約で宣言していることです。 次の実行例から確認できるように、列制約では1つの列に2つの制約を同時に宣言することが可能です。 また、CONSTRAINTSキーワードは制約名を定義しているだけなので、省略できます(デフォルト名が適用されるだけ)。 つまり、選択肢bのCREATE TABLE文は、構文としては間違っていません。表も作成されます。けれども、実際に値を挿入してみると、設問の要求どおりではないことが分かります。

SQL> --選択肢b
SQL> CREATE TABLE order_items
  2  (order_id   NUMBER NOT NULL UNIQUE
  3  ,prod_id    NUMBER NOT NULL UNIQUE
  4  ,order_date DATE DEFAULT SYSDATE
  5  ,qty        NUMBER CHECK (qty >= 1)
  6  ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));

表が作成されました。

SQL> insert into order_items values(1,100,SYSDATE,2);

1行が作成されました。

SQL> insert into order_items values(2,100,SYSDATE,4);
insert into order_items values(2,100,SYSDATE,4)
*
行1でエラーが発生しました。:
ORA-00001: 一意制約(HR.SYS_C007014)に反しています

設問では「ORDER_IDPROD_IDの組み合わせの値を一意に」といっているのに、選択肢bではORDER_IDPROD_IDのそれぞれで値の一意チェックが入っています。設問の条件に沿えば、(ORDER_ID,PROD_ID)=(1,100)(ORDER_ID,PROD_ID)=(2,100)は挿入できていいのに、実行してみると「prod_id列に挿入しようとしている「100」が重複している」といってエラーになっています。

このように、選択肢bは表の作成はできても、設問の意図に適した表ではないので不正解です。

選択肢c

選択肢cは、「ORDER_IDPROD_IDの組み合わせの値を一意にして、NULL値は設定できないようにする」という要件をPRIMARY KEY制約で実現しています。選択肢cは正解です。そのほかの要件に関しては、選択肢aとbで説明したとおりです。

SQL> --選択肢c
SQL>  CREATE TABLE order_items
  2  (order_id   NUMBER
  3  ,prod_id    NUMBER
  4  ,order_date DATE DEFAULT SYSDATE
  5  ,qty        NUMBER CHECK (qty >= 1)
  6  ,CONSTRAINTS oi_pk PRIMARY KEY(order_id ,prod_id)
  7  ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));

表が作成されました。

選択肢d

選択肢aの解説で、列制約でしか定義できないのはNOT NULLと説明しましたが、DEFAULTも列制約でしか定義できません。 厳密にいうと、DEFAULTは制約ではなく、列制約や表制約という言葉を使って理解するのはおかしいので、DEFAULTは列ごとに定義すると覚えてください。したがって、あたかも表制約で定義しているかのような選択肢dは不正解です。

SQL> --選択肢d
SQL>  CREATE TABLE order_items
  2  (order_id   NUMBER
  3  ,prod_id    NUMBER
  4  ,order_date DATE
  5  ,qty        NUMBER
  6  ,CONSTRAINTS oi_df DEFAULT (order_date = SYADATE)
  7  ,CONSTRAINTS oi_ck CHECK (qty >= 1)
  8  ,CONSTRAINTS oi_pk PRIMARY KEY(order_id ,prod_id)
  9  ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));
,CONSTRAINTS oi_df DEFAULT (order_date = SYADATE)
                   *
行6でエラーが発生しました。:
ORA-00904: : 無効な識別子です。

選択肢e

選択肢eも不正解です。 選択肢aで説明したとおり、order_date列にINTERVAL型を使用しているので要件を満たしていないことと、NOT NULL制約を表制約で定義しようとしていることが不正解の理由です。

SQL> --選択肢e
SQL>  CREATE TABLE order_items
  2  (order_id   NUMBER
  3  ,prod_id    NUMBER
  4  ,order_date INTERVAL YEAR TO MONTH DEFAULT SYSDATE
  5  ,qty        NUMBER CHECK (qty >= 1)
  6  ,CONSTRAINTS oi_nn NOT NULL (order_id ,prod_id)
  7  ,CONSTRAINTS oi_uk UNIQUE (order_id ,prod_id)
  8  ,CONSTRAINTS oi_fk FOREIGN KEY(prod_id) REFERENCES products(prod_id));
,CONSTRAINTS oi_nn NOT NULL (order_id ,prod_id)
                   *
行6でエラーが発生しました。:
ORA-00904: : 無効な識別子です。

次のページ
順序

この記事は参考になりましたか?

  • Facebook
  • X
  • Pocket
  • note
  • hatena
めざせオラクルマスターホルダー! Oracle DB 12c SQL基礎 弱点克服スクール連載記事一覧

もっと読む

この記事の著者

林 優子(ハヤシ ユウコ)

日本オラクル株式会社の教育ビジネスのスタートアップを全面的に支援し、バージョン5の頃からOracleに携わるベテラン講師として知る人も多い。Oracle認定講師を表彰するExcellent Instructorを連続受賞。1ランク上のITスペシャリスト育成を目標に、データベース分野にとどまらず「プレゼンテーション」、「ロジカルシンキング」などのトレーニングも手がけている。著書に『オラクルマスター教科書』シリーズ(翔泳社)、『プロとしてのデータモデリング入門』(SBクリエイティブ)など。その他、雑誌執筆、著書・メディア出演も多数。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事をシェア

  • Facebook
  • X
  • Pocket
  • note
  • hatena
HRzine
https://hrzine.jp/article/detail/297 2016/12/15 14:00

Special Contents

AD

Job Board

AD

おすすめ

アクセスランキング

アクセスランキング

イベント

HRzine Day(エイチアールジン・デイ)は、人が活き会社が成長する人事のWebマガジン「HRzine」が主催するイベントです。毎回、人事の重要課題を1つテーマに設定し、識者やエキスパードが持つ知見・経験を、参加者のみなさんと共有しています。

2024年12月6日(金)13:00~15:30

イベントカレンダーを見る

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング