在SQLAPI c ++

时间:2019-04-05 06:17:34

标签: c++ sqlapi++

我正在使用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();
    }

有人可以建议一种更好的方法吗?

1 个答案:

答案 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。