マナビング基本情報技術者

主キー制約に違反するSQL文はどれか、更新される行数から考える

基本情報技術者試験 令和8年度 問7 / データベース › データ操作

過去問にチャレンジ

令和8年度 問7

次のSQL文によって定義され,値が格納されている"商品"表に対して,制約違反で実行エラーとなるSQL文はどれか。 〔SQL文〕

CREATE TABLE 商品 (商品コード CHAR(4) PRIMARY KEY,商品名 VARCHAR(21), 仕入先コード CHAR(4),仕入単価 INT,在庫数 INT)
令和8年度 問7の図
  1. ア
    DELETE FROM 商品 WHERE 仕入先コード IS NULL
  2. イ
    INSERT INTO 商品 VALUES ('A555','空気清浄機','S005',60000,50)
  3. ウ
    UPDATE 商品 SET 商品コード = 'A666' WHERE 商品コード = 'A444'
  4. エ
    UPDATE 商品 SET 商品コード = 'A777' WHERE 在庫数 >= 20

会話形式の解説

講師講師
この問題で大事なのは、商品コードにPRIMARY KEY、つまり主キーが指定されている点です。主キーの列には「同じ値を二度使えない」「空(NULL)のままにできない」という2つの決まりがあります。4つのSQL文を実行した後に、この決まりが崩れるものを探します。
受験者受験者
表の値と照らし合わせるのですね。私はまず、アがNULLを扱っているので怪しいと思いました。
講師講師
アで条件にしているのは仕入先コードの列です。仕入先コードがNULLの行はA333だけなので、その1行が消えます。仕入先コードは主キーではないので、NULLが入っていても構いません。それに、行を消しても商品コードがかぶったり空になったりはしません。
受験者受験者
削除なら、残った行の商品コードは元のままですね。では、イのINSERTはどうですか。
講師講師
追加する商品コードはA555です。今ある表はA111からA444までなので、どれとも一致しませんし、空でもありません。問題なく1行増えます。
受験者受験者
ウはA444をA666に変える文ですね。A666は表にまだないので、これも大丈夫そうです。
講師講師
そのとおりです。WHERE句で商品コードがA444の行を指定しているので、書き換わるのは1行だけです。新しい値もほかの行とかぶりません。
受験者受験者
エのA777も表にない値です。ウと同じ理由でエラーにならないように見えて、迷っています。
講師講師
そこがこの問題の引っかけです。エは商品コードではなく「在庫数が20以上」で行を選んでいます。条件に合う行がいくつあるか、表で数えてみてください。
受験者受験者
在庫数は、A111が0、A222が50、A333がNULL、A444が20です。>=は20ちょうども入るので、A222とA444の2行が選ばれます。
講師講師
正しく数えられています。在庫数がNULLのA333は、比較しても結果が真にならないので選ばれません。選ばれた2行をどちらもA777にすると、商品コードがA777の行が2つになってしまいます。これは同じ値を二度使えないという決まりに反するので、エラーになります。
受験者受験者
変更後の値が表になくても、2行以上を同じ値にそろえたら重複が生まれるのですね。だから正解はエです。
講師講師
はい。整理すると、INSERTでは追加する値が既存の値とかぶらないか、空でないかを確かめます。UPDATEで主キーを決まった値に書き換えるときは、それに加えて、WHERE句で何行が選ばれるかを必ず数えてください。また、主キー以外の列には今回は制約がないので、そこにNULLがあってもエラーの原因にはなりません。

まとめ

主キー(PRIMARY KEY)を指定した列には、値の重複を許さない性質と、NULLを許さない性質の両方があります。この問題では、在庫数が20以上の行の商品コードをA777に書き換えるUPDATE文がエラーになります。在庫数50のA222と在庫数20のA444の2行が選ばれ、どちらも同じ商品コードになるからです。A777は元の表にない値ですが、複数の行を同じ値に変えれば重複が生まれます。主キーをUPDATEする問題では、新しい値が表にあるかどうかに加えて、WHERE句で選ばれる行数も確認することが大切です。

解答・解説

正解はエです

この問題のテーマ

PRIMARY KEYを指定した列にどんな制約があるかを理解したうえで、表の中身に対して実行すると一意性違反のエラーになるSQL文を選ぶ問題です。正解はエです。

解き方の考え方

まず、主キーの商品コードには「重複しない」「NULLにならない」の2つの制約がかかることを確認します。次に、各SQL文について、WHERE句で何行が対象になるか、実行後の商品コードがどうなるかを表の値と照らし合わせます。そのうえで、実行後に商品コードの重複やNULLが生じる文を探します。エは在庫数20以上の2行(A222とA444)をどちらもA777に書き換えるため、主キーが重複します。したがって正解はエです。

選択肢ごとの解説

  1. ×ア  
    DELETE FROM 商品 WHERE 仕入先コード IS NULL
    アのDELETE文は、仕入先コードがNULLの行を削除します。該当するのはA333の1行だけです。行を削除しても主キーの重複やNULLは生じないので、主キー制約には違反しません。仕入先コードは主キーではないため、この列がNULLであること自体も問題になりません。
  2. ×イ  
    INSERT INTO 商品 VALUES ('A555','空気清浄機','S005',60000,50)
    イのINSERT文で追加する商品コードA555は、既存のA111〜A444のどれとも重複しません。NULLでもないため、主キー制約を満たしたまま挿入できます。
  3. ×ウ  
    UPDATE 商品 SET 商品コード = 'A666' WHERE 商品コード = 'A444'
    ウのUPDATE文は、商品コードがA444の1行だけを対象にします。変更後のA666は表の中でまだ使われていない値なので、重複は起きません。そのためエラーにならずに更新できます。
  4. ○エ  
    UPDATE 商品 SET 商品コード = 'A777' WHERE 在庫数 >= 20
    エのUPDATE文の条件「在庫数 >= 20」は20を含みます。そのため、在庫数50のA222と在庫数20のA444の2行が対象になり、在庫数0のA111とNULLのA333は外れます。2行ともに商品コードがA777になるので主キーが重複し、一意性制約違反でエラーになります。A777はもともと表にない値ですが、更新によって複数の行が同じ値になれば違反です。「表にない値だから大丈夫」と考えると引っかかるので注意してください。

補足

主キー以外の列には制約が付いていないため、アのように仕入先コードがNULLの行があっても、それを削除しても、エラーにはなりません。INSERT文では「既存の値と重複しないか」と「NULLでないか」を確認し、UPDATE文ではさらに「対象行の数」も確認する、と区別して覚えておくと応用できます。

POINT

  • PRIMARY KEYを指定した列は、UNIQUE(重複不可)とNOT NULL(NULL不可)の性質を両方持ちます。
  • UPDATE文で主キーを固定の値に変えるときは、WHERE句で対象になる行が何行あるかを必ず数えます。
  • 対象が2行以上あれば、変更後の値が既存のデータになくても、更新後に重複して制約違反になります。
  • 比較演算子の>=は境界の値を含むので、在庫数がちょうど20の行も対象になります。
  • 在庫数がNULLの行は、比較条件の結果が真にならないため、WHERE句で選ばれません。

※出典:令和8年度 基本情報技術者試験 科目A 問7(一部改変)