0

我有一个来自一个表(FileInstance)的多个 SELECT 请求,这些 SELECT 使用 MAX 函数。在这个 INSERT 语句中SELECT MAX(Sequence) FROM FileInstance是否会给出相同的结果?是否可以在这些 SELECT 之间添加一条记录并且我会捕获不同的值?

INSERT INTO
    FileInstance (Data, Size, FileID, ChangesetID)
VALUES
(
    (SELECT Data FROM FileInstance WHERE FileID=%1 AND Sequence=(SELECT MAX(Sequence) FROM FileInstance WHERE FileID=%1)),
    (SELECT Size FROM FileInstance WHERE FileID=%1 AND Sequence=(SELECT MAX(Sequence) FROM FileInstance WHERE FileID=%1)),
    %1,
    NULL
);

当然,我认为两个调用 SELECT MAX(Sequence) FROM FileInstance WHERE FileID=%1 将转换为一个调用,但我只是想确定一下。

我使用postgresql 9.2。谢谢!

4

1 回答 1

2

是的,该语句在运行时会看到数据库的一致视图。所以两个子选择都将返回相同的值。

编辑:我认为可能还需要关于并发插入的注释。如果其他事务在您的语句运行时插入更高的序列号,如果您在序列上有唯一索引,则可能导致错误。

如果序列列不需要无间隙,则使用真正的序列可能是更好的解决方案。

如果您想避免并发事务的问题,您可能希望在运行插入之前将隔离级别更改为“可序列化”。


但是,您的陈述非常低效。这可以简化为:

INSERT INTO FileInstance 
  (Data, Size, FileID, ChangesetID)
SELECT Data, Size, %1, NULL
FROM FileInstance 
WHERE FileID=%1 
AND Sequence = (SELECT MAX(Sequence) 
                FROM FileInstance 
                WHERE FileID=%1);

通过删除子选择并将其替换为窗口函数,选择语句可能会更快:

INSERT INTO FileInstance 
  (Data, Size, FileID, ChangesetID)
select Data, Size, fileID, NULL
from (
  select data, 
         size,
         fileid,
         max(sequence) over (partition by fileId) as max_seq,
         sequence
  from fileinstance
  where fileID = %1
) t
where sequence = max_seq;
于 2013-04-30T07:12:00.337 回答