我正在使用SQLAPI从C ++代码连接到SQL-Server数据库。我需要执行一个带有IN子句的简单select语句,该子句中的字符串值作为字符串向量被接收。我们想使用参数化查询,所以要做这样的事情:
std::string getSQLQeury(std::vector<std::string> ids){
std::stringstream sql;
sql << "SELECT ID, Name, DOB FROM Employees WHERE ID IN (";
unsigned int counter = 0;
for each (auto id in ids)
{
sql << ":" << counter + 1;
if (++counter < ids.size())
{
sql << ",";
}
}
sql << ")";
return sql.str();
}
然后
int param_counter = 0;
for each (auto id in ids) {
command.Param(++param_counter).setAsString() = id.c_str();
}
有人可以建议一种更好的方法吗?
答案 0 :(得分:1)
好吧,我不想削弱您的基本问题,我认为这是“执行此操作的好方法是什么?”,但是C ++存在一些基本语法问题。从上面的错误代码中推断出您的意图,我收集了一个目标,即使用任意输入ID集合创建具有通用SQL选择查询的命令合成器。凉。我认为首先使用插入点创建综合模板命令,然后使用其参数替换方案没有任何好处。一次也可以进行综合。编译时正确的版本看起来像这样(通过一些调整使其更可重用)-
$query = $this->getDoctrine()->getManager()
->getRepository(Client::class)
->createQueryBuilder('c')
->select('c.name as client_name, COUNT(s.client) as number_of_sales')
->join('c.sales', 's')
->groupBy('s.client')
->getQuery();
$result = $query->getArrayResult();
现在您可以执行类似-
std::string getSQLQuery(
const std::string& columns
, const std::string& table
, const std::vector<std::string>& ids
){
// Check for empty strings/arrays here - leads to illegal SQL,
// so error out or except on empty ids, columns, or "table".
std::stringstream sql("SELECT ", std::ios_base::out | std::ios_base::ate);
sql << columns << " FROM " << table << " WHERE ID IN ( ";
// Trailing commas are not allowed in SQL, which makes synthesis a little trickier.
// We checked for empty inputs earlier, so we have at least one ID.
auto iter = ids.begin();
sql << *iter++; // add the first (and possibly only) ID
for (; iter != ids.end(); ++iter) { // add the rest (if any) with commas
sql << ", " << *iter;
}
sql << " )"; // <- should this be " );"? Or does SQLAPI++ deal with that?
return sql.str(); // There's a shrink-to-fit method you may want to use here.
}
这将完全跳过第二个替换阶段。 SQLAPI ++参数替换旨在用于具有更严格模板的查询,但是您正在做的事情更加动态。您可以想象也可以使用列的输入数组进一步扩展它,以避免表列表中的语法错误(就像我们在id列表中一样)。另外,由于id通常是数字,因此可以使id数组std::vector<std::string> id_array{ "1", "50", "aardvark" };
SACommand basic_command(connection, getSQLQuery("ID, Name, DOB", "Employees", id_array));
basic_command.Execute();
或任何适合您的特定应用程序的数组。实际上,通过签名-
std::vector<std::uint64_t>
我是新来者,但是长期用户,因此只需提一个问题即可。当您问诸如“任何人都可以提出更好的方法吗?”之类的问题时,答案始终是“是”。那里有很多聪明的人,并且为每个高级问题提供了无穷的解决方案。将来,您想陈述您要解决的问题(在这种情况下不难发现),并且,如果您显示尝试过并失败的解决方案,则应提供有关失败方式的详细信息。对于您提出的代码,失败的最明显原因是语法上错误–编译器不会接受。 “ for each”来自其他一些语言。在C ++中,它类似于“ for(auto id:ids)”。但是,如果您只是尝试显示某种伪代码,则表明您实际上并不知道您现有的方法是否有效,因为尚未尝试过。即使在这种情况下,您也应该说出您对所提出的解决方案不满意的地方(例如使用SQLAPI ++替代方案的不必要的第二步),并具体询问是否有人可以考虑删除该解决方案。我是一个演讲者,我会给出相同的答复,但是为了将来参考,请尽量避免出现以下问题:“以下代码已损坏。有人为我修复了它。”只是FWIW。