我要运行此查询:
string query = @"SELECT *
FROM hint
WHERE addedSessionId IN (x, y, z, ............)";
if (_connSource.State != ConnectionState.Open)
_connSource.Open();
MySqlCommand cmd = new MySqlCommand(query, _connSource);
MySqlDataReader r = cmd.ExecuteReader();
List<Hint> lstHint = new List<Hint>();
while (r.Read())
{
Hint h = new Hint(Convert.ToInt32(r[0]), Convert.ToInt32(r[1]),
Convert.ToString(r[2]), Convert.ToInt32(r[3]),
Convert.ToInt32(r[4]));
h.addedSessionId = (Guid)r[5];
lstHint.Add(h);
}
r.Close(); //important
在上面的代码中,如何将值x, y, z etc
传递给查询本身? x, y, z etc
不是int或string而是字节数组。在我的代码中,它们是.net Guid字段,但我将它作为二进制值保存在db中,方法是将其转换为字节数组。
我可以通过参数化方式实现我想要的目的,如下所示:
string query = @"SELECT *
FROM hint
WHERE addedSessionId = @newSessionId";
if (_connSource.State != ConnectionState.Open)
_connSource.Open();
List<Hint> lstHint = new List<Hint>();
foreach (List<Guid> myGuid in lstGuid)
{
MySqlCommand cmd = new MySqlCommand(query, _connSource);
cmd.Parameters.AddWithValue("newSessionId", myGuid.ToByteArray());
MySqlDataReader r = cmd.ExecuteReader();
while (r.Read())
{
int id = Convert.ToInt32(r[0]);
if (IsThisEntryAlreadyAdded(id, lstHint))
continue;
Hint h = new Hint(id, Convert.ToInt32(r[1]),
Convert.ToString(r[2]), Convert.ToInt32(r[3]),
Convert.ToInt32(r[4]));
h.addedSessionId = (Guid)r[5];
lstHint.Add(h);
}
r.Close(); //important
}
第二种方法的问题在于其相对速度非常慢。这里不仅需要对数据库运行很多次查询,而且每次我需要通过运行此IsThisEntryAlreadyAdded
函数来确保是否尚未添加该特定条目。
我的问题是如何在非参数化查询中传递对象(在我的情况下是字节数组)?如果它不可能,我的问题是有没有办法让我的查询更快?
答案 0 :(得分:1)
以下是示例(未经过测试的伪代码)我想象可以做到这一点:
string query = @"SELECT * FROM hint WHERE addedSessionId IN (";
MySqlCommand cmd = new MySqlCommand(query, _connSource);
int i = 0;
foreach (List<Guid> myGuid in lstGuid)
{
query = string.Format("{0}@param{1}", query, i);
cmd.Parameters.AddWithValue(string.Format("@param{0}", i), myGuid.ToByteArray());
i++;
if(i != lstGuid.Count) query = string.Format("{0},", query);
}
query = string.Format("{0})", query);
cmd.CommandText = query;
//Here you have command with constructed query and params
答案 1 :(得分:1)
IN (
子句的数量非常大时,我可以超过允许的最大数据包大小,因此查询根本不会运行。
所以这就是我最终得到的结果,对于大型表来说,更快:
string query = @"SELECT *
FROM hint
WHERE addedSessionId IN (" + GetStringValuesFromGuidList() + ")";
void GetStringValuesFromGuidList()
{
string guids = null;
for (int i = 0; i < lstGuid.Count; i++)
{
guids += "'" + UTF8Encoding.Default.GetString(lstGuid[i].ToByteArray()).Replace("\\", "\\\\").Replace("'", "''") + "'";
if (i < lstGuid.Count - 1)
guids += ", ";
}
return guids;
}
我将Guids转换为其字符串表示形式,然后将其传递给MySQL进行等效字符串搜索的查询。
对于数量有限的条目,参数化查询(Reinuz的回答)是最好的。对于非常大的值,请转到字符串搜索
编辑: UTF8Encoding
应该使用的.Default
取决于数据库的字符集是否为unicode等。在大多数情况下,我在'
取得了成功。此外,二进制的字符串表示将具有保留字符。因此,请使用\
或{{1}}