在多选请求期间可以更改数据吗?

时间:2013-04-30 07:08:00

标签: sql postgresql

我有一个来自一个表(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
);

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

我使用postgresql 9.2。 谢谢!

1 个答案:

答案 0 :(得分:2)

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

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

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

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


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

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);

通过删除子选择并用窗口函数替换它,select语句可能更快:

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;