【C#】ループでSQL書くなら絶対にStringBuilderクラスにすべし【MySQL】

C#

はい、本日はC#でループで作ったりするなっがいSQLを作るときはStringBuilderクラスだぞって話し。

スポンサーリンク

StrngBuilderクラスとは?普通のString型との違い


簡単に言うと通常のStringは+=でくっつけてく度メモリ上の領域を食っていきますが、
StringBuilderは一回生成すればそれでOKなので軽くて速いよって事です(雑)
加えて、あんまりそんな場面無いかもですが、もしも最終的な文字列長が予測可能なら、StringBuilder.Capacityプロパティで指定すると更にパフォーマンスが向上します。 先に確保する領域を指定してやる感じですね!

例えばこんな時に使う


大量のレコードが突っ込まれたデータテーブルを元にSQL文を作っていく場合。

Code_string

      // INSERT文設定
      string strSql = "INSERT INTO テーブルX \n";
      strSql += "(ID, 名前, 性別,生年月日) \n ";
      strSql += "VALUES \n ";

      // レコード分ループ
      for (int Cnt = 0; Cnt < Dt.Rows.Count; Cnt++)
      {
          strSql += "('" + Dt.Rows[Cnt]["ID"].ToString() + "',Dt.Rows[Cnt]["ID"].ToString(), Dt.Rows[Cnt]["ID"].ToString() + " ) \n");

          // 最終行以外の場合
          if (Cnt != Dt.Rows.Count - 1)
          {
              strSql += ",";
          }
      }

本番だと何万件置きとかに区切ると思いますが、こんな感じで作成してINSERTする事が結構あります。
でこれ普通のstringで行った形。

これだと冒頭でも書いた通りメモリの無駄遣いが激しく、結果的に処理速度の遅延に直結しています。
数千件とかならそこまで差は出ないですが、Dt.Rows.Countが数十万・数百万とかになってくると偉い違いが出ます。
なので、ループで長いSQLを作成する場合は下記のようにします。

Code_StringBuilder

      System.Text.StringBuilder sbSql = new System.Text.StringBuilder();      
      // INSERT文設定
      string strSql = "INSERT INTO テーブルX \n";
      strSql += "(ID, 名前, 性別,生年月日) \n ";
      strSql += "VALUES \n ";

      for (int Cnt = 0; Cnt < Dt.Rows.Count; Cnt++)
      {
          sbSql.Append("('" + Dt.Rows[Cnt]["ID"].ToString() + "',Dt.Rows[Cnt]["ID"].ToString(), Dt.Rows[Cnt]["ID"].ToString() + " ) \n");

          // 最終行以外の場合
          if (Cnt != Dt.Rows.Count - 1)
          {
              sbSql.Append(",");
          }
      }

Appendが普通のstringでいうところの+=になります。これでどんどん追加を行っていく。
上にも書きましたけども、レコード数に比例して処理速度がダンチなので、
ループで文字列連結時はぜひ StringBuilderクラスを!

追加情報


Append以外にも、Insert(挿入)Remove(削除)Clear(削除)等一通りのメソッドがありますが、
少しだけ変わってるのがLength(長さ)。

普通のstringのLengthは長さを得る為だけのものだけども、StringBuilderのLengthは書き込みも出来てしまう。
例えばsb.Length = 0 とするとクリアが出来る。使う時ないけど


コメント