PostgreSQL:通过触发器检查表中是否存在值

时间:2019-01-13 02:56:01

标签: postgresql plpgsql

我在(Postgre)sql中熟悉了触发器。

我现在拥有的是一张Verine桌子(这是德语的团队)。

Vereine :{[team:string, punkte:int, serie:int]}

这是我写的非常小的东西,只是为了了解如何创建表,对内容和视图进行排序,现在我将其用于触发器。无论如何,团队显然是团队的名称和主键,朋克表示积分,意甲是指团队的划分(只是为了您了解不同域的含义)。

问题从这里开始:

因此,假设我有一个团队,比如说“尤文图斯”,已经在我的表“ Vereine”中。如果我然后要插入具有相同键“尤文图斯”的另一行/元组,而不是想要两个条目/元组,我想更新键“尤文图斯”的值(用旧值替换新值) 。在下面的示例中,我尝试使用积分进行操作。

create table vereine(
    team varchar(20) primary key,
    punkte int not null,
    serie int not null
)

--beispiel was die Aufgabe verlangt

create trigger prevent_redundancy
before insert on vereine 
for each row 
execute procedure update_points() 

create or replace function update_points()
returns trigger as 
$BODY$
begin 
    if (new.team in (old.team)) then 
    update vereine
    set punkte = new.punkte 
    where team = new.team;
    else
    end if;
end;
$BODY$
LANGUAGE plpgsql;



--Was die aufgabe verlangt ist, dass keine bereits existierende ID eingefügt wird,
--sondern der entsprechende Modellname dann umgeändert wird 


insert into vereine values('JuventusFC', 50, 1);
insert into vereine values('AS Roma', 30, 1);
insert into vereine values('ParmaCalcio1913', 25, 1);
insert into vereine values('Palermo', 37, 2);
insert into vereine values('Pescara', 32, 2);
insert into vereine values('Spezia', 26, 2);
insert into vereine values('Carrarese Calcio', 34, 3);
insert into vereine values('Virtus Entella', 31, 3);
insert into vereine values('Juventus U-23', 50, 3);




select * 
from vereine

insert into vereine values('JuventusFC', 53, 1);

这是我的问题:

首先:如何检查表中是否已存在键?在查询中,我会使用情况,何时何地或只是以不同方式处理问题的情况。我需要if语句吗?换句话说,您将如何重写

if (new.team in (old.team)) then 

以便检查它是否已经存在?

第二:这可能与第一个问题有关:尝试插入任何元组时,我会得到此信息:

Query execution failed

Reason:
SQL Error [54001]: ERROR: stack depth limit exceeded
Hint: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
Where: SQL statement "insert into vereine values(new.team, new.punkte, new.serie)"

如何修复我的代码,使其能够执行我想要的工作?

抱歉,太罗word了。我只想确保您了解这应该如何工作。是的,我之前曾问过一个与同一作业相关的问题,但这是一个完全不同的问题。也很抱歉。

1 个答案:

答案 0 :(得分:0)

您基本上想要的是UPSERT语法,如this answer所示,使用UNIQUE CONSTRAINT列上的team。我建议您将其用于相关功能的插入操作中,而不要使用触发器。

如果您仍然坚持使用触发器,则可以编写如下内容。

create or replace function update_points()
returns trigger as 
$BODY$
begin 
    if EXISTS (select 1 FROM vereine WHERE team = new.team ) then 
    update vereine
      set punkte = new.punkte 
    where team = new.team;
    RETURN NULL;
     else
    RETURN NEW;
    end if;
end;
$BODY$
LANGUAGE plpgsql;

在触发器返回过程中,RETURN NULL;RETURN NEW;Before Insert触发器之间的区别是RETURN NULL不会执行触发语句(即主{{ 1}}操作),而INSERT继续正常执行预期的RETURN NEW;语句。

Demo

现在,您遇到了错误INSERT, 看来您已经在表上创建了另一个由更新操作触发的触发器,或者您已经写了另一个插入并从该触发器返回SQL Error [54001]: ERROR: stack depth limit exceeded。您必须就如何处理它是否是另一个触发器(删除它或修改它)进行电话咨询,但这超出了此问题的范围,如果您还有其他问题,则应单独询问)

您可以通过简单地查询NEWinformation_schema.triggers来检查表上是否存在触发器,有关更多详细信息,请参考this answer