与我对Oracle PL/SQL的了解相比,我对PostgreSQL的存储过程和plpgsql不是很熟悉.在Oracle中,有两种类型的callables:
据我所知,在plpgsql中,所有存储过程都被考虑在内functions.据我所知,这意味着,他们可以(但不必)总是返回一个值.现在我在文档页面上看到,我还可以在函数上声明OUT参数,这在Oracle中是不可能的.但是我没有看到关于OUT参数是否可以与返回值组合的示例或任何明确的陈述.我也无法看到IN OUT参数是否可行.
我是Postgresql的新手,并且正在努力构建一个循环一系列CSV文件并加载它们的函数.我可以使用单个文件使COPY正常工作,但我无法使FOR LOOP语法正确.我试图替代一年号码作为我的苍蝇被命名为/path/tmp.YEAR.out.csv
这就是我讨厌的内容:
CREATE OR REPLACE FUNCTION test() RETURNS void as $$
BEGIN
FOR i IN 1982..1983 LOOP
COPY myTable
FROM '/path/tmp.' || i::VARCHAR || '.out.csv'
delimiters ','
END LOOP;
END;
$$ LANGUAGE 'plpgsql';
Run Code Online (Sandbox Code Playgroud)
这会在第一个||处抛出错误.所以我怀疑我正在i不正确地管理变量的concat .有小费吗?
我试图在PostgreSQL 8.2中编写一个触发器函数,它将动态使用TG_TABLE_NAME来生成和执行SQL语句.我可以为PostgreSQL的更高版本找到各种各样的例子,但由于一些要求,我被困在8.2上.这是我的功能,因为它有效,但几乎没有动态:
CREATE OR REPLACE FUNCTION cdc_TABLENAME_function() RETURNS trigger AS $cdc_function$
DECLARE
op cdc_operation_enum;
BEGIN
op = TG_OP;
IF (TG_WHEN = 'BEFORE') THEN
IF (TG_OP = 'UPDATE') THEN
op = 'UPDATE_BEFORE';
END IF;
INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,DEFAULT,DEFAULT,OLD.*);
ELSE
IF (TG_OP = 'UPDATE') THEN
op = 'UPDATE_AFTER';
END IF;
INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,DEFAULT,DEFAULT,NEW.*);
END IF;
IF (TG_OP = 'DELETE') THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
这是当前编写的方式,我将不得不为每个表编写一个单独的触发器函数.我想使用TG_TABLE_NAME来动态构建我的INSERT语句,并在其前面加上'cdc_',因为所有表都遵循相同的命名约定.然后我可以让每个表调用的每个触发器只有一个函数.
我一直得到这个错误:列引用"人"是模棱两可的.
我需要返回一个TABLE(人整数).当我使用SETOF整数时它工作正常但在这种情况下它不起作用.我的另一个函数recurse()非常好地返回一组整数.
CREATE OR REPLACE FUNCTION try(_group text) RETURNS TABLE (person integer) AS $$
DECLARE
_init_id integer;
_record integer;
BEGIN
SELECT id INTO _init_id FROM egroups WHERE name = _group;
FOR _record in SELECT person FROM egroupdata WHERE egroup IN (SELECT recurse(_init_id))
LOOP
RETURN NEXT;
END LOOP;
END;
$$ language plpgsql stable;
Run Code Online (Sandbox Code Playgroud) 我有这种形式的PostgreSQL表:
base_id int | mods smallint[]
3 | {7,15,48}
Run Code Online (Sandbox Code Playgroud)
我需要填充这种形式的表格:
combo_id int | base_id int | mods smallint[]
1 | 3 |
2 | 3 | {7}
3 | 3 | {7,15}
4 | 3 | {7,48}
5 | 3 | {7,15,48}
6 | 3 | {15}
7 | 3 | {15,48}
8 | 3 | {48}
Run Code Online (Sandbox Code Playgroud)
我想我可以使用几乎完全相同的函数完成此操作,迭代第一个表并将组合写入第二个表: 在SQL中生成所有组合
但是,我是Postgres新手,不能为我的生活找出如何使用plpgsql做到这一点.它不需要特别快; 它只会在后端定期运行.第一个表有大约80个记录,粗略计算表明我们可以预期第二个表的大约2600条记录.
任何人都可以至少指出我正确的方向吗?
编辑:克雷格:我有PostgreSQL 9.0.我成功地使用了UNNEST():
FOR messvar IN SELECT * FROM UNNEST(mods) AS mod WHERE mod BETWEEN 0 AND POWER(2, …Run Code Online (Sandbox Code Playgroud) 我需要RECORD按键/索引遍历类型项,就像我可以使用其他编程语言中的数组结构一样.
例如:
DECLARE
data1 record;
data2 text;
...
BEGIN
...
FOR data1 IN
SELECT
*
FROM
sometable
LOOP
FOR data2 IN
SELECT
unnest( data1 ) -- THIS IS DOESN'T WORK!
LOOP
RETURN NEXT data1[data2]; -- SMTH LIKE THIS
END LOOP;
END LOOP;
Run Code Online (Sandbox Code Playgroud) 我正在调整一些PL/pgSQL代码,所以我refcursor可以将表名作为参数.因此我更改了以下行:
declare
pointCurs CURSOR FOR SELECT * from tableName for update;
Run Code Online (Sandbox Code Playgroud)
这一个:
OPEN pointCurs FOR execute 'SELECT * FROM ' || quote_ident(tableName) for update;
Run Code Online (Sandbox Code Playgroud)
我调整了循环,然后,循环经过了.现在在循环中的某个时刻我需要更新记录(由光标指向)并且我卡住了.我该如何正确调整以下代码行?
UPDATE tableName set tp_id = pos where current of pointCurs;
Run Code Online (Sandbox Code Playgroud)
我修改了tableName和的引号,并在开头pos添加了EXECUTE子句,但是我得到了错误where current of pointCurs.
(i)我如何更新记录?
(ii)该函数适用于来自公共模式的表,而来自其他模式的表(例如trace.myname)失败.
任何评论都非常感谢..
CREATE OR REPLACE FUNCTION getParentLtree(parent_id bigint, tbl_name varchar)
RETURNS ltree AS
$BODY$
DECLARE
parent_ltree ltree;
BEGIN
-- This works fine:
-- select into parent_ltree l_tree from tbl1 where id = parent_id;
EXECUTE format('select into parent_ltree l_tree from %I
where id = %I', tbl_name,parent_id);
RETURN parent_ltree;
END;
$BODY$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
上述功能有2个问题:
parent_id是integer,但它会被替换引号?int变量的正确格式说明符是什么?select into不起作用EXECUTE?如何使上面的注释查询使用表名传递?我来自SQL Server后台,在存储过程中使用/鼓励使用'@'符号.这很有用,因为您可以轻松查看列是什么以及值是什么.例如.
CREATE PROCEDURE Foo
@Bar VARCHAR(10),
@Baz INT
AS
BEGIN
INSERT INTO MyTable (
Bar,
Baz)
VALUES (
@Bar,
@Baz)
END
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用序数位置但是我们的一些存储过程有20个左右的参数,并且命名参数使它更易读IMO.
PostgreSQL社区是否有某种约定用于前缀?我试图找出确切的命名参数的规则,但我的谷歌搜索没有产生任何东西.
我想更新表中的列,stats其中特定列是一个参数,然后返回该列的更新值[只有1行]:
CREATE FUNCTION grow(col varchar) RETURNS integer AS $$
DECLARE
tmp int;
BEGIN
tmp := (EXECUTE format(
'UPDATE stats SET %I = %I + 1
RETURNING %I',
col, col, col
)
);
RETURN tmp;
END;
Run Code Online (Sandbox Code Playgroud)
总的来说,我甚至不确定这是否是我想做的最佳方式,任何建议都将不胜感激!
plpgsql ×10
postgresql ×10
dynamic-sql ×3
function ×2
sql ×2
cursor ×1
for-loop ×1
loops ×1
record ×1
return ×1
sql-update ×1
triggers ×1