结果,例如返回,来自未提交的高管?
Posted
技术标签:
【中文标题】结果,例如返回,来自未提交的高管?【英文标题】:Results, such as RETURNING, from uncomitted execs? 【发布时间】:2014-04-14 19:28:15 【问题描述】:使用 libpqxx,是否可以让一个 exec
s 但尚未被 commit
ted 的准备好的语句将结果存储在 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_table
的return
以查看if( == "")
。如果不是,则继续;否则,我将在那里commit
让它失败,或者如果可能的话最好取消交易;但是,如果可能的话,我还不知道该怎么做。
INSERT
s 到 child_table
每 parent_table
INSERT
的数量总是不确定的。
【问题讨论】:
for (result::size_type i=0; i < 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() > 0
那么我说是的。否则没有。
只要您准备下一个查询之后将结果保存到表(或临时表)中,同一事务中的所有内容都是可见的.
@ErwinBrandstetter 感谢您关注 Erwin Brandstetter!您介意在答案中澄清吗?我正在尝试将父表中的RETURNING
id
用于引用父表的子表列中,方法是将其存储在来自exec
的result
中。在所有准备好的语句都是exec
ed 之后,我然后commit
。你是说事务需要分解,要获得RETURNING
值,必须首先是commit
ted?如果是这样,我应该将隔离设置为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:你为什么要删除另一个问题?我在队列中有一个完成了一半的答案......以上是关于结果,例如返回,来自未提交的高管?的主要内容,如果未能解决你的问题,请参考以下文章