SQL 在 C# 中使用字符串生成器查询
SQL Query with String Builder in C#
我是 C# 的新手,当我尝试使用 stringbuilder 执行 sql 查询时,我 运行 遇到了一些问题。
这是 table 的一部分,命名为:
| ID | Name | InternalID |
|:----:|:---------:| :---------:|
| 1 | Emory Lu | 84765 |
| ... | ... | ... |
| 8 | John Smith| 52455 |
| 9 | John smith| 49 |
| ... | ... | ... |
请注意,在此 table 中,John Smith 被分配了两个不同的 InternalID(字符串类型)。在第二条记录中,他的姓氏以小写“s”开头。
我在输入员工姓名时对 select 员工的 InternalID(字符串类型)执行了一个简单的 sql 查询:
public DataTable findInternalID(string name)
{
RecordConnection.Open();
DataTable output = new DataTable();
OleDbCommand bdCommand = RecordConnection.CreateCommand() as OleDbCommand;
StringBuilder x = new StringBuilder();
// SELECT InternalID FROM EmployeeList WHERE Name = "(name)"
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine($"WHERE Name LIKE '%{name}%'");
bdCommand.CommandText = x.ToString();
_dataAdapter = new OleDbDataAdapter(bdCommand);
_dataAdapter.Fill(output);
RecordConnection.Close();
return output;
}
这段代码适用于只有一条记录的员工,但对于有多条记录的员工,它会同时填充所有 InternalID 记录和输出,因为这一行:
x.AppendLine($"WHERE Name LIKE '%{name}%'");
所以我尝试将LIKE关键字改成“=”:
x.AppendLine($"WHERE Name = '%{name}%'");
但这给了我一个错误。
如何编辑我的代码,以便在输入“John Smith”时仅输出“52455”而输入“John smith”仅输出“49”。
在main函数下,我写了一段代码来测试这个功能:
string name = "John Smith"; // or John smith
DataTable output = _accessManager.findInternalID(name);
String message = result.Rows[0][0].ToString(); // Or ROWS[1][0]
MessageBox.Show(message);
顺便说一句,我用的是 MS Access :)
=================问题解决了! ====================
非常感谢大家帮助我。我考虑了大家的建议,这是我的最终代码。我使用了 StrComp()
功能,该功能非常适合在 MS Access 中执行区分大小写的 sql 查询:
public DataTable findInternalID(string name)
{
RecordConnection.Open();
DataTable output = new DataTable();
OleDbCommand bdCommand = RecordConnection.CreateCommand() as OleDbCommand;
StringBuilder x = new StringBuilder();
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine($"WHERE StrComp(Name, @name, 0) = 0;");
bdCommand.CommandText = x.ToString();
bdCommand.Parameters.AddWithValue("name", $"{name}");
_dataAdapter = new OleDbDataAdapter(bdCommand);
_dataAdapter.Fill(output);
RecordConnection.Close();
return output;
}
仅供将来参考的一些注意事项,如果您使用的是 MS Access,则 COLLATE
和 varbinary(MAX)
不适合您。
在SQL服务器中你只需要case-sensitive搜索,试试这个!
x.AppendLine($"WHERE Name = '{name}' COLLATE Latin1_General_CS_AS ");
在MS-Access,试试这个!
x.AppendLine($"WHERE StrComp(Name, '{name}', 0) = 0");
对于初学者,您永远不应该通过将用户提供的数据连接到查询字符串中来构建 SQL 查询。这样做会使您容易受到 SQL Injection 的攻击。相反,您应该使用查询参数将用户提供的数据传递给您的查询。
重写原始函数以使用参数可能如下所示:
public DataTable findInternalID(string name)
{
RecordConnection.Open();
var output = new DataTable();
var bdCommand = RecordConnection.CreateCommand() as OleDbCommand;
var x = new StringBuilder();
// SELECT InternalID FROM EmployeeList WHERE Name = "(name)"
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine("WHERE Name LIKE @name");
bdCommand.CommandText = x.ToString();
bdCommand.Parameters.AddWithValue("name", $"%{name}%");
_dataAdapter = new OleDbDataAdapter(bdCommand);
_dataAdapter.Fill(output);
RecordConnection.Close();
return output;
}
至于区分大小写的查询,我不能说我真的做到了。看起来 COLLATE
应该可以工作,假设您的数据库是 SQL 服务器。
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine("WHERE Name = @name COLLATE Latin1_General_CP1_CS_AS");
或者,也许转换为 varbinary(MAX)
来比较字节?
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine("WHERE CAST(Name as varbinary(MAX)) = CAST(@name AS varbinary(MAX))");
此外,最后一点,您根本不需要使用 StringBuilder
。如果您想跨多行格式化语句,您可以只使用带有 @
标识符的逐字 string
。
string commandText = @"SELECT InternalId
FROM EmployeeList
WHERE Name = @name COLLATE Latin1_General_CP1_CS_AS";
我是 C# 的新手,当我尝试使用 stringbuilder 执行 sql 查询时,我 运行 遇到了一些问题。
这是 table 的一部分,命名为:
| ID | Name | InternalID |
|:----:|:---------:| :---------:|
| 1 | Emory Lu | 84765 |
| ... | ... | ... |
| 8 | John Smith| 52455 |
| 9 | John smith| 49 |
| ... | ... | ... |
请注意,在此 table 中,John Smith 被分配了两个不同的 InternalID(字符串类型)。在第二条记录中,他的姓氏以小写“s”开头。
我在输入员工姓名时对 select 员工的 InternalID(字符串类型)执行了一个简单的 sql 查询:
public DataTable findInternalID(string name)
{
RecordConnection.Open();
DataTable output = new DataTable();
OleDbCommand bdCommand = RecordConnection.CreateCommand() as OleDbCommand;
StringBuilder x = new StringBuilder();
// SELECT InternalID FROM EmployeeList WHERE Name = "(name)"
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine($"WHERE Name LIKE '%{name}%'");
bdCommand.CommandText = x.ToString();
_dataAdapter = new OleDbDataAdapter(bdCommand);
_dataAdapter.Fill(output);
RecordConnection.Close();
return output;
}
这段代码适用于只有一条记录的员工,但对于有多条记录的员工,它会同时填充所有 InternalID 记录和输出,因为这一行:
x.AppendLine($"WHERE Name LIKE '%{name}%'");
所以我尝试将LIKE关键字改成“=”:
x.AppendLine($"WHERE Name = '%{name}%'");
但这给了我一个错误。
如何编辑我的代码,以便在输入“John Smith”时仅输出“52455”而输入“John smith”仅输出“49”。
在main函数下,我写了一段代码来测试这个功能:
string name = "John Smith"; // or John smith
DataTable output = _accessManager.findInternalID(name);
String message = result.Rows[0][0].ToString(); // Or ROWS[1][0]
MessageBox.Show(message);
顺便说一句,我用的是 MS Access :)
=================问题解决了! ====================
非常感谢大家帮助我。我考虑了大家的建议,这是我的最终代码。我使用了 StrComp()
功能,该功能非常适合在 MS Access 中执行区分大小写的 sql 查询:
public DataTable findInternalID(string name)
{
RecordConnection.Open();
DataTable output = new DataTable();
OleDbCommand bdCommand = RecordConnection.CreateCommand() as OleDbCommand;
StringBuilder x = new StringBuilder();
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine($"WHERE StrComp(Name, @name, 0) = 0;");
bdCommand.CommandText = x.ToString();
bdCommand.Parameters.AddWithValue("name", $"{name}");
_dataAdapter = new OleDbDataAdapter(bdCommand);
_dataAdapter.Fill(output);
RecordConnection.Close();
return output;
}
仅供将来参考的一些注意事项,如果您使用的是 MS Access,则 COLLATE
和 varbinary(MAX)
不适合您。
在SQL服务器中你只需要case-sensitive搜索,试试这个!
x.AppendLine($"WHERE Name = '{name}' COLLATE Latin1_General_CS_AS ");
在MS-Access,试试这个!
x.AppendLine($"WHERE StrComp(Name, '{name}', 0) = 0");
对于初学者,您永远不应该通过将用户提供的数据连接到查询字符串中来构建 SQL 查询。这样做会使您容易受到 SQL Injection 的攻击。相反,您应该使用查询参数将用户提供的数据传递给您的查询。
重写原始函数以使用参数可能如下所示:
public DataTable findInternalID(string name)
{
RecordConnection.Open();
var output = new DataTable();
var bdCommand = RecordConnection.CreateCommand() as OleDbCommand;
var x = new StringBuilder();
// SELECT InternalID FROM EmployeeList WHERE Name = "(name)"
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine("WHERE Name LIKE @name");
bdCommand.CommandText = x.ToString();
bdCommand.Parameters.AddWithValue("name", $"%{name}%");
_dataAdapter = new OleDbDataAdapter(bdCommand);
_dataAdapter.Fill(output);
RecordConnection.Close();
return output;
}
至于区分大小写的查询,我不能说我真的做到了。看起来 COLLATE
应该可以工作,假设您的数据库是 SQL 服务器。
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine("WHERE Name = @name COLLATE Latin1_General_CP1_CS_AS");
或者,也许转换为 varbinary(MAX)
来比较字节?
x.AppendLine("SELECT InternalID ");
x.AppendLine("FROM EmployeeList ");
x.AppendLine("WHERE CAST(Name as varbinary(MAX)) = CAST(@name AS varbinary(MAX))");
此外,最后一点,您根本不需要使用 StringBuilder
。如果您想跨多行格式化语句,您可以只使用带有 @
标识符的逐字 string
。
string commandText = @"SELECT InternalId
FROM EmployeeList
WHERE Name = @name COLLATE Latin1_General_CP1_CS_AS";