我是plpgsql的新手,我试图创建一个函数来检查表中是否存在某个值,如果不存在则会添加一行。
CREATE OR REPLACE FUNCTION hire(
id_pracownika integer,
imie character varying,
nazwisko character varying,
miasto character varying,
pensja real)
RETURNS TEXT AS
$BODY$
DECLARE
wynik TEXT;
sprawdzenie INT;
BEGIN
sprawdzenie = id_pracownika;
IF EXISTS (SELECT id_pracownika FROM pracownicy WHERE id_pracownika=sprawdzenie) THEN
wynik = "JUZ ISTNIEJE";
RETURN wynik;
ELSE
INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (id_pracownika,imie,nazwisko,miasto,pensja);
wynik = "OK";
RETURN wynik;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
问题是我收到的错误是id_pracownika
是列名和变量。
如何指定" id_pracownika"在这样的上下文中是指列名?
答案 0 :(得分:6)
CREATE OR REPLACE FUNCTION hire(
id_pracownika integer
, imie varchar
, nazwisko varchar
, miasto varchar
, pensja real)
RETURNS TEXT AS
$func$
BEGIN
IF EXISTS (SELECT 1 FROM pracownicy p
WHERE p.id_pracownika = hire.sprawdzenie) THEN
RETURN 'JUZ ISTNIEJE'::text; -- wynik
ELSE
INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (hire.sprawdzenie,hire.imie,hire.nazwisko,hire.miasto,hire.pensja);
RETURN 'OK'::text; -- wynik
END IF;
END
$func$ LANGUAGE plpgsql;
与@pozs评论一样,使用函数名对模式限定列名和前缀函数参数,以便在必要时消除歧义。
但请注意,INSERT
的目标列表中的列名可能不会加前缀。无论如何,这些都不会模棱两可。
就像@Frank评论的那样,最好避免这种含糊不清,这样可以减少错误。
如果您还需要列名作为函数参数名,那么避免命名冲突的一种方法是在函数内部使用ALIAS
。这是ALIAS
实际上有用的极少数情况之一。
或者您可以在$1
之前引用输入参数: id_pracownika
,在这种情况下为"OK"
。
但还有更多:
字符串文字(文本常量)必须用单引号括起来:'确定',而不是 。:=
plpgsql中的赋值运算符为EXISTS
。
在SELECT id_pracownika
表达式中,选择 并不重要。 SELECT 1
与SELECT 123/0
甚至VOLATILE COST 100
相同。只有行的存在才有意义。
分配变量比其他编程语言相对昂贵。如果有一种优雅的方法可以保存其中一些操作,那么这是plpgsql的首选方式。尽可能在SQL语句中直接执行。
SELECT
是函数的默认装饰器。你不必拼出那些。
INSERT
或UPSERT
你的功能是" SELECT或INSERT"的另一个实现。 - INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (hire.sprawdzenie,hire.imie,hire.nazwisko,hire.miasto,hire.pensja);
ON CONFLICT DO NOTHING
RETURNING 'OK'::text; -- wynik
IF NOT FOUND THEN
RETURN 'JUZ ISTNIEJE'::text;
END IF;
问题的变体,面对并发写入负载比您想象的更复杂。 (您的简单解决方案忽略的潜在问题,顺便说一句,并且可能使其失败!)详情:
Postgres团队(最突出的是Peter Geoghegan)已经在Postgres 9.5中实施了UPSERT。 Is SELECT or INSERT in a function prone to race conditions?这种新语法将执行干净工作:
{{1}}
答案 1 :(得分:0)
这是我测试的一个示例,我使用EXECUTE运行select并使用动态列名将其结果放入游标中。
<强> 1。创建表格:
create table people (
nickname varchar(9),
name varchar(12),
second_name varchar(12),
country varchar(30)
);
<强> 2。创建功能:
CREATE OR REPLACE FUNCTION fun_find_people (col_name text, col_value varchar)
RETURNS void AS
$BODY$
DECLARE
local_cursor_p refcursor;
row_from_people RECORD;
BEGIN
open local_cursor_p FOR
EXECUTE 'select * from people where '|| col_name || ' LIKE ''' || col_value || '%'' ';
raise notice 'col_name: %',col_name;
raise notice 'col_value: %',col_value;
LOOP
FETCH local_cursor_p INTO row_from_people; EXIT WHEN NOT FOUND;
raise notice 'row_from_people.nickname: %', row_from_people.nickname ;
raise notice 'row_from_people.name: %', row_from_people.name ;
raise notice 'row_from_people.country: %', row_from_people.country;
END LOOP;
END;
$BODY$ LANGUAGE 'plpgsql'
第3。运行功能
select fun_find_people('name', 'Cristian');
select fun_find_people('country', 'Chile');