【问题标题】:Correct usage of Postgres JSON conversion functionsPostgres JSON转换函数的正确使用
【发布时间】:2020-03-22 21:12:57
【问题描述】:

我正在处理 Postgres 更新事务。

假设我有两张桌子:eventsticket_books,带有活动预订类型。 ticket_books 表有一个外键指向events

我需要更新存储在数据库中的事件,包括ticket_books 表中的预订类型记录。

为了处理级联更新和删除,我决定构建一个事务,在“伪代码”中它看起来像:

    BEGIN;
      DELETE FROM
        ticket_books
      WHERE
        event_id = ${req.params.id} AND
        id NOT IN (${bookingIds})
      FOR booking IN json_to_recordset('${JSON.stringify(book)}') as book(id int, title varchar(200), price int, ...) LOOP
        IF bookind.id THEN
          UPDATE
            ticket_books
          SET
            title = booking.title, price = booking.price
          WHERE
            event_id = ${req.params.id};
        ELSE
          INSERT INTO
            ticket_books (title, price, qty_available, qty_per_sale)
          VALUES
            (booking.title, booking.price, booking.qty_available, booking.qty_per_sale)
          RETURNING
            id
        END IF;
      END LOOP;
   UPDATE
     event
   SET
    ...
   WHERE
     id = ...
   RETURNING
     id;
   COMMIT;

我目前收到错误:syntax error at or near "json_to_recordset"。我以前从未使用过json_to_recordset 或朋友,只是从文档中看到从 9.3 及更高版本开始可用。不过,不确定如何让 Postgres 了解我的需求。

我正在嵌入一个 JSON 数组,所以最后一行看起来像:

FOR booking IN json_to_record('[{"id":13,"description":"Three day access to the festival","title":"Three Day General Admission","price":260,"qty_available":5000,"qty_per_sale":10},{"id":14,"description":"Single day access to the festival","title":"Single Day General Admission","price":"90.90","qty_available":2000,"qty_per_sale":2},{"title":"Free Admission","price":"0.00","qty_available":0,"qty_per_sale":0}]')

我相信我的 JSON 数组是有效的。显然,这不是我应该将它传递给 Postgres 的方式。我应该怎么做?我的目标是遍历数组条目。如果booking.id 有整数值,我想更新记录,否则插入一个新记录。

【问题讨论】:

    标签: sql node.js postgresql transactions plpgsql


    【解决方案1】:

    你需要一个查询,一个独立的函数调用通常不算作查询:

    FOR booking IN select * from json_to_recordset(...
    

    此外,您不能使用 BEGIN 在 plpgsql 中启动事务。它仅用于启动一个块。如果您使用的是过程而不是函数,那么您可以 COMMIT 但新事务会立即开始,而不会使用 BEGIN 令牌。

    您还缺少 DELETE 和 FOR 之间的分号,但错误消息似乎仅在您的帖子中丢失,而不是在您的实际代码中。

    【讨论】:

      猜你喜欢
      • 2021-08-26
      • 1970-01-01
      • 2016-10-06
      • 2013-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-27
      相关资源
      最近更新 更多