c++ - 结果,例如 RETURNING,来自未提交的 execs?

标签 c++ postgresql prepared-statement libpqxx

对于 libpqxx,是否有可能将 exec 但尚未被 commit 的准备好的语句存储在 result 中用于以后准备好的语句?

如果是这样,如何做到这一点?

代码

为了便于阅读,我已将其精简,但这实际上是我想要做的:

void prepare_write_parent_table(connection_base &c){
    try
    {
        c.prepare("write_parent_table", 
            "INSERT INTO parent_table (column_1) "
            "SELECT $1 "
            "RETURNING id"
        )
        ("character", pqxx::prepare::treat_string);
    }
    catch (const exception &e)
    {
        cerr << e.what() << endl;
    }
}

string write_parent_table(transaction_base &t, string data){
    try
    {
        result parent_table_result = t.prepared("write_parent_table")(data).exec();
        return parent_table_result[0][0].c_str();

    }
    catch (const exception &e)
    {
        cerr << e.what() << endl;
        return "";
    }
}

void prepare_write_child_table(connection_base &c){
    try
    {
        c.prepare("write_child_table", 
            "INSERT INTO child_table (parent_table_id, column_a) "
            "SELECT $1, $2 "
        )
        ("character", pqxx::prepare::treat_string)
        ("character", pqxx::prepare::treat_string);
    }
    catch (const exception &e)
    {
        cerr << e.what() << endl;
    }
}

write_parent_tablereturn 被检查以查看if( == "")。如果不是,则继续;否则,我将在那里提交让它失败,或者如果可能的话最好取消交易;但是,如果可能的话,我还不知道该怎么做。

每个 parent_table INSERT 总是会有不确定数量的 INSERTchild_table 中。

最佳答案

使用 data-modifying CTE 对两个插入使用单个 SQL 语句来简化操作.这比在客户端中存储中间状态要快得多。

子表中的 INSERT 只有在父表中的第一个 INSERT 成功并返回一个 id 时才会发生:

void prepare_write_both_tables(connection_base &c){
    try
    {
       c.prepare("write_both_tables", 
          "WITH p AS ("
             "INSERT INTO parent_table (column_1) "
             "SELECT $1 "
             "RETURNING id) "
          "INSERT INTO child_table (parent_table_id, column_a) "
          "SELECT p.id, $2 "
          "FROM   p"
        )
        ("character", pqxx::prepare::treat_string)
        ("character", pqxx::prepare::treat_string);
    }
    catch (const exception &e)
    {
        cerr << e.what() << endl;
    }
}

Search for [postgres] & "data-modifying CTE"更多示例。
也称为“可写 CTE”(或“可写 CTE”)。

多个 child

对于一个单亲 parent 和0到多个 child :

void prepare_write_both_tables(connection_base &c){
    try
    {
       c.prepare("write_both_tables", 
          "WITH p AS ("
             "INSERT INTO parent_table (column_1) "
             "SELECT $1 "
             "RETURNING id) "
          "INSERT INTO child_table (parent_table_id, column_a) "
          "SELECT p.id, a "
          "FROM   p, unnest($2::text[]) AS a"
        )
        ("character", pqxx::prepare::treat_string)
        ("character", pqxx::prepare::treat_string);
    }
    catch (const exception &e)
    {
        cerr << e.what() << endl;
    }
}

其中第二个参数是文本表示形式的文本数组。示例:

{foo,bar,baz}

这会插入与文本数组中的元素一样多的行。对于 0 个 child ,传递 NULL 或一个空数组 {}

关于c++ - 结果,例如 RETURNING,来自未提交的 execs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23068613/

相关文章:

c++ - 将多个参数传递给插槽

c++ - 立即模式纹理奇怪的输出

java - 使用 Order by 准备好的语句来防止 SQL 注入(inject) java

php - mysqli_stmt::bind_param() 的参数 2 预期为引用,给出值

java - 准备好的陈述有问题

c++ - 为什么 lock_guard 是模板?

c++ - 如何在 C++ 和 Linux 中将 std::ostream 重定向到文件或/dev/null

postgresql - Postgresql 中的日期/时间字段超出范围,小时字段超过 24 小时

database - 哪个索引最适合 PostgreSQL inet 数据类型?

PostgreSQL 9.5 : Hide password from dblink connection