JSONからSQL INSERTへ
このコンバータは、ブラウザ内のJSONレコード配列からSQL INSERT文を作成します。列名は二重引用符で囲み、文字列はシングルクォートを二重にしてエスケープし、nullはNULLに、ブール値はTRUEまたはFALSEに変換されます。レコードは同じキーセットを持つ必要があり、データはタブから出ません。
JSONからSQL INSERTへとは
シードデータはJSONに存在します――APIのフィクスチャ、エクスポートされたレポート、テストレコード――ですが、データベースはINSERT文を要求します。この変換は機械的であり、正確に行う価値があります:各レコードが1行に、各キーが列に、そして各値が正しい型のSQLリテラルとして到達する必要があります。エスケープを間違えると文は即座に失敗し、微妙に間違えると3週間後、最初の名前にアポストロフィが含まれるレコードで失敗します。
このコンバータはマルチ行のINSERT文を出力します:1つの二重引用符で囲まれた列リストの後に、各レコードごとにVALUESタプルが続きます。二重引用符は識別子のSQL標準であり、シングルクォートで囲まれた文字列内の埋め込みクォートは二重になります――O''Brienという形式は、準拠したパーサーが1つのリテラルクォートとして読み取ります。数値はそのまま、trueとfalseはTRUEとFALSEに、JSONのnullは引用符のないキーワードNULLになります。対象テーブル名はツールのテーブルフィールドで指定します;以下の例ではpeopleを使用しています。
すべての処理はこのブラウザタブ内で行われます。レコードはブラウザのJSON.parseで解析され、SQLテキストはメモリ内で組み立てられ、ページからリクエストは送信されません――DevToolsのネットワークパネルでは変換中に何も表示されず、サイトのContent-Security-Policyもいかなる発信接続も禁止しています。
行がJSONではなくスプレッドシートのエクスポートにある場合、CSVからSQLへのコンバータはセルごとの型推論を伴うRFC 4180パーサーの上で同じ引用規則を適用します。
このコンバータは厳密なJSON配列のみを受け付けるため、ペイロードがスクリプトやログファイルから来た場合は、まずJSON検証ツールで確認してください;そこで表示されるエラーが、このツールが発生させるエラーです。
変換の実際の動作
エンジンはJSON.parse――ブラウザ自身のRFC 8259パーサー――を使ってJSONを解析し、何かを出力する前に3つのチェックを行います。なぜなら、各失敗モードは無効か、または静かに間違ったSQLを生成するからです:
- 形状:トップレベルはオブジェクトの要素を持つ配列である必要があります;単一のオブジェクトやネストされた配列は、問題のあるインデックスを示すメッセージと共に拒否されます。
- 一貫したキー:すべてのレコードは同じキーセットを持つ必要があります。INSERT文は1つの列リストを宣言するため、他のレコードにないキーを持つレコードはどこにも配置できません――コンバータはNULLを勝手に生成する代わりに、そのキーと行を報告します。
- フラットな値:レコード内にネストされたオブジェクトや配列には、プレーンなSQLリテラルの同等物がないため、背後で文字列化される代わりに、パス名と共に拒否されます。
リテラルのマッピング
各値はJSON型によってレンダリングされ、標準SQL形式のみを使用します:
- 型に関する注意点が1つあります:TRUEとFALSEは標準SQLのブーリアンリテラルであり、PostgreSQLとSQLiteではネイティブに読み取られ、MySQLでは1と0として読み取られます。ブーリアンリテラルを持たないエンジン――例えばSQL ServerのBIT列――は、ステートメント内で1と0を必要とします。そのため、ターゲットがその場合はキーワードを置き換えてください;引用規則とNULLのルールはまったく同じです。
| JSON値 | SQLリテラル |
|---|---|
| "Ada Lovelace" | 'Ada Lovelace' |
| "O'Brien" | 'O''Brien'――クォートが二重になっています |
| null | NULL、引用符なし |
| true / false | TRUE / FALSE |
| 9.5 | 9.5、数値として |
| [1, 2] | 拒否され、パスが示されます |
出力の見た目
以下の作業例は、コンバーターの「サンプルを読み込む」ボタンがpeopleという名前のテーブルに対して生成する正確なペアです:2つのレコード、4つの一貫したキー、そして各興味深いリテラルが1つずつです。2番目のレコードの名前にはアポストロフィが含まれており、出力は標準的な防御策を示しています――クォートが二重になっており、これはどのSQL方言も文字列の終わりではなく単一のリテラルクォートとして読み取ります。そのスコアはnullであり、空文字列ではなくキーワードNULLとして扱われます――測定値がないことと、長さがゼロの測定値の違いです。ブロックをそのままコピーするか、.sqlファイルとしてダウンロードしてください;どちらの場合も完全で終端されたスクリプトです。
データベースにステートメントを取り込む方法
出力は完全で終端されたスクリプトです:SQLコンソールに貼り付けるか、マイグレーションランナー用に.sqlファイルとして保存してください。クリーンなロードのためには、トランザクションで囲んでください――BEGIN;を前に、COMMIT;を後に――そうすれば、スクリプト中間での失敗がシード全体をロールバックし、テーブルの半分が残るのを防ぎます。ステートメントは標準SQL形式のみを使用するため、同じファイルはANSI_QUOTESが有効なPostgreSQL、SQLite、MySQLで変更なく実行されます;ブーリアンに関する上記の注意点だけが、特定のエンジンでは変更が必要になる場合があります。
- psql: 対話型シェルに貼り付けるか、プロンプトから\i seed.sqlを実行します。
- sqlite3: .read seed.sqlを実行するか、シェルからファイルをパイプします。
- GUIツール: 大半のクエリウィンドウは、スクリプト全体を1つのバッチとして受け入れ、行数を報告します。
よくある質問
JSONからSQLコンバータは私のデータをアップロードしますか?
いいえ。解析とSQL生成は、ページ開時に一度だけ読み込まれるJavaScriptを使って、このブラウザタブ内で実行されます。ページにはデータを送信するエンドポイントがなく、そのContent-Security-Policyは発信リクエストをブロックします。主張は検証可能です:DevToolsを開き、ネットワークパネルに切り替え、大きなファイルを変換し、リクエストが表示されないのを確認してください。
なぜ列名は二重引用符で囲まれていますか?
二重引用符で囲まれた識別子はSQL標準であり、キーワードと衝突したり、大文字小文字が混在したりする列名を保護するものです――orderやUserNameという名前の列は、引用符で囲まれてこそ生存できます。PostgreSQL、SQLite、SQL Serverは直接受け入れます;MySQLもANSI_QUOTESモードがオンなら受け入れます。それ以外の場合は、バックティックの同等表現を使用してください。
文字列内のシングルクォートはどのようにエスケープされますか?
二重にすることで、これは標準です:名前O'Brienは'O''Brien'として出力され、準拠したパーサーはそのペアを1つのリテラルクォートとして読み取ります。バックスラッシュでのエスケープ――O\'Brienのように――はMySQLの拡張機能であり、文法エラーや余分なバックスラッシュを他のすべての場所で生成するため、このコンバータは出力しません。
JSONのnullはSQL内で何になりますか?
引用符のないキーワードNULL――SQL自身の不在値を示すマーカーで、空文字列''とは異なります。nullのスコアは測定が行われなかったことを意味します;空文字列は長さゼロの測定値を意味します。コンバータはその区別を維持しますなぜなら、2つを一緒に collapse することは、 populate されたテーブルで元に戻すのが最も難しい間違いの一つだからです。
なぜすべてのレコードに同じキーが必要ですか?
INSERT文は一度だけ列リストを宣言し、すべてのVALUESタプルはまさにその列を埋める必要があるからです。キーが欠けているか、余分なキーを持つレコードは、そのリスト内で定義された場所がありません。コンバータは問題のあるキーと行インデックスを報告するので、最初にレコードを正規化できます――もしそれが意図なら、意図的にnullでギャップを埋めることができます。
なぜ行ごとのステートメントではなく、1つのマルチ行INSERTですか?
ステートメントが少なく、1回の解析、そして典型的にははるかに高速なロード――単一のマルチ行INSERTは、シード用に推奨されるほとんどのバルクロードガイドの形です。出力はセミコロンで終わるため、完全なスクリプトです。もしツールが行ごとのステートメントを好むなら、各VALUESタプルは独自の行にあるため、分割は小さな機械的な編集です。