{
  "assessmentTests": {
    "sql_test": {
      "name": "SQLテスト",
      "desc": "フィルタリング、結合、集約、サブクエリ、ウィンドウ関数に関する30のシナリオ問題——あなたのSQLスキルが、求人票の『SQL習熟度』と一致しているかを判定します。",
      "recommendation": "あなたのSQLスキルプロフィール",
      "results": {
        "beginner": {
          "name": "初級者",
          "desc": "動作するSELECT文を書くことはでき、複数の条件でフィルタリングできますが、あなたが外した問題は、構文というより、NULL処理と結合のしくみに集中しています——列をNULLと比較するときに = で比較する、LEFT JOINが実際に何を保持するか、BETWEENの境界がどう動くか。これは『データベースが下手』という話ではなく、標準化されたSQLの特定のルールであり、試行錯誤でSQLを学んだ人が同じくらい引っかかる内容です。仕事で重要なのは、こうしたルール一つひとつが、クエリが正しく見えても実際には間違った行数を返す場所だからです。",
          "recommendation": "3つのテーマから始めましょう、この順で。WHERE col = NULLが絶対にマッチしない理由（そしてIS NULLが必須な理由）、INNER JOINはマッチしない行を落とし、LEFT JOINは保持すること、BETWEENが正確にどの境界を含むか。Mode AnalyticsのSQLチュートリアルとPostgreSQLドキュメンテーションは、いずれも3つすべてを実行可能な例でカバーしています。"
        },
        "intermediate": {
          "name": "中級者",
          "desc": "日常的なレポーティングクエリは快適にこなします——結合、GROUP BY、ストレートなフィルタリング——定番のダッシュボードやアドホック分析の作業で足を引っ張られることはありません。ここから上級への差は、主として句（clause）の相互作用で何が起きるかです。左結合テーブルにWHERE句を使うと、静かにLEFT JOINがINNER JOINに変わることがある。一対多の結合が行数をファンアウト（扇状に増加）させて、そのあと集約が適用される。NOT INが静かに何も返さなくなることがある。なぜなら、サブクエリにNULLが1つ混じったから。こういったバグは、ざっと眺めたくらいでは見つかりませんが、別のレポートと合計を比較したときに初めて表れます。",
          "recommendation": "各句だけでなく、句が相互作用するしくみに焦点を当てましょう。LEFT JOINの右側の列をWHERE句でフィルタリングすること、一対多結合が集約されるまでに行数を増やすこと、NOT INがNULLの存在で壊れる理由（EXISTS はたいてそうなりません）。それからHAVING vs WHERE。両方の句を個別には知っている人でも、この分け方で引っかかるものです。"
        },
        "advanced": {
          "name": "上級者",
          "desc": "これは、ほぼすべての求人票が『SQL強い』とはこのレベルを指しています。複数結合のクエリを見て、その行数を実行前に予測でき、結果が変わったんだけどなぜかは、変わったの事実だけでなく理由もわかります。ネストされたサブクエリではなく、CTEやウィンドウ関数に手を伸ばすことができます。それが明確な道具だからです。このランクと最上位を分ける要素は、仕事の守備面です。タイが重要なときはどのランキング関数を使うか、トランザクションが同時アクセスのセッションから何を隔離するか、ON DELETEルールを指定しなかった場合にデータベースレベルで実際に何が起きるか、を知ること。",
          "recommendation": "複数人がアクセスするデータを保護する側面に進みましょう。RANK、DENSE_RANK、ROW_NUMBERがタイの下でどう変わるか、COMMITが何を見える状態にするのか、そして誰に見えるのか、外部キーのDELETEの動作。The IndexニュースレターまたはSQL for Devsのウィンドウ関数とトランザクション分離についての深掘り記事が、次のステップに最適です。"
        },
        "expert": {
          "name": "エキスパート",
          "desc": "すべてのセクション——フィルタリングとNULLセマンティクス、結合と集合演算、集約とサブクエリ、ウィンドウ関数とCTE、トランザクションと制約——で最高点を取りました。実務上、それは初めて見た誰かのマルチ結合レポートクエリを渡されて、構文が言うべき出力だけでなく、なぜその行数が返ってくるのかを説明できるということ。これはより難しく、より価値ある技能です。このレベルでは、クエリ言語そのものが仕事の制限になることはまれです。制限は通常、スキーマ設計か、その下にあるデータの大きさです。",
          "recommendation": "リターンは今、実行計画と設計の側にあります。EXPLAINの出力をクエリが遅い、と仮定する前に読むこと、インデックス戦略を無料な利得ではなく、書き込みコストとのトレードオフとして扱うこと、スキーマが成長するにつれて耐える正規化の判断。採用面接でスクリーニングされている場合は、SQL機能の名前を挙げるのではなく、本番環境で見つけた結合ファンアウトまたはNOT IN/NULLトラップのようなクエリバグの説明をしてください。それは語彙ではなく、推論の力を示します。"
        }
      },
      "questions": [
        {
          "question": "テーブルはnullableのage列を持ちます。SELECT * FROM users WHERE age = NULLを実行すると何行返りますか。ageがNULLに設定されている行がいくつかあっても。",
          "options": [
            {
              "icon": "",
              "label": "ageがNULLのすべての行。=はNULLを他の値のようにマッチさせるから"
            },
            {
              "icon": "",
              "label": "ゼロ——NULLに対してなんかを=と比較するとUNKNOWNが返り、TRUEにはならないため、行はマッチしません。IS NULLが必須です"
            },
            {
              "icon": "",
              "label": "構文エラー——NULLは=の右側に現れません"
            },
            {
              "icon": "",
              "label": "テーブルのすべての行、なぜならNULL比較はデフォルトでTRUEになるから"
            }
          ]
        },
        {
          "question": "SELECT DISTINCT department, role FROM employeesを実行すると、DISTINCTは何の重複を削除しますか？",
          "options": [
            {
              "icon": "",
              "label": "departmentとroleの組み合わせ——両列が別の行と正確にマッチしてはじめて行が削除される"
            },
            {
              "icon": "",
              "label": "departmentの重複値だけ、すべてのroleを保持"
            },
            {
              "icon": "",
              "label": "roleの重複値だけ、すべてのdepartmentを保持"
            },
            {
              "icon": "",
              "label": "何もしない——DISTINCTは1列のときだけ動く"
            }
          ]
        },
        {
          "question": "列nameはWHERE name LIKE 'A_'でフィルタリングされます。これらの値のうち、マッチするのはどれ：'A'、'Al'、'Ana'、'Ally'？",
          "options": [
            {
              "icon": "",
              "label": "'A'——アンダースコアはオプショナルで、ゼロ個以上の文字にマッチ"
            },
            {
              "icon": "",
              "label": "'Al'——アンダースコアはちょうど1文字にマッチするから、LIKE 'A_'はAで始まる2文字の文字列にマッチ"
            },
            {
              "icon": "",
              "label": "'Ana'と'Ally'——アンダースコアは後ろにいくつでも文字があってもマッチ"
            },
            {
              "icon": "",
              "label": "4つすべてマッチする。LIKEは長さを無視するから"
            }
          ]
        },
        {
          "question": "price列はWHERE price BETWEEN 10 AND 20でフィルタリングされます。priceがちょうど10か20の行は含まれますか？",
          "options": [
            {
              "icon": "",
              "label": "いいえ——BETWEENは両端を除外"
            },
            {
              "icon": "",
              "label": "はい——BETWEENは両端を含み、price >= 10 AND price <= 20と等価"
            },
            {
              "icon": "",
              "label": "price = 10だけ含まれる。上端は除外"
            },
            {
              "icon": "",
              "label": "price = 20だけ含まれる。下端は除外"
            }
          ]
        },
        {
          "question": "テーブルordersは10行を持ち、そのうち3行はshipped_dateがNULLです。SELECT COUNT(*) FROM ordersとSELECT COUNT(shipped_date) FROM ordersはそれぞれいくつ返しますか？",
          "options": [
            {
              "icon": "",
              "label": "10、そして10——COUNTはNULLに関わらず常に行を数える"
            },
            {
              "icon": "",
              "label": "7、そして7——両方ともNULLの行をスキップ"
            },
            {
              "icon": "",
              "label": "10、そして7——COUNT(*)はすべての行を数え、COUNT(column)はその列がNULLでない行だけ数える"
            },
            {
              "icon": "",
              "label": "10、そして3——COUNT(column)はNULL値だけを数える"
            }
          ]
        },
        {
          "question": "SELECT name, salary FROM employees ORDER BY 2 DESCを実行すると、この2は何を指しますか？",
          "options": [
            {
              "icon": "",
              "label": "構文エラー——ORDER BYは列名だけを受け付け、番号は受け付けない"
            },
            {
              "icon": "",
              "label": "結果の2番目の行"
            },
            {
              "icon": "",
              "label": "タイブレーカーとして使う2というリテラル値"
            },
            {
              "icon": "",
              "label": "SELECTリストの2番目の列、salary——ORDER BYは列の位置番号を速記として受け付ける"
            }
          ]
        },
        {
          "question": "標準SQLでは、'Ana' || ' ' || 'Lee'はどう評価されますか？",
          "options": [
            {
              "icon": "",
              "label": "構文エラー——SQLに連結演算子はない"
            },
            {
              "icon": "",
              "label": "3——||はブール値のORとして扱われ、カウントを返す"
            },
            {
              "icon": "",
              "label": "'AnaLee'——||はスペースを保持せず連結"
            },
            {
              "icon": "",
              "label": "'Ana Lee'——||は標準SQLの文字列連結演算子"
            }
          ]
        },
        {
          "question": "WHERE status IN ('open', 'pending', 'review')と完全に等価なのはどれ？",
          "options": [
            {
              "icon": "",
              "label": "WHERE status = 'open' AND status = 'pending' AND status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status != 'open' OR status != 'pending' OR status != 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status = 'open' OR status = 'pending' OR status = 'review'"
            },
            {
              "icon": "",
              "label": "WHERE status LIKE 'open,pending,review'"
            }
          ]
        },
        {
          "question": "customersは100行あり、そのうち20行は一度も注文をしていません。SELECT c.id FROM customers c INNER JOIN orders o ON c.id = o.customer_idを実行すると、注文がない20人の顧客は結果に現れますか？",
          "options": [
            {
              "icon": "",
              "label": "はい、1回ずつ、o.idはNULLで表示される"
            },
            {
              "icon": "",
              "label": "はい、ただし彼らもWHERE句に現れる場合だけ"
            },
            {
              "icon": "",
              "label": "いいえ——INNER JOINは両テーブルにマッチする行だけ返すため、注文がない顧客は完全に落ちます"
            },
            {
              "icon": "",
              "label": "はい。ただし、orders内の列数ごとに1回ずつ複製"
            }
          ]
        },
        {
          "question": "あなたは注文があるかないか関わらずすべての顧客が欲しいので、SELECT c.id, o.total FROM customers c LEFT JOIN orders o ON c.id = o.customer_id WHERE o.total > 100を書きます。これでも注文がない顧客が返りますか？",
          "options": [
            {
              "icon": "",
              "label": "いいえ——WHERE句でo.totalをフィルタリングすると、LEFT JOINが作ったNULL行を破棄し、INNER JOINのように動く"
            },
            {
              "icon": "",
              "label": "はい——LEFT JOINは常にcustomersのすべての行を保持し、その後に何があっても関係ない"
            },
            {
              "icon": "",
              "label": "はい。注文がない顧客についてはo.totalは0で表示"
            },
            {
              "icon": "",
              "label": "いいえ——LEFT JOINはWHERE句が追加されると、自動的にRIGHT JOINに変わる"
            }
          ]
        },
        {
          "question": "employeesテーブルはid列とmanager_id列を持ち、manager_idは別の行のidを指します。各従業員の横にマネージャーの名前を表示するには、テーブルを自分に結合する：SELECT e.name, m.name FROM employees e JOIN employees m ON e.manager_id = m.id。このパターンの名前は？",
          "options": [
            {
              "icon": "",
              "label": "クロス結合——すべての従業員がすべてのマネージャーにマッチ"
            },
            {
              "icon": "",
              "label": "再帰結合——管理チェーン全体をフェッチ"
            },
            {
              "icon": "",
              "label": "自己結合——同じテーブルが2つの異なるエイリアスで自分に結合される"
            },
            {
              "icon": "",
              "label": "これは無効なSQL——テーブルを自分に結合することはできない"
            }
          ]
        },
        {
          "question": "2つのSELECT問い合わせが同じ列を持ち、UNIONで組み合わされます。両方のクエリが同じ行を返す場合、その行は最終結果に何回出現しますか？",
          "options": [
            {
              "icon": "",
              "label": "1回——UNIONは結合結果全体の重複行を削除。UNION ALLなら両方が残る"
            },
            {
              "icon": "",
              "label": "2回——UNIONは両方のクエリのすべての行を保持"
            },
            {
              "icon": "",
              "label": "0回——UNIONは両クエリに現れるあらゆる行を削除"
            },
            {
              "icon": "",
              "label": "どのクエリが最初に行をリストしたかで決まる"
            }
          ]
        },
        {
          "question": "sizesテーブルは3行、colorsテーブルは4行です。SELECT * FROM sizes CROSS JOIN colorsは何行返しますか？",
          "options": [
            {
              "icon": "",
              "label": "7——CROSS JOINは行数を足す"
            },
            {
              "icon": "",
              "label": "12——CROSS JOINは両テーブルのすべての行の組み合わせを返す (3 x 4)"
            },
            {
              "icon": "",
              "label": "3——CROSS JOINは最初のテーブルの行数と同じ行を返す"
            },
            {
              "icon": "",
              "label": "0——CROSS JOINはON条件がないと何も返さない"
            }
          ]
        },
        {
          "question": "ordersは注文#100に1行を持ち、order_itemsは注文#100に3行を持ちます（ラインアイテムごと一行）。SELECT o.id, o.total FROM orders o JOIN order_items i ON o.id = i.order_id WHERE o.id = 100を実行します。注文#100について何行返ってきますか？",
          "options": [
            {
              "icon": "",
              "label": "3——結合は一致するorder_items行ごとに出力行を一つ作るため、注文#100の単一行はラインアイテムごとに一回繰り返される"
            },
            {
              "icon": "",
              "label": "1——ordersが注文#100に一行しかないため、結合はそれ以上生成できない"
            },
            {
              "icon": "",
              "label": "4——注文に対して一行、プラスラインアイテムごとに一行"
            },
            {
              "icon": "",
              "label": "0——一行のテーブルを三行のテーブルに非ユニークキーで結合するのは失敗する"
            }
          ]
        },
        {
          "question": "SELECT c.name, o.id FROM customers c RIGHT JOIN orders o ON c.id = o.customer_idは、以下のどれと同じ行を返しますか？",
          "options": [
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c INNER JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o LEFT JOIN customers c ON c.id = o.customer_id——テーブル順序を入れ替えてRIGHT JOINの代わりにLEFT JOINを使う方法が等価"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON c.id = o.customer_id"
            },
            {
              "icon": "",
              "label": "SELECT c.name, o.id FROM orders o CROSS JOIN customers c"
            }
          ]
        },
        {
          "question": "標準SQLでは、SELECT department, name, AVG(salary) FROM employees GROUP BY departmentを実行します。これは妥当なクエリですか？",
          "options": [
            {
              "icon": "",
              "label": "はい——GROUP BYはdepartmentだけを含む必要があります。なぜなら最初に記載されているから"
            },
            {
              "icon": "",
              "label": "いいえ——nameは選ばれているのに、集約されていないしGROUP BYにも記載されていない。標準SQLは、選ばれたすべての非集約列がGROUP BY句に現れることを要求する"
            },
            {
              "icon": "",
              "label": "はい——SQLは自動的に部門ごとに1つの任意の名前を選ぶ"
            },
            {
              "icon": "",
              "label": "いいえ——AVG()をGROUP BYと同じクエリで組み合わせることはできない"
            }
          ]
        },
        {
          "question": "平均給与が80000を超える部門が欲しい。集約値AVG(salary)の後ろのフィルタリングはどちらの句で——WHEREそれともHAVING？",
          "options": [
            {
              "icon": "",
              "label": "WHERE——HAVINGはUNIONクエリでだけ使われる"
            },
            {
              "icon": "",
              "label": "どちらでも集約関数で同等に動く"
            },
            {
              "icon": "",
              "label": "どちらも不可——集約フィルタリングはサブクエリを必須"
            },
            {
              "icon": "",
              "label": "HAVING——WHERE句はグループ化の前に個別行をフィルタリングし、HAVINGは集約後にグループをフィルタリング"
            }
          ]
        },
        {
          "question": "SELECT salary * 1.1 AS new_salary FROM employees WHERE new_salary > 50000を書きます。これは動きますか？",
          "options": [
            {
              "icon": "",
              "label": "はい——SELECTで定義されたエイリアスは、同じクエリではいつもWHEREで利用可能"
            },
            {
              "icon": "",
              "label": "はい。ただし数字のエイリアスの場合"
            },
            {
              "icon": "",
              "label": "いいえ——ASはWHEREでフィルタリングされるクエリ内で許可されない"
            },
            {
              "icon": "",
              "label": "いいえ——WHEREはSELECTがエイリアスnew_salaryを割り当てる前に評価されるため、エイリアスはまだ存在しない"
            }
          ]
        },
        {
          "question": "SELECT name FROM employees e WHERE salary > (SELECT AVG(salary) FROM employees WHERE department = e.department)。これを相関サブクエリと呼ぶのはなぜ？",
          "options": [
            {
              "icon": "",
              "label": "WHERE句の代わりにJOINを使っているから"
            },
            {
              "icon": "",
              "label": "内部のサブクエリが外部クエリのe.departmentを参照しているため、外部クエリが考える各行について再評価されなければならない"
            },
            {
              "icon": "",
              "label": "1列以上を返すから"
            },
            {
              "icon": "",
              "label": "外部クエリが開始される前に、正確に1回実行されるから"
            }
          ]
        },
        {
          "question": "サブクエリSELECT manager_id FROM employeesはNULL値を返しますが、実のidも返します。SELECT name FROM employees WHERE id NOT IN (SELECT manager_id FROM employees)を実行します。何が起きますか？",
          "options": [
            {
              "icon": "",
              "label": "マネージャーではないすべての従業員を返し、NULLを無視"
            },
            {
              "icon": "",
              "label": "ゼロ行を返す——NOT INリストの1つのNULLがすべての比較をUNKNOWNにさせるため、行はこの条件を満たすことができない"
            },
            {
              "icon": "",
              "label": "NOT INをサブクエリで使えないため、エラーを起す"
            },
            {
              "icon": "",
              "label": "すべての従業員を返す。NULLはワイルドカードとして扱われる"
            }
          ]
        },
        {
          "question": "SELECT name FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id)。これは何を返しますか？",
          "options": [
            {
              "icon": "",
              "label": "ordersに少なくとも1行を持つすべての顧客——EXISTSはサブクエリが行を返すかどうかだけチェックし、その値は何かはチェックしない"
            },
            {
              "icon": "",
              "label": "すべての顧客、なぜならSELECT 1は常にtrueを返すから"
            },
            {
              "icon": "",
              "label": "エラー。サブクエリが列名の代わりに数字を選ぶから"
            },
            {
              "icon": "",
              "label": "正確に1つの注文を持つ顧客だけ"
            }
          ]
        },
        {
          "question": "SELECT name, (SELECT order_id FROM orders WHERE customer_id = c.id) AS last_order FROM customers cを書き、ある顧客はordersに3行を持ちます。このクエリが実行されるとき何が起きますか？",
          "options": [
            {
              "icon": "",
              "label": "最初にマッチするorder_idを返し、他の2つは黙って無視"
            },
            {
              "icon": "",
              "label": "すべての3つのorder_idをコンマ区切りリストで返す"
            },
            {
              "icon": "",
              "label": "その顧客について3行を返す、注文ごと1行"
            },
            {
              "icon": "",
              "label": "実行時エラーを起す——SELECTリスト内のスカラサブクエリは最大1行を返さねばならず、このサブクエリは3行を返す"
            }
          ]
        },
        {
          "question": "4行が最高スコアでタイして、RANK() ORDER BY score DESCを使うと、4行すべてランク1を得ます。1段下の行は何ランクを得ますか？",
          "options": [
            {
              "icon": "",
              "label": "5——RANK()はタイが終わった行の数に等しいギャップを残す"
            },
            {
              "icon": "",
              "label": "2——RANK()はいつもタイの後、ちょうど1でインクリメント"
            },
            {
              "icon": "",
              "label": "1——すべての後続行もランク1を得る"
            },
            {
              "icon": "",
              "label": "4——RANK()はタイの数から数え始める"
            }
          ]
        },
        {
          "question": "4行が最高スコアでタイして、DENSE_RANK() ORDER BY score DESCを使うと、4行すべてランク1を得ます。1段下の行は何ランクを得ますか？",
          "options": [
            {
              "icon": "",
              "label": "5——DENSE_RANK()はRANK()とまったく同じ"
            },
            {
              "icon": "",
              "label": "1——DENSE_RANK()はすべての残りの行に同じランクを割り当てる"
            },
            {
              "icon": "",
              "label": "2——DENSE_RANK()はギャップを残さないため、次の異なる値は常に次の連続ランクを得る"
            },
            {
              "icon": "",
              "label": "3——DENSE_RANK()はタイグループごと1ランクをスキップ"
            }
          ]
        },
        {
          "question": "SUM(amount) OVER (PARTITION BY region ORDER BY amount)がクエリに追加されます。ここでPARTITION BY regionは何をしますか？",
          "options": [
            {
              "icon": "",
              "label": "実行サムをリージョンごとに別に再スタートさせ、結果セット全体で累積する代わりに"
            },
            {
              "icon": "",
              "label": "1つのリージョンに結果をフィルタリング"
            },
            {
              "icon": "",
              "label": "GROUP BYのように行をグループ化してリージョンごと1行に整形"
            },
            {
              "icon": "",
              "label": "和をする前にリージョンをアルファベット順にソート"
            }
          ]
        },
        {
          "question": "ROW_NUMBER() OVER (ORDER BY score DESC)が5行に適用され、2行がスコアで正確にタイしています。2つの行は同じrow numberを受け取ることができますか？",
          "options": [
            {
              "icon": "",
              "label": "はい——タイした行は常に同じrow numberを共有"
            },
            {
              "icon": "",
              "label": "PARTITION BYも使う場合だけ"
            },
            {
              "icon": "",
              "label": "タイが最初か最後の位置にあるか次第"
            },
            {
              "icon": "",
              "label": "いいえ——ROW_NUMBER()は常にすべての行にユニークで厳密に増加する整数を割り当て、値がタイしていても"
            }
          ]
        },
        {
          "question": "WITH high_earners AS (SELECT * FROM employees WHERE salary > 100000) SELECT department, COUNT(*) FROM high_earners GROUP BY department。high_earnersは何ですか？",
          "options": [
            {
              "icon": "",
              "label": "共通テーブル式 (CTE)——名前付き、一時的な結果セット。クエリの残りはテーブルのようにこれを参照できる"
            },
            {
              "icon": "",
              "label": "データベースに永続的に作られたテーブル"
            },
            {
              "icon": "",
              "label": "クエリが終わった後も保持されるビュー"
            },
            {
              "icon": "",
              "label": "別々に呼び出されねばならないストアドプロシージャ"
            }
          ]
        },
        {
          "question": "列がPRIMARY KEYとして宣言されます。その列がNULLな行をインサートできますか？",
          "options": [
            {
              "icon": "",
              "label": "はい——PRIMARY KEYは唯一性だけを強制し、NULL-nessではない"
            },
            {
              "icon": "",
              "label": "はい。ただしNULL行は1つだけ許可される。UNIQUE制約と同じ"
            },
            {
              "icon": "",
              "label": "いいえ——PRIMARY KEY列は暗黙的にNOT NULLで、それへのNULLインサートは拒否される"
            },
            {
              "icon": "",
              "label": "列がデフォルト値も持つか次第"
            }
          ]
        },
        {
          "question": "オープンなトランザクション内で、UPDATEを実行しましたが、まだCOMMITを実行していません。データベースの第2の、別のコネクションから、そのアップデートは見えますか？",
          "options": [
            {
              "icon": "",
              "label": "はい——すべてのコネクションはすべての書き込みを即座に見ます"
            },
            {
              "icon": "",
              "label": "はい。ただし第2のコネクションがトランザクションを開く場合だけ"
            },
            {
              "icon": "",
              "label": "どのテーブルが更新されたかに依存"
            },
            {
              "icon": "",
              "label": "いいえ——コミットされていない変更は、その変更を行ったトランザクション内だけで見え、COMMITがそれを永続的にして他に見えるようにするまで"
            }
          ]
        },
        {
          "question": "products.category_idはcategories.idを参照するFOREIGN KEY制約を持ちます。それでもproductsがそれを指す間に、ON DELETEルールを指定せずに、categoriesから行をDELETEしようとします。何が起きますか？",
          "options": [
            {
              "icon": "",
              "label": "category行は削除され、マッチするproducts.category_id値は自動的にNULLに設定"
            },
            {
              "icon": "",
              "label": "category行は削除され、それを参照したあらゆるproductは同様に削除"
            },
            {
              "icon": "",
              "label": "DELETEは拒否される——デフォルトの外部キーの振る舞いは、従属行がまだそれを指している間、参照される行の削除をブロック"
            },
            {
              "icon": "",
              "label": "DELETEは無言で成功し、productのcategory_idをもう存在しないcategoryに指したまま放置"
            }
          ]
        }
      ],
      "optionOrderVersion": "e0466e547cfd8a45"
    }
  }
}
