WITH之后的SELECT如果在显式事务中则不返回任何行

时间:2017-12-27 17:03:42

标签: sql postgresql transactions

WITH generated_id AS (
  INSERT INTO ... RETURNING id
)
SELECT id FROM generated_id;

返回42,而

BEGIN;
WITH generated_id AS (
  INSERT INTO ... RETURNING id
)
SELECT id FROM generated_id;
COMMIT;

什么都不返回。为什么呢?

更新

我刚发现WITH无关紧要,因为即使单个选择也不起作用:

SELECT something FROM some_table;

返回行。

BEGIN;
SELECT something FROM some_table;
COMMIT;

不返回任何行。

更新2:

我认为BEGINSTART TRANSACTION完全相同。无论如何,我尝试了所有可能的组合,但它们都不适合我。

我正在使用 this 免费的postgres服务,但现在我 tested it with SQL Fiddle 并且没有抱怨。

但奇怪的是,如果我没有在SELECT行的末尾添加;,我的数据库引擎会给我一个语法错误,如果我把它放在那里使用SQL Fiddle,它会告诉我不允许显式提交。

因此,我仍然不清楚究竟发生了什么。它是否仅适用于SQL Fiddle,因为它确实没有在显式事务中运行我的查询,如果它会结果是相同的:没有行,就像我的数据库引擎的行为一样。

我很遗憾无法在其他服务器上测试它,但如果有人有可靠的postgres配置,也许他们可以尝试一下它是否运行并告诉我。

3 个答案:

答案 0 :(得分:1)

这在大多数客户端都不会返回任何内容,因为您只看到最后一个命令返回的内容:

BEGIN;
SELECT something FROM some_table;
COMMIT;

尝试改为:

BEGIN;
SELECT something FROM some_table;

但是不要忘记COMMITROLLBACK以后终止开放交易。

SQL Fiddle不允许显式事务包装器。 I quote:

  

所有SQL查询都在SQL执行后立即回滚的事务中运行。

在开放事务中发出的

BEGIN;仅发出WARNING - 这不会显示在SQL Fiddle中(您看到的结果为0行)。

COMMIT;会引发您看到的错误。

在您尝试在SELECT之后省略分号时,COMMIT被解释为表别名:

BEGIN;
SELECT something FROM some_table
COMMIT;

......相当于:

BEGIN;
SELECT something FROM some_table AS commit;

这是另一个误解。

答案 1 :(得分:0)

你试过说BEGIN WORK吗? 我想你需要从那开始,然后你可以用COMMIT

结束它

答案 2 :(得分:0)

尝试开始:

BEGIN TRANSACTION;

然后结束:

END TRANSACTION;