如何在Postgresql中准备语句和绑定参数
How to prepare statements and bind parameters in Postgresql for C++
我是C++
的新手,对pqxx
库有一点了解。我要实现的是准备语句和绑定参数。在PHP
中,我习惯以这样一种简洁的方式做到这一点:
$s = $db->prepare("SELECT id FROM mytable WHERE id = :id");
$s->bindParam(':id', $id);
$s->execute();
或使用令牌:
$data = array();
$data[] = 1;
$data[] = 2;
$s = $db->prepare("SELECT id FROM mytable WHERE id = ? or id = ?");
$s->execute($data);
我试图从pqxx文档中找出如何实现这一点,但对我来说,文档看起来一团糟,缺乏简短的示例(就像我上面提供的那样)。我希望在C++
中处理Postgresql
时,有人也能提供这样简单的例子(或类似的简单-不必编写一些庞然大物的代码)。
一个简单的例子。这只是打印id值为0的条目数。
#include<pqxx/pqxx>
#include<iostream>
int main()
{
std::string name = "name";
int id = 0;
try {
//established connection to data base
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
//statement template
c.prepare("example", "SELECT id FROM mytable WHERE id = $1");
//invocation as in varible binding
pqxx::result r = w.prepared("example")(id).exec();
w.commit();
//result handling for accessing arrays and conversions look at docs
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
函数w.p reed()有点复杂。它类似于haskell中的curry (curry)函数,因为它接受一个参数并返回另一个函数,该函数反过来接受另一个参数。诸如此类。
文档说:
如何传递这些参数?c++没有很好的方法让您向函数调用传递无限可变数量的参数,并且编译器不知道您将传递多少个参数。这里有一个技巧:您可以将从prepared返回的值视为一个函数,调用该函数来传递参数。你从那个调用中得到的结果还是一样的,所以你可以再次调用它来传递另一个参数,等等。
一旦以这种方式传递了所有参数,就可以通过在调用
时调用exec来调用带有参数的语句。
如果有更多的参数,则在prepare
函数中使用$1 $2等等
c.prepare("SELECT id name FROM mytable WHERE id = $1 AND name = $2")
并给出变量
w.prepared("example")(dollar1_var)(dollar2_var).exec()
动态准备示例
#include<pqxx/pqxx>
#include<iostream>
#include<vector>
//Just give a vector of data you can change the template<int> to any data type
pqxx::prepare::invocation& prep_dynamic(std::vector<int> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
int main()
{
std::string name = "name";
//a data array to be used.
std::vector<int> ids;
ids.push_back(0);
ids.push_back(1);
try {
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
c.prepare("example", "SELECT id FROM mytable WHERE id = $1 or id = $2");
pqxx::prepare::invocation w_invocation = w.prepared("example");
//dynamic array preparation
prep_dynamic(ids, w_invocation);
//executing prepared invocation.
pqxx::result r = w_invocation.exec();
w.commit();
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
如果你想处理其他数据类型,使用这个函数定义
template<class T> pqxx::prepare::invocation& prep_dynamic(std::vector<T> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
尽可能使用pqxx::prepare::调用,并在执行前绑定更多的值,因为它更稳定,更能防止错误,但还有一种更快的方法,我将在下面描述它。
。调用:
pqxx::nontransaction W(C);
std::string m_insertCommand = "INSERT INTO tableforperftest(column1, column2) VALUES";
unsigned int m_nCurrentRow = 32767;
for (size_t i = 0; i < m_nCurrentRow; i++)
{
unsigned int countOf$ = i * 2;
for (unsigned int i = 0; i < 2; ++i)
{
if (i == 0)
{
m_insertCommand += "(";
}
else
{
m_insertCommand += ", ";
}
m_insertCommand += "$";
std::stringstream ss;
ss << countOf$ + i + 1;
m_insertCommand += ss.str();
}
if(i < m_nCurrentRow - 1)
m_insertCommand += ") ,";
}
m_insertCommand += ")";
C.prepare("insert_into_db", m_insertCommand);
pqxx::prepare::invocation inv = W.prepared("insert_into_db");
for (size_t i = 0; i < m_nCurrentRow; i++)
{
inv(i)(i);
}
inv.exec();
二世。使用存储过程获取更多参数值:
CREATE OR REPLACE FUNCTION insertintoboosted(valuesforinsert TEXT) RETURNS VOID AS
$$
BEGIN
EXECUTE 'INSERT INTO tableforperftestproof(column1, column2) VALUES (' || valuesforinsert || ')';
END;
$$
LANGUAGE plpgsql;
代码:for (size_t i = 0; i < m_nCurrentRow; i++)
{
if (i == 0)
ss << i << "," << i;
else
ss << "(" << i << "," << i;
if (i < m_nCurrentRow - 1)
ss << "),";
}
C.prepare("prep2", "select insertintoboosted($1::text)");
W.prepared("prep2")(ss).exec();
III。每次使用参数绑定和执行:
std::string m_insertCommand3 = "INSERT INTO tableforperftest(column1, column2) VALUES ($1, $2)";
C.prepare("insert_into_db3", m_insertCommand3);
for (size_t i = 0; i < m_nCurrentRow; i++)
{
W.prepared("insert_into_db3")(i)(i).exec();
}
比较32767个insert的解决方案:
Invocation: --> Elapsed: 0.250292s
Stored Proc: --> Elapsed: 0.154507s
Parameter binding + execution each time: --> Elapsed: 29.5566s
相关文章:
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 在基于范围的for循环中使用结构化绑定声明
- 使用 LuaBridge 将 LuaJIT 绑定到C++会导致"PANIC: unprotected error"
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 在使用GPU支持编译Tensorflow时,会遇到CUDA_TOOLKIT_PATH未绑定变量
- 视觉studo 2019中的漫画和静态/动态绑定
- 将自由函数绑定为类成员函数
- 将常量指针引用绑定到非常量指针
- 在派生类中绑定非静态模板化成员函数
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 在 openGL 中多次绑定缓冲区
- 定义有趣的宏和正则表达式在Z3 C++绑定
- sqlite3绑定多个语句值
- 为什么结构化绑定禁用RVO和移动返回语句
- 如何使用libpq库和C 绑定无效的语句
- Qt Sql 无法将变量绑定到 QSqlQuery prepare 语句
- return 语句将右值引用绑定到左值
- 用When语句绑定滑块值
- 如何在Postgresql中准备语句和绑定参数
- 在C++中实现sql语句绑定的最佳方式