我有一个查询只有在外部引用(用户,会话)已经存在时才在数据库中插入事件。
。我收到此错误:
“PHP警告:pg_query_params():查询失败:错误:语法错误 在“IF”处或附近
此查询:
BEGIN;
SELECT id FROM users WHERE mongoid = $1 (userid);
IF not found THEN
-- inserts user and should remember userid
INSERT INTO users (mongoid, shopid, idinshop, attributes)
VALUES ($1, $2, $3, $4) RETURNING id (userid);
END IF;
--looks for session and should remember sessionid
SELECT id FROM sessions WHERE mongoid = $5 (sessionid);
IF not found THEN
-- inserts session
INSERT INTO sessions (mongoid, shopid, userid, session, traffic, counts)
VALUES ($5, $2, (userid), $6, $7, $8) RETURNING id (sessionid);
END IF;
-- finally inserts the event
INSERT INTO events (shopid, sessionid, userid, type, attributes, mongoid)
VALUES ($2, (sessionid), (userid), $9, $10, $11);
COMMIT;
稍后编辑: 我使用下面的答案解决了这个问题!
答案 0 :(得分:5)
您可以使用data-modifying CTEs在单 SQL语句中使用纯SQL 重写过程逻辑。
WITH usr1 AS (SELECT id FROM users WHERE mongoid = $1)
, usr2 AS (
INSERT INTO users (mongoid, shopid, idinshop, attributes)
SELECT $1, $2, $3, $4
WHERE NOT EXISTS (SELECT 1 FROM usr1)
RETURNING id
)
, ses1 AS (SELECT id FROM sessions WHERE mongoid = $5)
, ses2 AS (
INSERT INTO sessions (mongoid, shopid, userid, session, traffic, counts)
SELECT $5, $2, (SELECT id FROM usr1 NATURAL FULL OUTER JOIN usr2
, $6, $7, $8
WHERE NOT EXISTS (SELECT 1 FROM ses1)
RETURNING id
)
INSERT INTO events (shopid, sessionid, userid, type, attributes, mongoid)
VALUES ($2
, (SELECT id FROM usr1 NATURAL FULL OUTER JOIN usr2)
, (SELECT id FROM ses1 NATURAL FULL OUTER JOIN ses2)
, $9, $10, $11);
需要Postgres 9.1 或更高版本 未经测试。如果您想要测试答案,请在您的问题中提供测试用例。
应该比单个命令(let alone repeated round trips to the db server!)快得多。
请注意并发负载过重的潜在并发问题。提出的单个陈述已经很多不太可能导致麻烦。但可能性存在。 可能的解决方案包括manual locking(昂贵)advisory locks或serializable transactions(也可能很贵)。
相关答案及更多信息:
Postgresql batch insert or ignore