2016-06-14 9 views
3

I stillstruggle Go/psqlの準備済み明細の利点を理解してください。ここで準備文を使用すると良いでしょうか?

のは、私が構造

type Brand struct { 
    Id  int  `json:"id,omitempty"` 
    Name  string  `json:"name,omitempty"` 
    Issued_at *time.Time `json:"issued_at,omitempty"` 
} 

とIDが一意のフィールドであるいくつかのテーブルbrandsを、持っていると仮定しましょう。今、私はそのテーブルからidを使って要素を取得したいと思います。

私は、QueryRowを使って次の関数を書くことができます。プリペアドステートメントを使用して

func GetBrand1(id int) (Brand, error) { 
    brand := Brand{} 
    if err := Db.QueryRow("SELECT name, issued_at FROM brands WHERE id = $1", id).Scan(&brand.Name, &brand.Issued_at); err != nil { 
     if err == sql.ErrNoRows { 
      return brand, nil 
     } 

     return brand, err 
    } 

    brand.Id = id 
    return brand, nil 
} 

と私は同じことを行うことができます(私はそれが同じであると思います):

私のアプリケーションでは今
func GetBrand2(id int) (Brand, error) { 
    brand := Brand{} 

    stmt, err := Db.Prepare("SELECT name, issued_at FROM brands WHERE id = $1") 
    if err != nil { 
     return brand, err 
    } 
    defer stmt.Close() 

    rows, err := stmt.Query(id) 
    if err != nil { 
     return brand, err 
    } 
    defer rows.Close() 

    for rows.Next() { 
     rows.Scan(&brand.Name, &brand.Issued_at) 
     brand.Id = id 
     return brand, err 
    } 
    if err = rows.Err(); err != nil { 
     return brand, err 
    } 

    return brand, err 
} 

私は(GetBrand*機能を何度も実行するために計画しています異なるパラメータ)。 Willはこの実装の1つが(SQL-Request/Memory/anythingに関して)別のものよりも好ましいです。あるいは、彼らはどちらも吸うことがあり、私は他の何かをするのがよいでしょう。

私はthisfollowed up linkを読んでいると私は見たこと:

はdb.Query()実際には、準備実行、および準備 文を閉じます。これはデータベースへの3回のラウンドトリップです。あなたが注意しない ている場合は、あなたの アプリケーションが

なりますが、私は後者の場合で準備された文は、関数の終了時に削除されることを考えて、データベースの相互作用の数を3倍にすることができます。

+0

[これは役立つ可能性があります](https://stackoverflow.com/questions/37683218/golang-sql-drivers-prepare-statement/37686891#37686891) – Snowman

答えて

3

これらの例では、おおよそ同じデータベースオーバーヘッドがあります。あなたが多くのステートメントを使うつもりなら、それを一度より広い範囲で準備して、再利用できるようにします。

あなたはそのパターンでデータベースを1回往復するだけです。

+0

この申し立てをバックアップするものはありますか?それが今の立場であるので、私の質問に書いたのと同じ仮定であり、私はこの前提を裏付ける信頼できる情報源を持ちたいと思っています。 –

+1

@SalvadorDaliあなたがリンクしたドキュメントによると、[行]は文を準備して実行し、それを閉じます。 あなたがその声明を一度だけ準備し、同じ準備文を常に実行すると、3に近づくにつれて往復を減らすことになります。 あなたの第1の例と第2の例はおおよそ同じことをしていますすべての関数呼び出しで新しい準備済みのステートメントを作成しています。 –

+0

妥当と思われます。ありがとう、+1 –

0

ユーザー入力と連動してデータベースを使用する場合は、必ず事前に文章を準備する必要があります。

DB挿入(SQL Insertion ex)の危険性があります。

+0

まず第一に、これは私の質問に答えることはできません、パラメータ$ 1の第二のqueryRowも私のためのステートメントを準備します、あなたの答えは本当に正しいわけではありません –

関連する問題