我必须构建一个动态的SQL查询。为了正确执行它,我必须分三步完成:
因为这个查询是动态构建的,所以我必须为给定的索引存储适当的值。
例如:
SELECT * FROM Table WHERE A =? AND E ='?';
SELECT * FROM Table WHERE A =? AND B =? AND E ='?';
在构建查询期间,我必须存储以下内容:
在第一种情况下:
在第二种情况下:
我最好的想法是创建两个地图:< int,string>,< int,int>并在创建第一个位置索引和第二个位置值的查询集,然后创建两个循环,一个用于字符串,第二个用于整数和绑定参数,它们工作正常。
但是我想知道是否可以使用后续索引和类型安全方式在一个循环中完成所有操作。
谢谢。
答案 0 :(得分:2)
我会考虑创建一个包装SQL参数的类。
实际上我会创建一个这样的抽象类:
SQLParameterBase
{
std::string toString() = 0;
void print()
{
std::cout << toString();
}
}
然后是模板类:
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
}
}
你可以这样使用它:
SQLParameterBase * params[10];
maps[0] = new SQLParameter<int>();
希望有所帮助
答案 1 :(得分:1)
实际上它是改进的AMDG解决方案。谢谢他!
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;
在我的函数中,构建查询:
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);
}
答案 2 :(得分:0)
有Boost::Any,但它比你要求的更通用,并且不会阻止用户存储不受支持的类型,你不必担心创建相应的子类。
如果你想从你的DB Boost中返回结果,也可能是答案。
我建议限制绑定函数中的类型而不是存储中的类型。如果你使用可变参数绑定函数,这仍然是必要的。