Postgresql: проверьте, существует ли значение в таблице через триггер - PullRequest
0 голосов
/ 13 января 2019

Я знакомлюсь с триггерами в (Postgre) sql.

Теперь у меня есть таблица Verine (это команды на немецком языке).

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

Это очень маленькая вещь, которую я написал, чтобы понять, как работают создание таблиц, сортировка и представления, и теперь я использую это для триггеров. В любом случае команда - это команда, очевидно, название команды и первичный ключ, пункт - это очки, а серия - это разделение команды (чтобы вы понимали, что означают разные домены).

Проблема начинается здесь:

Итак, предположим, у меня есть команда, скажем, "Ювентус", уже в моем столе "Верейн". Если я затем захочу вставить другую строку / кортеж с тем же ключом «Ювентус», вместо того, чтобы требовать для них две записи, мне бы хотелось обновить значения ключа «Ювентус» (заменив новые значения старыми). , В приведенном ниже примере я пытаюсь сделать это с баллами.

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 (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)"

Как я могу исправить свой код так, чтобы он делал то, что я хочу?

Извините, что слишком многословен. Я просто хочу убедиться, что вы понимаете, как это должно работать. Да, я задавал вопрос, прежде чем относился к одному и тому же заданию, но это совсем другая проблема. Извините за это.

1 Ответ

0 голосов
/ 13 января 2019

В основном вам нужен синтаксис UPSERT, как показано в в этом ответе с использованием столбца 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 не будет выполнять оператор триггера (т. Е. Основная операция INSERT), тогда как RETURN NEW; продолжается с запланированным INSERT выполнением оператора в обычном режиме.

Демо

Теперь, подойдя к вашей ошибке SQL Error [54001]: ERROR: stack depth limit exceeded, похоже, что у вас уже есть другой триггер в таблице, который запускается операцией обновления, или вы написали другую вставку и возвращаете NEW из триггера. Вы должны принять решение о том, как обрабатывать, если это другой триггер (либо удалить его, либо изменить его, но это выходит за рамки этого вопроса, и вы должны задать его отдельно, если у вас есть дальнейшие проблемы)

Вы можете проверить наличие триггеров в таблице, просто запросив information_schema.triggers или pg_trigger, Подробнее см. этот ответ .

...