Я довольно новый (как для чтения, о-он-5-часовой давности новый) в триггерах, поэтому мне нужна помощь по этому вопросу:DB2 SQL Триггеры
Создать таблицу TelefonnummerAenderung
и удалить все данные в нем, если он уже существует. Создание триггера, отвечающие следующим условиям: (я надеюсь, что это нормально для вас, ребята, если я не переводить все имена таблиц и атрибутов на английский язык.)
-a изменение атрибута Telefonnummer
в KundenKontaktDaten
разрешено только 15 сек после последнего изменения -otherwise в SIGNAL SQLSTATE '70001'
выброшен
-когда изменения Telefonnummer
в KundenKontaktDaten
новая запись в TelefonnummerAenderungen
создается содержащий старый Telefonnummer
и время было изменено
-если новый и й е старые Telefonnummer
то же самое, не провоцирующее действие не происходит
Эти две таблицы являются следующие:
KundenKontaktDaten
: (редактирование: Я забыл, Kunden_Nr
также ссылки Kunde(Kunden_Nr)
. Это не имеет значения для выполнения этой задачи, просто говоря)
create table KundenKontaktDaten
(Kunden_Nr int not null primary key,
Twitter_Id Varchar(40),
Google_Id bigint,
Facebook_Id bigint,
Skype_Id Varchar(64),
Telefonnummer Varchar(50)
);
TelefonnummerAenderungen
:
create table TelefonnummerAenderungen
(GEAENDERT_AM TIMESTAMP NOT NULL,
KUNDEN_NR INTEGER NOT NULL,
ALTE_NUMMER VARCHAR(50),
FOREIGN KEY(KUNDEN_NR)
REFERENCES KUNDE(KUNDEN_NR)
ON DELETE CASCADE
ON UPDATE RESTRICT,
PRIMARY KEY(GEAENDERT_AM, KUNDEN_NR)
);
мое решение (Java-код, не имеет значения в отношении вопроса):
static public void triggerAnlegen(Connection con) throws SQLException {
Statement stmt = con.createStatement();
try {
stmt.execute("create table TelefonnummerAenderungen (GEAENDERT_AM TIMESTAMP NOT NULL, KUNDEN_NR INTEGER NOT NULL, ALTE_NUMMER VARCHAR(50), FOREIGN KEY(KUNDEN_NR) REFERENCES KUNDE(KUNDEN_NR) ON DELETE CASCADE ON UPDATE RESTRICT, PRIMARY KEY(GEAENDERT_AM, KUNDEN_NR))");
} catch (SQLException e) {
if(e.getErrorCode()==-601){
stmt.execute("DELETE FROM TelefonnummerAenderungen");
}
}
try{
stmt.execute("CREATE TRIGGER haTrigger AFTER UPDATE OF Telefonnummer ON KundenKontaktDaten REFERENCING NEW as n_row OLD as o_row FOR EACH ROW WHEN (o_row.Telefonnummer<>n_row.Telefonnummer) "+
"BEGIN " +
"IF(NOT EXISTS(SELECT * FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr)) " +
"THEN " +
"INSERT INTO TelefonnummerAenderungen VALUES (CURRENT TIMESTAMP,n_row.Kunden_Nr,o_row.Telefonnummer); " +
"ELSEIF(CURRENT TIMESTAMP<((SELECT GEAENDERT_AM FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr) + 15 seconds)) " +
"THEN " +
"UPDATE KundenKontaktDaten SET Kunden_Nr=o_row.Kunden_Nr,Twitter_Id=o_row.Twitter_Id,Google_Id=o_row.Google_Id,Facebook_Id=o_row.Facebook_Id,Skype_Id=o_row.Skype_Id,Telefonnummer=o_row.Telefonnummer;" +
"SIGNAL SQLSTATE '70001'; " +
"ELSE " +
"UPDATE TelefonnummerAenderungen SET GEAENDERT_AM=CURRENT TIMESTAMP,ALTE_NUMMER=o_row.Telefonnummer WHERE Kunden_Nr=n_row.Kunden_Nr; " +
"END IF;" +
"END");
} catch (SQLException e) {
throw e;
}
}
SQL- только:
CREATE TRIGGER haTrigger
AFTER UPDATE OF Telefonnummer ON KundenKontaktDaten
REFERENCING
NEW as n_row
OLD as o_row
FOR EACH ROW WHEN (o_row.Telefonnummer <> n_row.Telefonnummer)
BEGIN
IF (NOT EXISTS (SELECT *
FROM TelefonnummerAenderungen
WHERE Kunden_Nr=n_row.Kunden_Nr)
)
THEN
INSERT INTO TelefonnummerAenderungen
VALUES
(CURRENT TIMESTAMP, n_row.Kunden_Nr, o_row.Telefonnummer);
ELSEIF (CURRENT TIMESTAMP < ((SELECT GEAENDERT_AM
FROM TelefonnummerAenderungen
WHERE Kunden_Nr=n_row.Kunden_Nr) + 15 seconds)
)
THEN
UPDATE KundenKontaktDaten
SET Kunden_Nr = o_row.Kunden_Nr,
Twitter_Id = o_row.Twitter_Id,
Google_Id = o_row.Google_Id,
Facebook_Id = o_row.Facebook_Id,
Skype_Id = o_row.Skype_Id,
Telefonnummer = o_row.Telefonnummer;
SIGNAL SQLSTATE '70001';
ELSE
UPDATE TelefonnummerAenderungen
SET GEAENDERT_AM = CURRENT TIMESTAMP,
ALTE_NUMMER = o_row.Telefonnummer
WHERE Kunden_Nr = n_row.Kunden_Nr;
END IF;
END
Я использовал AFTER UPDATE OF [...]
, потому что не был уверен, что (при использовании BEFORE UPDATE OF [...]
) запрос, вызвавший запуск триггера, все еще выполняется после обработки триггера.
[редактировать: изменил его BEFORE
и выронил
UPDATE KundenKontaktDaten
SET Kunden_Nr = o_row.Kunden_Nr,
Twitter_Id = o_row.Twitter_Id,
Google_Id = o_row.Google_Id,
Facebook_Id = o_row.Facebook_Id,
Skype_Id = o_row.Skype_Id,
Telefonnummer = o_row.Telefonnummer;
, потому что я получаю каскадные ошибки запуска в противном случае; не изменит код здесь, хотя для вопроса прозрачности]
Это (очевидно) моя домашняя работа (не проблема реального мира, надеюсь, что все в порядке, и мы получаем градуировку автоматически с помощью некоторой тестовой функции, которую мы не знаем - таким образом, я знаю, что мои результаты неверны Но я не знаю, какая часть этого является неправильным, так что мне нужна помощь по этому
Edit 2:
Мой пост становится.. я думаю, что создание ответа было бы более ясным, чем дальнейшее редактирование моего сообщения:
После дополнительных испытаний я выяснил проблему с первой попытки:
При использовании 'ПОСЛЕ ОБНОВЛЕНИЯ ...'в моем триггере, слишком поздно, и я не могу отменить изменения, внесенные в «KundenKontaktDaten», хотя 15 секунд не прошло, так как это приведет к каскадным вызовам триггера.
При использовании «ПЕРЕД ОБНОВЛЕНИЕМ ...» DB2 ограничивает меня использованием любых INSERT или UPDATE.
Так я понял, что я должен использовать INSTEAD OF
:
CREATE TRIGGER haTrigger INSTEAD OF UPDATE ON KundenKontaktDaten REFERENCING NEW as n_row OLD as o_row FOR EACH ROW
BEGIN
IF(o_row.Telefonnummer<>n_row.Telefonnummer) THEN
IF(NOT EXISTS(SELECT * FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr)) THEN
UPDATE KundenKontaktDaten SET Kunden_Nr=n_row.Kunden_Nr,Twitter_Id=n_row.Twitter_Id,Google_Id=n_row.Google_Id,Facebook_Id=n_row.Facebook_Id,
Skype_Id=n_row.Skype_Id,Telefonnummer=n_row.Telefonnummer WHERE Kunden_Nr=o_row.Kunden_Nr;
INSERT INTO TelefonnummerAenderungen VALUES (CURRENT TIMESTAMP,n_row.Kunden_Nr,o_row.Telefonnummer);
ELSEIF(CURRENT TIMESTAMP<((SELECT GEAENDERT_AM FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr) + 15 seconds)) THEN
SIGNAL SQLSTATE '70001';
ELSE
UPDATE KundenKontaktDaten SET Kunden_Nr=n_row.Kunden_Nr,Twitter_Id=n_row.Twitter_Id,Google_Id=n_row.Google_Id,Facebook_Id=n_row.Facebook_Id,
Skype_Id=n_row.Skype_Id,Telefonnummer=n_row.Telefonnummer WHERE Kunden_Nr=o_row.Kunden_Nr;
UPDATE TelefonnummerAenderungen SET GEAENDERT_AM=CURRENT TIMESTAMP,ALTE_NUMMER=o_row.Telefonnummer WHERE Kunden_Nr=n_row.Kunden_Nr;
END IF;
END IF;
END
в результате еще одной ошибки:
DB2 SQL Error: SQLCODE=-159, SQLSTATE=42809, SQLERRMC=GRP13.KUNDENKONTAKTDATEN;TABLE;UNTYPED VIEW
Поскольку я понятия не имею, кто-нибудь знает, что проблема с этой? Если ни Before
, ни After
, ни Instead of
не работают, то у меня немного вариантов.
Я предлагаю вам извлечь Java из картинки, пока вы не выясните триггер. Покажите только код SQL и объясните, как результаты выполнения триггера отличаются от ожидаемого. – mustaccio
Я просто редактирую сообщение и добавляю только запрос sql. Кроме того, я провел некоторое дополнительное тестирование, и если я изменил атрибут «Telefonnummer» слишком быстро (<15 секунд друг от друга), теперь я получаю: Произошла ошибка в вызванном SQL-заявлении в триггере «GRP13.HATRIGGER». Информация, возвращаемая для ошибки, включает SQLCODE «-724», SQLSTATE «54038» <- не должен ли я получить sqlstate = 70001, так как это то, что бросает? –
nvm, изменил часть с «ПОСЛЕ ОБНОВЛЕНИЯ ...» до «ПЕРЕД ОБНОВЛЕНИЕМ» -> теперь я получаю правильный SQLSTATE; все еще не работает, хотя, и у меня нет идеи, почему (как я уже сказал, его автоматическое тестирование этого, и у меня нет исходного кода для теста). Он работает, проверяя вручную. –