postgresql 里面的事务,明明又错误为什么也执行了?

2022-09-26 03:41:42 +08:00
 Fixedsys

本人在初学 postgresql ,版本 14 ,关于事务,教程里说的额是如果有一个错误所有的命令都不会执行。

但是下面的这个例子里面,原始表里并没有“T 恤衫”这个产品名,而是“T 恤”,所以将“T 恤衫”的价格上浮 1000 日元这个指令筛选不出来“T 恤衫”,我理解应该是错误的,但是 commit 之后,只有“运动 T 恤”的价格下调了,“T 恤衫”上浮 1000 并没有实现。

这个怎么解释呢?

shop=# select * from product;
 product_id | product_name | product_type | sale_price | purchase_price | regist_date
------------+--------------+--------------+------------+----------------+-------------
 0001       | T 恤          | 衣服         |       1000 |            500 | 2009-09-20
 0002       | 打孔器       | 办公用品     |        500 |            320 | 2009-09-11
 0003       | 运动 T 恤      | 衣服         |       4000 |           2800 |
 0004       | 菜刀         | 厨房用具     |       3000 |           2800 | 2009-09-20
 0005       | 高压锅       | 厨房用具     |       6800 |           5000 | 2009-01-15
 0006       | 叉子         | 厨房用具     |        500 |                | 2009-09-20
 0007       | 擦菜板       | 厨房用具     |        880 |            790 | 2008-04-28
 0008       | 圆珠笔       | 办公用品     |        100 |                | 2009-11-11
(8 行记录)


shop=# BEGIN TRANSACTION;
BEGIN
shop=*# -- 将运动 T 恤的销售单价降低 1000 日元
shop=*# UPDATE Product SET sale_price = sale_price - 1000 WHERE product_name = '运动 T 恤';
UPDATE 1
shop=*# -- 将 T 恤衫的销售单价上浮 1000 日元
shop=*# UPDATE Product SET sale_price = sale_price + 1000 WHERE product_name = 'T 恤衫';
UPDATE 0
shop=*# COMMIT;
COMMIT
shop=# select * from product;
 product_id | product_name | product_type | sale_price | purchase_price | regist_date
------------+--------------+--------------+------------+----------------+-------------
 0001       | T 恤          | 衣服         |       1000 |            500 | 2009-09-20
 0002       | 打孔器       | 办公用品     |        500 |            320 | 2009-09-11
 0004       | 菜刀         | 厨房用具     |       3000 |           2800 | 2009-09-20
 0005       | 高压锅       | 厨房用具     |       6800 |           5000 | 2009-01-15
 0006       | 叉子         | 厨房用具     |        500 |                | 2009-09-20
 0007       | 擦菜板       | 厨房用具     |        880 |            790 | 2008-04-28
 0008       | 圆珠笔       | 办公用品     |        100 |                | 2009-11-11
 0003       | 运动 T 恤      | 衣服         |       3000 |           2800 |
(8 行记录)
2248 次点击
所在节点    PostgreSQL
7 条回复
dayeye2006199
2022-09-26 04:11:33 +08:00
没毛病,两条语句都执行成功了,所以事物成功了。第一条更新 1 条记录,第二条更新 0 条记录,都执行成功。
你问的应该是,怎么让更新 0 条记录的时候 update 语句失败,而不是成功。你可以在 update 之后加 returning id ,返回受到更新影响的行的主键。这时候 0 条记录更新的情况下,会直接失败。
moen
2022-09-26 04:16:57 +08:00
呃,你这个查询是顺利执行,只不过是无法匹配记录导致更新 0 行记录。没有顺利执行的那才是导致事务出错回滚
felixcode
2022-09-26 05:23:06 +08:00
SQL 是描述型语言,描述和操作的都是集合。
所以匹配不上就是空集,而不是运行报错。
PendingOni
2022-09-26 07:58:41 +08:00
@dayeye2006199 #1 正解,只要 SQL 事务操作中没有抛出异常就会一直执行,T 恤衫没有影响到任何一行
nekoneko
2022-09-26 17:40:04 +08:00
你数据库哪有 'T 恤衫' 这个 product_name 啊
nekoneko
2022-09-26 17:41:09 +08:00
# 1 正解
Fixedsys
2022-09-26 19:38:36 +08:00
好的,明白了,感谢各位大佬。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/882893

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX