2013-04-30 38 views
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(序列)FROM FileInstance WHERE =写到FileID 1%将转化为一个呼叫,但我只是想确定。

我使用postgresql 9.2。 谢谢!

回答

2

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

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

如果序列列不需要没有空位,使用real序列可能是更好的解决方案。

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


但是,您的声明效率很低。这可以简化为:

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; 
+0

谢谢你,并优化了。 – Serhiy 2013-04-30 07:31:17

+0

@Serhiy:请参阅我关于并发事务问题的编辑。 – 2013-04-30 07:34:11

+0

在我的情况下,concurent insert是不可能的,我在其他表中有一个警卫作为唯一记录。 – Serhiy 2013-04-30 07:44:04

相关问题