sql >> データベース >  >> RDS >> PostgreSQL

Golangで*DB.exec()またはプリペアドステートメントを使用するのはなぜですか?

    「db.Exec()を使用する理由」:

    db.Execを使用できるのは事実です およびdb.Query 同じSQLステートメントを実行するために交換可能ですが、2つのメソッドは異なるタイプの結果を返します。ドライバによって実装された場合、結果はdb.Execから返されます db.Queryがクエリの影響を受けた行数を知ることができます 代わりにrowsオブジェクトを返します。

    たとえば、DELETEを実行するとします。 ステートメントとあなたはそれによって削除された行の数を知りたいです。適切な方法で行うことができます:

    res, err := db.Exec(`DELETE FROM my_table WHERE expires_at = $1`, time.Now())
    if err != nil {
        panic(err)
    }
    
    numDeleted, err := res.RowsAffected()
    if err != nil {
        panic(err)
    }
    print(numDeleted)
    

    または、より冗長で客観的にコストのかかる方法:

    rows, err := db.Query(`DELETE FROM my_table WHERE expires_at = $1 RETURNING *`, time.Now())
    if err != nil {
        panic(err)
    }
    defer rows.Close()
    
    var numDelete int
    for rows.Next() {
        numDeleted += 1
    }
    if err := rows.Err(); err != nil {
        panic(err)
    }
    print(numDeleted)
    

    postgresCTEの組み合わせでこれを行うことができる3番目の方法があります。SELECT COUNTdb.QueryRow およびrow.Scan しかし、db.Execと比較した場合のアプローチがいかに不合理であるかを示すために例は必要ないと思います。 。

    db.Execを使用するもう1つの理由 db.Queryを介して 返される結果を気にしないとき、必要なのはクエリを実行してエラーがあったかどうかを確認することだけのときです。このような場合、これを行うことができます:

    if _, err := db.Exec(`<my_sql_query>`); err != nil {
        panic(err)
    }
    

    一方、これを行うことはできません(できますが、すべきではありません):

    if _, err := db.Query(`<my_sql_query>`); err != nil {
        panic(err)
    }
    

    これを行うと、しばらくすると、プログラムがパニックになり、too many connections openに似たエラーが表示されます。 。これは、返されたdb.Rowsを破棄しているためです。 最初に必須のCloseを作成せずに値 それを呼び出すと、開いている接続の数が増え、最終的にサーバーの制限に達することになります。

    "またはGolangでプリペアドステートメント?":

    あなたが引用した本は正しくないと思います。少なくとも私には、db.Queryかどうかのように見えます callは、使用しているドライバーに応じて、毎回新しいプリペアドステートメントを作成します。

    たとえば、queryDCのこれら2つのセクションを参照してください。 (db.Queryによって呼び出されるエクスポートされていないメソッド ):プリペアドステートメントなしおよびプリペアドステートメントあり。

    本が正しいかどうかに関係なく、db.Stmt db.Queryによって作成されました 内部キャッシュが実行されていない限り、返されたRowsを閉じた後に破棄されます。 物体。代わりに手動でdb.Prepareを呼び出す場合 次に、返されたdb.Stmtをキャッシュして再利用します 頻繁に実行する必要のあるクエリのパフォーマンスを向上させる可能性があります。

    プリペアドステートメントを使用してパフォーマンスを最適化する方法を理解するには、公式ドキュメントを参照してください:https://www.postgresql.org/docs/current/static/sql-prepare.html




    1. SQLServerでのデータベーススキーマの使用

    2. MySQL SELECTはここ数日ですか?

    3. SQLServerの再帰的自己結合

    4. MySQLで交差する代わりに