Qiita初投稿です。
お手柔らかに。
概要
- SQL文を動的生成する必要があった。
- さらにその中でIN句を使うケースがあった。
- パラメータを渡してもうまくSQLが生成されず、少々ハマった。
実装
※引数のkeysには"1"~"27"の値を渡しています。
hoge.cs
public fugaClass findByKeys(string[] keys)
{
StringBuilder query = new StringBuilder("SELECT * FROM hogeTable");
// WHERE句生成
StringBuilder conditions = new StringBuilder("WHERE key IN (");
for(int i=0; i < keys.length; i++)
{
conditions.Add(" @Val" + generateAlphabet(i));
if (i != keys.Length - 1) conditions.Add(",");
}
IDbParameters params = CreateDbParameters();
for(int i=0; i < keys.length; i++)
{
params.Add("Val" + generateAlphabet(i), DbType.String).Value = key
}
HogeCallback callback = new HogeCallBack
AdoTemplate.QueryWithRowCallback(CommandType.Text, query.ToString(), callback, params);
return callback.result;
}
private string generateAlphabet(int index) {
string str = "";
do {
str = Convert.ToChar(index % 26 + 0x41) + str;
} while ((index = index / 26 - 1) != -1);
return str;
}
生成されるSQL
SELECT * FROM hogeTable WHERE key IN (@ValA, @ValB,...@ValAA)
パラメータを渡した後のSQL
SELECT * FROM hogeTable WHERE key IN ('1', '2',...'1'A)
なんじゃこりゃ。
どうやら同文字列が先に存在したらそっちに値が渡ってしまうようです。(説明下手)
改善
hoge.cs
public fugaClass findByKeys(string[] keys)
{
StringBuilder query = new StringBuilder("SELECT * FROM hogeTable");
// WHERE句生成
StringBuilder conditions = new StringBuilder("WHERE key IN (");
for(int i=0; i < keys.length; i++)
{
conditions.Add(" @Val" + generateAlphabet(i));
if (i != keys.Length - 1) conditions.Add(",");
}
IDbParameters params = CreateDbParameters();
// 降順でパラメータを追加
for(int i=keys.length; i >= 0; i--)
{
params.Add("Val" + generateAlphabet(i), DbType.String).Value = key
}
HogeCallback callback = new HogeCallBack
AdoTemplate.QueryWithRowCallback(CommandType.Text, query.ToString(), callback, params);
return callback.result;
}
private string generateAlphabet(int index) {
string str = "";
do {
str = Convert.ToChar(index % 26 + 0x41) + str;
} while ((index = index / 26 - 1) != -1);
return str;
}
生成されるSQL
SELECT * FROM hogeTable WHERE key IN (@ValA, @ValB,...@ValAA)
パラメータを渡した後のSQL
SELECT * FROM hogeTable WHERE key IN ('1', '2',...'27')
⇒OK!
まとめ
- 連番、連続した文字列でパラメータ文字列を生成した時は降順にセットを行う
- 調べてわかったが、LIKE句で実装すると楽らしい
投稿者はC#初心者です・・・。
素のコードをそのまま張り付けているわけではないので、なにか不備などありましたらご指摘お願いいたします。