Ofi*_*son 0 sql postgresql upsert
我想将 Postgres 中的这段代码转换为更短的代码,以实现相同的效果。我读过有关 upsert 的内容,但我不明白在我的代码上实现它的好方法。我写的很好,但我想找到一种更优雅的方式来编写它。希望这里有人可以帮助我!这是查询:
CREATE OR REPLACE FUNCTION insert_table(
in_guid character varying,
in_x_value character varying,
in_y_value character varying
)
RETURNS TABLE(response boolean) LANGUAGE 'plpgsql'
DECLARE _id integer;
BEGIN
-- guid exists and it's been 10 minutes from created_date:
IF ((SELECT COUNT (*) FROM public.tbl_client_location WHERE guid = in_guid AND created_date < NOW() - INTERVAL '10 MINUTE') > 0) THEN
RETURN QUERY (SELECT FALSE);
-- guid exists but 10 minutes hasen't passed yet:
ELSEIF ((SELECT COUNT (*) FROM public.tbl_client_location WHERE guid = in_guid) > 0) THEN
UPDATE
public.tbl_client_location
SET
x_value = in_x_value,
y_value = in_y_value,
updated_date = now()
WHERE
guid = in_guid;
RETURN QUERY (SELECT TRUE);
-- guid not exist:
ELSE
INSERT INTO public.tbl_client_location
( guid , x_value , y_value )
VALUES
( in_guid, in_x_value, in_y_value )
RETURNING id INTO _id;
RETURN QUERY (SELECT TRUE);
END IF;
END
Run Code Online (Sandbox Code Playgroud)
这确实可以简单得多:
\nCREATE OR REPLACE FUNCTION insert_table(in_guid text\n , in_x_value text\n , in_y_value text\n , OUT response bool) -- \xe2\x91\xa3\n -- RETURNS record -- optional noise -- \xe2\x91\xa3\n LANGUAGE plpgsql AS -- \xe2\x91\xa0\n$func$ -- \xe2\x91\xa1\n-- DECLARE\n -- _id integer; -- what for?\nBEGIN\n INSERT INTO tbl AS t\n ( guid, x_value, y_value)\n VALUES (in_guid, in_x_value, in_y_value)\n ON CONFLICT (guid) DO UPDATE -- guid exists\n SET ( x_value, y_value, updated_date)\n = (EXCLUDED.x_value, EXCLUDED.y_value, now()) -- \xe2\x91\xa4\n WHERE t.created_date >= now() - interval \'10 minutes\' -- \xe2\x91\xa2 have not passed yet\n -- RETURNING id INTO _id -- what for?\n ;\n response := FOUND; -- \xe2\x91\xa5\nEND\n$func$;\nRun Code Online (Sandbox Code Playgroud)\n假设guid被定义UNIQUE或PRIMARY KEY,且 created_date被定义NOT NULL DEFAULT now()。
\xe2\x91\xa0 语言名称是一个标识符 - 最好不带引号。
\n\xe2\x91\xa1 函数体周围的引号丢失(无效命令)。看:
\n\n\xe2\x91\xa2UPDATE仅当 10 分钟尚未过去时。请记住,时间戳是各个事务开始时的时间戳。因此,请保持交易简短而简单。看:
\xe2\x91\xa3 具有OUT参数且无RETURNS子句的函数自动返回单行 ( record)。您的原始函数被声明为集合返回函数(0-n 返回行),这是没有意义的。看:
\xe2\x91\xa4 通常使用特殊EXCLUDED行比再次拼出值更好。看:
\xe2\x91\xa4 还使用短语法来更新多列。看:
\n\xe2\x91\xa5 要查看是否写入了行,请使用特殊变量FOUND。微妙的区别:与您原来的不同,您在事实之后得到true或,表示一行实际上已被写入(或未写入)。在您的原始版本中,或可能仍会被触发器或规则跳过(不会引发异常),并且在这种情况下函数结果会产生误导。看:false INSERTUPDATE
进一步阅读:
\n\n您可以只运行单个 SQL 语句,并提供一次值:
\nINSERT INTO tbl AS t(guid, x_value,y_value)\nVALUES ($in_guid, $in_x_value, $in_y_value) -- your values here, once\nON CONFLICT (guid) DO UPDATE\nSET (x_value,y_value, updated_date)\n = (EXCLUDED.x_value, EXCLUDED.y_value, now())\nWHERE t.created_date >= now() - interval \'10 minutes\';\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1152 次 |
| 最近记录: |