【问题标题】:Postgresql: Can the minus operator not be used with a parameter? Only hardcoded values?Postgresql:减号运算符不能与参数一起使用吗?只有硬编码的值?
【发布时间】:2021-09-19 23:07:15
【问题描述】:

以下查询使用索引删除条目:

 const deleteGameQuery = ` 
                update users 
                set games = games - 1
                where username = $1
            `

如果我将索引作为参数传递,则不会删除任何内容:

const gameIndex = rowsCopy[0].games.findIndex(obj => obj.game == gameID).toString();


            const deleteGameQuery = ` 
                update users 
                set games = games - $1
                where username = $2
            `
    
          const { rows } = await query(deleteGameQuery, [gameIndex, username]);

          ctx.body = rows;

gameIndex 参数只是一个字符串,就像我键入它一样。那么为什么它似乎没有读取值呢?这是不允许的吗?

游戏栏目为jsonb数据类型,数据如下:

[
    {
        "game": "cyberpunk-2077",
        "status": "Backlog",
        "platform": "Any"
    },
    {
        "game": "new-pokemon-snap",
        "status": "Backlog",
        "platform": "Any"
    }
]

【问题讨论】:

  • 查询的结果是什么?该语句看起来不错,因此 $1==0 或 $2 不包含确切的用户名。如果 rows==0 表示 $2 不在表中。如果 rows>0 则意味着 $1==0。
  • @Vicctor 结果为 []。我什至将参数硬编码为“1”并且仍然相同。你可以从截图here看到他们在数据库中。
  • @Schwern 帖子中的第一个查询确实使用给定的索引号删除了数组内的对象,我对其进行了测试。
  • @George 这是重要的部分:游戏中有什么。如果您在帖子中明确说明,您将得到答案。
  • @Schwern 已编辑,谢谢。是的,它通过索引删除,这很棒,但我希望能够将索引作为参数传递,因为每次都不会是相同的索引,请参阅第二个代码块。

标签: postgresql parameters node-postgres


【解决方案1】:

问题是您传递的是文本而不是整数。您需要传递一个整数。我不确定您的数据库接口如何传递整数,请尝试删除 toString() 并确保 gameIndexNumber

const gameIndex = rowsCopy[0].games.findIndex(obj => obj.game == gameID).


array - integerarray - text 表示两个不同的东西。

array - 1 从数组中删除 second 元素。

select '[1,2,3]'::jsonb - 1;

 [1, 3]

array - '1' 搜索条目 '1' 并将其删除。

select '["1","2","3"]'::jsonb - '1';

 ["2", "3"]

-- Here, nothing is removed because 1 != '1'.
select '[1,2,3]'::jsonb - '1';

 [1, 2, 3]

传入参数时,query会根据其类型进行翻译。如果您传递一个数字,它将被翻译为1。如果您传递一个字符串,它将被翻译为'1'。 (或者至少它应该是这样工作的,我对 Javascript 数据库库并不完全熟悉。)


附带说明,此类数据最好作为join table 处理。

create table games (
  id bigserial primary key,
  name text not null,
  status text not null,
  platform text not null
);

create table users (
  id bigserial primary key,
  username text not null
);

create table game_users (
  game_id bigint not null references games,
  user_id bigint not null references users,

  -- If a user can only have each game once.
  unique(game_id, user_id)
);

-- User 1 has games 1 and 2. User 2 has game 2.
insert into game_users (game_id, user_id) values (1, 1), (2, 1), (2,2);

-- User 1 no longer has game 1.
delete from game_users where game_id = 1 and user_id = 1;

您还会有一个平台表和一个 game_platforms 连接表。

联接表有点让人费解,但它们是 SQL 存储关系的方式。 JSONB 非常有用,但它不能替代关系。

【讨论】:

  • 所以我之前也尝试过传递号码,但不幸的是,这并没有奏效,例如await query(deleteGameQuery, [1, username]);。我将研究连接表,因为我以前没有听说过它们。
  • @George 可以肯定的是,尝试对用户名进行硬编码。你在用node-postgres吗?我不确定它到底是如何工作的,只是 Postgres 方面。我已标记您的问题,以引起对节点界面的适当关注。
  • @George 检查gameIndextypeof。您可能必须将其转换为 Numeric 甚至 BigInt。
  • 是的,但我使用的代码很少,查询功能就是这样:const query = (text: string, params: any) => { return dbConfig.query(text, params) }
  • 搞定了。我必须在查询中转换为 Int - set games = games - $1::int。将给你答案,因为正确的问题是什么。
【解决方案2】:

您可以尝试避免在 postgress 之外分解对象,并像这样在查询中操作 jsonb 结构:

create table gameplayers as (select 1 as id, '[
{
    "game": "cyberpunk-2077",
    "status": "Backlog",
    "platform": "Any"
},
{
    "game": "new-pokemon-snap",
    "status": "Backlog",
    "platform": "Any"
},
{
    "game": "gameone",
    "status": "Backlog",
    "platform": "Any"
}
]'::jsonb games);



with
 ungroupped as (select * from gameplayers g, jsonb_to_recordset(g.games) 
  as (game text, status text, platform text)),
 filtered as (select id, 
     jsonb_agg(
      json_build_object('game', game, 
                        'status', status, 
                        'platfrom', platform
                       )
              ) games 
  from ungroupped where game not like 'cyberpunk-2077' group by id)     
UPDATE gameplayers as g set games=f.games 
       from filtered f where f.id=g.id;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 2021-12-17
    • 1970-01-01
    • 2020-04-22
    相关资源
    最近更新 更多