结果,例如返回,来自未提交的高管?

Posted

技术标签:

【中文标题】结果,例如返回,来自未提交的高管?【英文标题】:Results, such as RETURNING, from uncomitted execs? 【发布时间】:2014-04-14 19:28:15 【问题描述】:

使用 libpqxx,是否可以让一个 execs 但尚未被 committed 的准备好的语句将结果存储在 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( == "")。如果不是,则继续;否则,我将在那里commit 让它失败,或者如果可能的话最好取消交易;但是,如果可能的话,我还不知道该怎么做。

INSERTs 到 child_tableparent_table INSERT 的数量总是不确定的。

【问题讨论】:

for (result::size_type i=0; i &lt; Results.size(); ++i) other_prepare_object(Results[i]); pqxx.org/devprojects/libpqxx/doc/3.1/html/Reference/a00076.html @CantChooseUsernames 谢谢 CantChooseUsernames!所以您是说可以从尚未提交的exec 返回结果?如果是这样,这是一个了不起的设置! 我没有亲自尝试过,但值得一试。将该循环粘贴到您的代码中并打印Results[i] 的任何内容,然后查看.. 如果Results.size() &gt; 0 那么我说是的。否则没有。 只要您准备下一个查询之后将结果保存到表(或临时表)中,同一事务中的所有内容都是可见的. @ErwinBrandstetter 感谢您关注 Erwin Brandstetter!您介意在答案中澄清吗?我正在尝试将父表中的RETURNING id 用于引用父表的子表列中,方法是将其存储在来自execresult 中。在所有准备好的语句都是execed 之后,我然后commit。你是说事务需要分解,要获得RETURNING 值,必须首先是committed?如果是这样,我应该将隔离设置为SERIALIZABLE吗?如果是这样,怎么做?提前非常感谢您! 【参考方案1】:

通过使用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”)。

多个孩子

对于 单个 父级和 0 到多个 子级:

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;
    

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

foo,bar,baz

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

【讨论】:

仔细检查 C++ 语法。我是 Postgres 方面的专家,但不是 C++ 方面的专家。 @Gracchus:我为多个孩子添加了一个版本。 这个接受数组的文本表示。也许有更优雅的方式来传递数组... @Gracchus:这里不可能进行 SQL 注入。数据将仅被视为准备好的语句中的数据。如果语法无效,你会得到一个异常,一切都会回滚。 @Gracchus:你为什么要删除另一个问题?我在队列中有一个完成了一半的答案......

以上是关于结果,例如返回,来自未提交的高管?的主要内容,如果未能解决你的问题,请参考以下文章

提交的Sequelize事务的结果为“未定义”

在字符串列上使用 GROUP BY 时未获得分组结果

DropDownList 结果未返回

BigQuery 未准确返回结果

循环遍历 Mongoose 结果返回未定义

NSJsonSerialzation 未解析来自 Facebook 的结果 - Cocoa 错误 3840 [重复]