Postgresql:减号运算符不能与参数一起使用吗?只有硬编码值?
Postgresql: Can the minus operator not be used with a parameter? Only hardcoded values?
以下查询使用索引删除条目:
const deleteGameQuery = `
update users
set games = games - 1
where username =
`
如果我将索引作为参数传递,则不会删除任何内容:
const gameIndex = rowsCopy[0].games.findIndex(obj => obj.game == gameID).toString();
const deleteGameQuery = `
update users
set games = games -
where username =
`
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"
}
]
问题是您传递的是文本而不是整数。您需要传递一个整数。我不确定您的数据库接口如何传递整数,请尝试删除 toString()
并确保 gameIndex
是 Number.
const gameIndex = rowsCopy[0].games.findIndex(obj => obj.game == gameID)
.
array - integer
和 array - 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;
您还会有一个平台 table 和一个 game_platforms 连接 table。
加入 table 有点麻烦,但它们是 SQL 存储关系的方式。 JSONB很有用,但不能代替关系
您可以尝试避免在 postgres 之外分解对象,并像这样在查询内部操作 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;
以下查询使用索引删除条目:
const deleteGameQuery = `
update users
set games = games - 1
where username =
`
如果我将索引作为参数传递,则不会删除任何内容:
const gameIndex = rowsCopy[0].games.findIndex(obj => obj.game == gameID).toString();
const deleteGameQuery = `
update users
set games = games -
where username =
`
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"
}
]
问题是您传递的是文本而不是整数。您需要传递一个整数。我不确定您的数据库接口如何传递整数,请尝试删除 toString()
并确保 gameIndex
是 Number.
const gameIndex = rowsCopy[0].games.findIndex(obj => obj.game == gameID)
.
array - integer
和 array - 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;
您还会有一个平台 table 和一个 game_platforms 连接 table。
加入 table 有点麻烦,但它们是 SQL 存储关系的方式。 JSONB很有用,但不能代替关系
您可以尝试避免在 postgres 之外分解对象,并像这样在查询内部操作 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;