我有一个存储过程,我需要在其中查询一组ids
,然后在UPDATE
语句的WHERE
子句中使用该集合。我正在使用 PostgresQL 9.0 + 。我宁愿不在ids
集上使用循环并发出多个UPDATE
语句 - 这不是很有效。
这是一个简单的例子:
CREATE OR REPLACE FUNCTION test_it()
RETURNS VOID AS $$
DECLARE
cur_time TIMESTAMP;
ids a%ROWTYPE;
BEGIN
SELECT id FROM a INTO ids;
UPDATE b
SET state = 'foobar', updated_at = cur_time
WHERE id IN ids;
END;
$$ LANGUAGE plpgsql;
这甚至都没有编译。
我也尝试了 SELECT -ing ids
就像这样......
CREATE OR REPLACE FUNCTION test_it()
RETURNS VOID AS $$
DECLARE
cur_time TIMESTAMP;
ids a%ROWTYPE;
BEGIN
SELECT id FROM a INTO ids;
UPDATE b
SET state = 'foobar', updated_at = cur_time
WHERE id IN (SELECT ids);
END;
$$ LANGUAGE plpgsql;
这会抛出一个错误:提示:没有运算符匹配给定的名称和参数类型。您可能需要添加显式类型转换。
我的实际存储过程要复杂得多,因为ids
集的初始查询实际上是一个动态查询。
实际错误输出是这个(只是更多上下文......):
ERROR: operator does not exist: integer = task_responses
LINE 3: WHERE id IN (SELECT task_response_ids)
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
QUERY: UPDATE task_responses
SET state = state, updated_at = cur_time, rejected_at = cur_time
WHERE id IN (SELECT task_response_ids)
CONTEXT: PL/pgSQL function "reject_submissions_with_comment" line 38 at SQL statement
答案 0 :(得分:1)
在执行我的SP期间,我需要循环结果,所以我选择跟踪我访问它们的ID,稍后在动态查询中使用它们来执行单个更新。
FWIW:我永远无法得到@ Steve的建议,因为task_response_ids
是一个结果集,而不是表表达式。如果我嵌入了可行的查询,但在我的用例中我需要多次运行相同的查询,因为我有多个更新(不同的表)要做。
以下是基于我的需求的(假)代码,如上所述和原始问题:
CREATE OR REPLACE FUNCTION test_it() RETURNS VOID AS $$
DECLARE
cur_time TIMESTAMP;
state varchar(20);
a_response RECORD;
ids bigint[];
other_ids bigint[];
s_ids varchar(4000);
s_other_ids varchar(4000);
BEGIN
state := 'foobar';
cur_time := CURRENT_TIMESTAMP;
FOR a_response IN (SELECT id,other_id FROM a) LOOP
ids[id_index] := a_response.id;
other_ids[id_index] := a_response.other_id;
id_index := id_index + 1;
-- do other stuff with the current record
END LOOP;
s_ids := array_to_string(ids, ',');
s_other_ids := array_to_string(other_ids, ',');
EXECUTE '
UPDATE b
SET state = $1, updated_at = $2
WHERE id IN (' || s_ids || ')'
USING state, cur_time;
EXECUTE '
UPDATE c
SET state = $1, updated_at = $2
WHERE id IN (' || s_other_ids || ')'
USING state, cur_time;
END;
$$ LANGUAGE plpgsql;
这段代码非常虚构,但它展示了我需要完成的事情。
答案 1 :(得分:0)
根据http://www.postgresql.org/docs/9.1/static/sql-update.html
,您需要UPDATE ... FROM ...样式查询UPDATE b
SET state = 'foobar', updated_at = cur_time
FROM
ids i
WHERE
b.id = i.id;