在Oracle的PL/SQL中,我可以使用包定义创建基于会话的全局变量.使用Postgresql的PLpg/SQL,它似乎不可能,因为没有包,只有独立的程序和功能.
以下是PL/SQL将g_spool_key声明为全局的语法...
CREATE OR REPLACE PACKAGE tox IS
g_spool_key spool.key%TYPE := NULL;
TYPE t_spool IS REF CURSOR RETURN spool%ROWTYPE;
PROCEDURE begin_spool;
PROCEDURE into_spool
(
in_txt IN spool.txt%TYPE
);
PROCEDURE reset_spool;
FUNCTION end_spool
RETURN t_spool;
FUNCTION timestamp
RETURN VARCHAR2;
END tox;
Run Code Online (Sandbox Code Playgroud)
如何使用PLpg/SQL实现基于会话的全局变量?
我只是有一个表格,其中包含国家列表及其ISO国家/地区代码.我将查询包装在存储过程(也称为函数)中,例如:
CREATE OR REPLACE FUNCTION get_countries(
) RETURNS setof record AS $$
SELECT country_code, country_name FROM country_codes
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
ERROR: a column definition list is required for functions returning "record"
Run Code Online (Sandbox Code Playgroud)
我知道我可以定义一个TYPE,然后像光标一样循环遍历记录集,但是在更新版本的PostgreSQL(我使用的是8.4.3)下,有更好的方法可以做到这一点,但我正在尝试要记住.
编辑:
这有效:
CREATE OR REPLACE FUNCTION get_countries(
) RETURNS setof country_codes AS $$
SELECT country_code, country_name FROM country_codes
$$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
请注意"RETURNS setof [table name]".但它似乎并不是最灵活的.如果我尝试返回多个表的连接,它就会崩溃.
我正在尝试从游戏数据库中删除与用户ID相关的所有数据.
有一张桌子可容纳所有游戏(每个游戏由3名玩家扮演):
# select * from pref_games where gid=321;
gid | rounds | finished
-----+--------+----------------------------
321 | 17 | 2011-10-26 17:16:04.074402
(1 row)
Run Code Online (Sandbox Code Playgroud)
并且有一张桌子可以控制该游戏的玩家分数#321:
# select * from pref_scores where gid=321;
id | gid | money | quit
----------------+-----+-------+------
OK531282114947 | 321 | 218 | f
OK501857527071 | 321 | -156 | f
OK429671947957 | 321 | -62 | f
Run Code Online (Sandbox Code Playgroud)
当我在PostgreSQL的psql-prompt上尝试以下SELECT INTO语句时,它似乎按预期工作(临时表在会话关闭时消失):
# select gid into temp temp_gids from pref_scores where id='OK446163742289';
SELECT
# select * from temp_gids ;
gid …Run Code Online (Sandbox Code Playgroud) 这是我的函数声明和正文的一部分:
CREATE OR REPLACE FUNCTION access_update()
RETURNS void AS $$
DECLARE team_ids bigint[];
BEGIN
SELECT INTO team_ids "team_id" FROM "tmp_team_list";
UPDATE "team_prsnl"
SET "updt_dt_tm" = NOW(), "last_access_dt_tm" = NOW()
WHERE "team_id" IN team_ids;
END; $$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
我想team_ids成为一个我可以在UPDATE声明中使用的一组int .这个函数给我这样的错误:
psql:functions.sql:62: ERROR: syntax error at or near "team_ids"
LINE 13: AND "team_id" IN team_ids;
Run Code Online (Sandbox Code Playgroud) 我在数据库中有一个表:
create table store (
...
n_status integer not null,
t_tag varchar(4)
t_name varchar,
t_description varchar,
dt_modified timestamp not null,
...
);
Run Code Online (Sandbox Code Playgroud)
在我的存储函数中,我需要select多次对该表执行相同的操作:
select * from store
where n_place_id = [different values]
and t_tag is not null
and n_status > 0
and (t_name ~* t_search or t_description ~* t_search)
order by dt_modified desc
limit n_max;
Run Code Online (Sandbox Code Playgroud)
这里,t_search并且n_max是存储函数的参数.我认为为此使用准备好的声明是有意义的,但我遇到了奇怪的问题.这就是我所拥有的:
create or replace function fn_get_data(t_search varchar, n_max integer)
returns setof store as
$body$
declare
resulter store%rowtype;
mid integer; …Run Code Online (Sandbox Code Playgroud) 如果我有以下玩具查询
SELECT *
FROM my_tables
WHERE my_id in (
SELECT my_other_id
FROM my_other_tables
) AND some_slow_func(arg) BETWEEN 1 AND 2;
Run Code Online (Sandbox Code Playgroud)
WHERE子句中的第一个条件是否会短路第二个具有复杂运行时间的条件?
我正在研究一些实际上是plpgsql中FOR LOOP的一部分的sql,我可以对my_other_tables中存在的所有记录进行迭代,然后使用some_slow_func()在FOR LOOP的范围内进行测试.但我很好奇是否支持sql,或者plpgsql支持短路.
一些研究:我查看了Postgres的邮件列表,发现这说SQL一般不支持短路:
http://www.postgresql.org/message-id/171423D4-9229-4D56-B06B-58D29BB50A77@yahoo.com
但其中一个回复表明订单可以通过子选择来强制执行.我不确定他在说什么.我知道子选择是什么,但我不确定如何强制执行命令?有人可以为我澄清一下吗?
我在PostgreSQL中有两个我需要联合的数组.例如:
{1,2,3}工会{1,4,5}会回来{1,2,3,4,5}
使用连接(||)运算符不会删除重复的条目,即它返回 {1,2,3,1,4,5}
我在网上找到了一个解决方案,但我不喜欢它需要如何取消两个数组:
select ARRAY(select unnest(ARRAY[1,2,3]) as a UNION select unnest(ARRAY[2,3,4,5]) as a)
是否有一个运算符或内置函数可以干净地结合两个数组?
我正在为 PostgreSQL 编写一个脚本,因为我希望它以原子方式执行,所以我将它包装在一个事务中。
我希望脚本看起来像这样:
BEGIN
-- 1) Execute some valid actions;
-- 2) Execute some action that causes an error.
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END; -- A.k.a. COMMIT;
Run Code Online (Sandbox Code Playgroud)
但是,在这种情况下,pgAdmin 在初始BEGIN. 如果我通过像这样附加分号来终止命令:BEGIN;它会通知我附近的错误EXCEPTION。
我意识到我可能混淆了控制结构和事务的语法,但是我在文档中找不到任何关于如何回滚失败事务的内容(也没有在 SO 中)。
我还考虑过事务可能会在出错时自动回滚,但由于以下脚本,情况似乎并非如此:
BEGIN;
-- 1) Execute some valid actions;
-- 2) Execute some action that causes an error.
COMMIT;
Run Code Online (Sandbox Code Playgroud)
警告我:ERROR: current transaction is aborted, commands ignored until end of transaction block然后我必须手动ROLLBACK;进行交易。
似乎我在这里遗漏了一些基本的东西,但是什么?
编辑:
我也试过DO像这样使用: …
在 Postgres 12 数据库中,我在一个函数中有多个查询(SELECT、UPDATE、 ...),总共需要大约 20 分钟才能完成。我在顶部有一个检查,它执行UPDATEifstatus未运行:
create or replace function aaa.fnc_work() returns varchar as
$body$
begin
if (select count(*) from aaa.monitor where id='invoicing' and status='running')=0 then
return 'running';
else
update aaa.monitor set status='running' where id='invoicing';
end if;
--- rest of code ---
--finally
update aaa.monitor set status='idle' where id='invoicing';
return '';
exception when others then
return SQLERRM::varchar;
end
$body$
language plpgsql;
Run Code Online (Sandbox Code Playgroud)
这个想法是为了防止其他用户执行直到--- rest of code ---空闲status。
然而,其他人(调用相同的函数)似乎看不到更新的状态,他们也继续并开始执行 …
postgresql stored-procedures transactions plpgsql task-queue
我想更新 postgres 表的一列。记录大约有 5500 万条,因此我们需要批量更新 10000 条记录。注意:我们要更新所有行。但我们不想锁定我们的桌子。
我正在尝试以下查询 -
Update account set name = Some name where id between 1 and 10000
Run Code Online (Sandbox Code Playgroud)
我们如何为每 10000 条记录更新创建一个循环?
任何建议和帮助将不胜感激。
PostgreSQL 10.5
plpgsql ×10
postgresql ×10
sql ×4
transactions ×2
arrays ×1
exception ×1
oracle ×1
plsql ×1
rollback ×1
select-into ×1
task-queue ×1
union ×1