V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
Fixedsys

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

  •  
  •   Fixedsys · Sep 26, 2022 · 2968 views
    This topic created in 1315 days ago, the information mentioned may be changed or developed.

    本人在初学 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 行记录)
    
    7 replies    2022-09-26 19:38:36 +08:00
    dayeye2006199
        1
    dayeye2006199  
       Sep 26, 2022 via Android   ❤️ 2
    没毛病,两条语句都执行成功了,所以事物成功了。第一条更新 1 条记录,第二条更新 0 条记录,都执行成功。
    你问的应该是,怎么让更新 0 条记录的时候 update 语句失败,而不是成功。你可以在 update 之后加 returning id ,返回受到更新影响的行的主键。这时候 0 条记录更新的情况下,会直接失败。
    moen
        2
    moen  
       Sep 26, 2022   ❤️ 1
    呃,你这个查询是顺利执行,只不过是无法匹配记录导致更新 0 行记录。没有顺利执行的那才是导致事务出错回滚
    felixcode
        3
    felixcode  
    PRO
       Sep 26, 2022 via Android   ❤️ 3
    SQL 是描述型语言,描述和操作的都是集合。
    所以匹配不上就是空集,而不是运行报错。
    PendingOni
        4
    PendingOni  
       Sep 26, 2022
    @dayeye2006199 #1 正解,只要 SQL 事务操作中没有抛出异常就会一直执行,T 恤衫没有影响到任何一行
    nekoneko
        5
    nekoneko  
       Sep 26, 2022
    你数据库哪有 'T 恤衫' 这个 product_name 啊
    nekoneko
        6
    nekoneko  
       Sep 26, 2022
    # 1 正解
    Fixedsys
        7
    Fixedsys  
    OP
       Sep 26, 2022
    好的,明白了,感谢各位大佬。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   912 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 54ms · UTC 18:28 · PVG 02:28 · LAX 11:28 · JFK 14:28
    ♥ Do have faith in what you're doing.