简体   繁体   English

最佳SQL参数的STL容器

[英]Best stl container for sql parameters

I have to build a dynamic sql query. 我必须建立一个动态的SQL查询。 To proper execute it I have to do it in 3 steps: 为了正确执行它,我必须分3个步骤进行操作:

  1. Prepare statement 准备陈述
  2. Bind Parameters with functions: bindString(string value, int index); 将参数与函数绑定:bindString(string value,int index); bindInt(int value, int index); bindInt(int值,int索引);
  3. Execute it 执行它

Because of the fact, that this query is build dynamically I have to store somewhere proper values for given index. 由于这个事实,该查询是动态构建的,因此我必须在某个地方存储给定索引的适当值。

For example: 例如:

  1. SELECT * FROM Table WHERE A = ? SELECT * FROM Table WHERE A =吗? AND E = '?'; AND E ='?';

  2. SELECT * FROM Table WHERE A = ? SELECT * FROM Table WHERE A =吗? AND B = ? 与B =? AND E = '?'; AND E ='?';

During building query I have to store somewhere that: 在构建查询期间,我必须将存储在以下位置:

In the first case: 在第一种情况下:

  • index 0 is for int A, 索引0代表int A,
  • index 1 is for string E 索引1用于字符串E

In the second case: 在第二种情况下:

  • index 0 is for int A 索引0用于int A
  • index 1 is for int B 索引1用于int B
  • index 2 is for string E 索引2用于字符串E

My best idea is to create two maps: < int, string >, < int, int > and during creating query set in first place indexes and in second place values and then creating two loops, one for strings, the second one for integers and binding parameters in them and it works fine. 我最好的主意是创建两个映射:<int,string>,<int,int>,并在创建查询集的第一位索引和第二位值的过程中,然后创建两个循环,一个循环用于字符串,第二个循环用于整数,在其中绑定参数,效果很好。

However I wonder if is it possible to do everything in one loop using succeeding indexes and in type safety way. 但是,我想知道是否有可能使用后续索引和类型安全方式在一个循环中完成所有操作。

Thank You. 谢谢。

I would consider creating a class to wrap SQL parameters. 我会考虑创建一个包装SQL参数的类。

In fact I would create an abstract class like that : 实际上,我将创建一个抽象类,例如:

SQLParameterBase
{

   std::string toString() = 0;
   void print()
   {
     std::cout << toString();
   }
}

And then a template class : 然后是一个模板类:

template<class ParamType>
SQLParameter : public SQLParameterBase
{
private:
    ParamType value;
public:
    std::string toString()
    {
       // You can use std::ostringstream to convert to string,
       // or create another class (derivated from SQLParameterBase) with very specific values
    }
}

And you could use it like that : 您可以像这样使用它:

SQLParameterBase * params[10];
maps[0] = new SQLParameter<int>();

Hope that will help 希望会有所帮助

Actually it is modified AMDG solution. 实际上是修改后的AMDG解决方案。 Thanks to him! 多亏他!

class SQLParam {
public:
   virtual ~SqlParam(){}
   void bind(DatabaseHandler &db, int index) = 0;
};

class SQLParamInt {
private:
   int value;
public:
   SqlParamInt(int p_value) : value(p_value) {
   }
   ~SqlParamInt() {}
   int bind(DatabaseHandler &db, int index) {
       return db.bindInt(value, index);
   }
};

class SQLParamString {
private:
   string value;
public:
   SqlParamString(std::string p_value) : value(p_value) {
   }
   ~SqlParamString() {}
   int bind(DatabaseHandler &db, int index) {
       return db.bindString(value, index);
   }
};

typedef std::vector<std::unique_ptr<SqlParam>> SqlParamsContainer;
typedef std::unique_ptr<SqlParamInt> SqlParamIntPtr;
typedef std::unique_ptr<SqlParamString> SqlParamStringPtr;

In my function, building query: 在我的函数中,构建查询:

int buildQuery(RequestHandler &request) {
    SqlParamsContainer params;
    stringstream query << "SELECT * FROM Table WHERE A = ?";

    params.push_back(SqlParamIntPtr(new SqlParamInt(request.A())));
    if(request.has_B()) {
         params.push_back(SqlParamIntPtr(new SqlParamInt(request.B())));
         query << " AND B = ?";
    }
    if(request.has_C()) {
         params.push_back(SqlParamStringPtr(new SqlParamString(request.C())));
         query << " AND C = ?";
    }
    query << ";";
    db.prepare(query.str());

    for(int i = 0; i < v_container.size(); i++)
        v_container.at(i)->bind(db,i);
}

There is Boost::Any while it is more general than what you ask for and does not prevent the user from storing unsupported types you do not need to worry about creating the according subclasses. 还有Boost :: Any,尽管它比您想要的更通用,并且不会阻止用户存储不受支持的类型,您无需担心创建相应的子类。

If you want to return results as well from your DB Boost::Any might be the answer as well. 如果您也想从DB Boost ::返回结果,那么任何一个也可能是答案。

I suggest limiting the types in your bind function rather than in the storage. 我建议限制绑定函数而不是存储中的类型。 If you work with a variadic bind function this is necessary anyways. 如果您使用可变参数绑定函数,则无论如何都需要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM