SQL:重用函数返回的值?

时间:2014-03-14 17:47:50

标签: sql postgresql variables sql-insert sql-function

  1. 如何重用下面函数中调用的pair返回的值?

    CREATE FUNCTION messages_add(bigint, bigint, text) RETURNS void AS $$
        INSERT INTO chats SELECT pair($1, $2), $1, $2
            WHERE NOT EXISTS (SELECT 1 FROM chats WHERE id = pair($1, $2));
        INSERT INTO messages VALUES (pair($1, $2), $1, $3);
    $$ LANGUAGE SQL;
    

    我知道SQL query language doesn't support storing simple values in variables和典型的编程语言一样。所以,我查看了WITH Queries (Common Table Expressions),但我不确定是否应该使用WITH,无论如何,我无法找出正确的语法。做的事情。

  2. 这是我的SQLFiddle以及关于storing chats & messages in PostgreSQL的原始问题。然后插入此函数inserts-if-not-exists。我没有使用交易,因为我想保持快速,并且存储没有消息的聊天并不是那么糟糕,反之则更糟糕。因此,查询顺序很重要。如果有更好的办法,请提供建议。

  3. 我想重用该值主要是为了加速代码。但是,SQL解释器是否会自动优化上面的功能?不过,我想写好DRY代码。

3 个答案:

答案 0 :(得分:2)

由于函数体是程序性的,因此使用plpgsql语言而不是SQL:

CREATE FUNCTION messages_add(bigint, bigint, text) RETURNS void AS $$
BEGIN
    INSERT INTO chats
        SELECT pair($1, $2), $1, $2
        WHERE NOT EXISTS (SELECT 1 FROM chats WHERE id = pair($1, $2));
    INSERT INTO messages VALUES (pair($1, $2), $1, $3);
END
$$ LANGUAGE plpgsql;

此外,如果要重用的结果是pair($1,$2),您可以将其存储到变量中:

CREATE FUNCTION messages_add(bigint, bigint, text) RETURNS void AS $$
DECLARE
    pair bigint := pair($1, $2);
BEGIN
    INSERT INTO chats
        SELECT pair, $1, $2
        WHERE NOT EXISTS (SELECT 1 FROM chats WHERE id = pair);
    INSERT INTO messages VALUES (pair, $1, $3);
END
$$ LANGUAGE plpgsql;

答案 1 :(得分:1)

create function messages_add(bigint, bigint, text) returns void as $$
    with p as (
        select pair($1, $2) as p
    ), i as (
        insert into chats
        select (select p from p), $1, $2
        where not exists (
            select 1
            from chats
            where id = (select p from p)
        )
    )
    insert into messages
    select (select p from p), $1, $3
    where exists (
        select 1
        from chats
        where id = (select p from p)
    )
    ;
$$ language sql;

只有在聊天中存在时才会插入消息。

答案 2 :(得分:0)

  1. 我实际上对这部分问题没有答案,但无论如何我都会解决这个问题,因为Markdown SUCKS and Stack Overflow doesn't support the start attribute on the ol element

  2. 行。现在,我们在2,:-) PostgreSQL functions are transactional。因此,订单实际上并不重要,因为两个插入都将在一个事务中一起提交。

  3. 不,优化器仅在使用常量(非变量)参数调用不可变函数时预先计算它们,例如pair(4, 5)。请参阅Function Volatility Categories