本人在初学 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 行记录)
1
dayeye2006199 2022-09-26 04:11:33 +08:00 via Android 2
没毛病,两条语句都执行成功了,所以事物成功了。第一条更新 1 条记录,第二条更新 0 条记录,都执行成功。
你问的应该是,怎么让更新 0 条记录的时候 update 语句失败,而不是成功。你可以在 update 之后加 returning id ,返回受到更新影响的行的主键。这时候 0 条记录更新的情况下,会直接失败。 |
2
moen 2022-09-26 04:16:57 +08:00 1
呃,你这个查询是顺利执行,只不过是无法匹配记录导致更新 0 行记录。没有顺利执行的那才是导致事务出错回滚
|
3
felixcode 2022-09-26 05:23:06 +08:00 via Android 3
SQL 是描述型语言,描述和操作的都是集合。
所以匹配不上就是空集,而不是运行报错。 |
4
PendingOni 2022-09-26 07:58:41 +08:00
@dayeye2006199 #1 正解,只要 SQL 事务操作中没有抛出异常就会一直执行,T 恤衫没有影响到任何一行
|
5
nekoneko 2022-09-26 17:40:04 +08:00
你数据库哪有 'T 恤衫' 这个 product_name 啊
|
6
nekoneko 2022-09-26 17:41:09 +08:00
# 1 正解
|
7
Fixedsys OP 好的,明白了,感谢各位大佬。
|