mysql trigger

Hello!

Az alábbi triggert szeretném léterhozni mysql-ben:

CREATE TRIGGER mac_trigger AFTER INSERT ON radacct FOR EACH ROW
IF (SELECT COUNT(*) FROM radcheck WHERE ( UserName = NEW.UserName AND Attribute = 'Calling-Station-Id' AND Value = '')) > 0 THEN
UPDATE radcheck SET Value = `NEW.Calling-Station-Id` WHERE (UserName = NEW.UserName AND Attribute = 'Calling-Station-Id')
END IF;

(nem rakom code-ba, mert akkor látszanak a mod_security miatt belerakott

<m>

-ek)

De syntax errot-t kapok. Mit csinálok rosszul?

Annyit szeretnék, hogy ha a radacct táblába beszúrunk egy új rekordot, akkor a radcheck táblában megnézzük, hogy ahol UserName == a radacct-ba beszúrt új sor UserName mezője, és Attribute == 'Calling-Station-Id', ott a Value mező üres-e. Ha üres, akkor szúrjuk be oda a radacct táblába újonnan beszúrt sor Calling-Station-Id mezőjét.

Tudtok nekem segíteni?

Előre is köszönöm!

Petya

Hozzászólások

Rakd begin end közé, és használj mási kdelimiter ehhez, valahogy így:

mysql> deli miter //
mysql> CRE ATE TRIGGER mac_trigger AFTER INSERT ON radacct FOR EACH ROW
- > BE GIN
- > IF (SEL ECT COUNT(*) FROM radcheck WHERE ( UserName = NEW.UserName AND Attribute = 'Calling-Station-Id' AND Value = '')) > 0 THEN
- > UPD ATE radcheck SET Value = `NEW.Calling-Station-Id` WHERE (UserName = NEW.UserName AND Attribute = 'Calling-Station-Id')
- > END IF;
- > END;
mysql> //
mysql> deli miter ;

--
The Net is indeed vast and infinite...
http://gablog.eu

mysql> deli miter //
mysql> CRE ATE TRIGGER mac_trigger AFTER INSERT ON radacct FOR EACH ROW
-> BEGIN
-> IF (SE LECT COUNT(*) FROM radcheck WHERE ( UserName = NEW.UserName AND Attribute = 'Calling-Station-Id' AND Value = '')) > 0 THEN
-> UPD ATE radcheck SET Value = `NEW.Calling-Station-Id` WHERE (UserName = NEW.UserName AND Attribute = 'Calling-Station-Id')
-> END IF;
-> END;
-> //
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE radcheck SET Value = `NEW.Calling-Station-Id` WHERE (UserName = NEW.UserN' at line 4

Köszönöm, így már elfogadja, viszont nem működik.

Közben mást is javítottam (a RADIUS nem úgy működött, ahogy elsőre gondoltam), tehát a mostani állapot:


DELIMITER //
CRE ATE TRIGGER mac_trigger AFTER INS ERT ON radacct FOR EACH ROW
BEGIN
IF (SEL ECT COUNT(*) FROM radcheck WHERE ( UserName = NEW.UserName AND Attribute = 'Calling-Station-Id')) = 0 
THEN INS ERT INTO radcheck (id, UserName, Attribute, op, Value) VALUES ( NULL, NEW.UserName, 'Calling-Station-Id', '==' ,NEW.`CallingStationId`);
END IF;
END;
//

Annyi a változás, hogy nem az üres sort, hanem a sor hiányát kell figyelni, és nem UPD ATE hanem INS ERT van, ha aktiválódik a trigger.

Petya

Hello!

Azt hiszem, megvan a probléma, a triggerben lévő SQL parancsok nem futnak le:

IF ((SE LECT COUNT(*) FROM radcheck WHERE ( UserName = 'triggerteszt' AND Attribute = 'Calling-Station-Id')) = 0 )
THEN INS ERT INTO radcheck (id, UserName, Attribute, op, Value) VALUES ( NULL, 'triggerteszt', 'Calling-Station-Id', '==' ,'proba');
END IF;

Erre megint csak syntax error. Egyáltalán hogy kell a COUNT kimenetét az IF-nek megadni? Erre sehol nem látok leírást, példát.

Petya

Lehet hogy nincs igazam, akkor majd kijavítotok.
Nekem az a tapasztalatom, hogy a MySQL nem fogad el az IF feltételében select-et. Az ilyen nekem csk úgy müxik, hogy a select eredményét változóba rakom, és a változó értékét vizsgálom.

Mondom, lehet hogy én vagyok lammer, de eddig nekem csak imigyen ment.
(Debian "Sarge", Mysql 5.0.51-3)

---
"A megoldásra kell koncentrálni nem a problémára."

Próbáltam, de a DEC LARE-en is leakad.

BE GIN
DEC LARE x INT;
IF ((SE LECT COUNT(*) FROM radcheck IN TO x WHERE ( UserName = 'triggerteszt' AND Attribute = 'Calling-Station-Id')) = 0 )
THEN INS ERT INTO radcheck (id, UserName, Attribute, op, Value) VALUES ( NULL, 'triggerteszt', 'Calling-Station-Id', '==' ,'proba');
END IF;
END;

Vagy esetleg tárolt eljárásban tudok csak változót deklarálni?

szerk: próbálom a tárolt eljárást, de ez sem jó, syntax error:

DELI MITER //
CRE ATE PROC EDURE `mac_proc`(`user` VARCHAR(50), `mac` VARCHAR(50))
BEG IN
DEC LARE `x` INT := NULL;
SE LECT COUNT(*) FROM `radcheck` INTO `x` WHERE ( `UserName` = `user` AND `Attribute` = 'Calling-Station-Id');
IF `x` = 0 THEN IN SERT INTO `radcheck` (`id`, `UserName`, `Attribute`, `op`, `Value`) VALUES ( NULL, `user`, 'Calling-Station-Id', '==' ,`mac`);
END IF;
END;//

Petya

Elfogad.


cre ate trigger tg_szamlakiad_update after up dateon kimszamlacikklista
for each row
begin
if (SEL ECT vont FR OM `kimszamla` where szamla_id=NEW.szamla_id) < 1 then
up date keszlet set menny=menny+NEW.menny-OLD.menny where cikk_id=NEW.cikk_id and raktar_id=NEW.raktar_id;
end if;
end;

itt a szamlazombol egy selectes trigger.

pch

Hello!

Ezt próbáltam legutóbb:


delimiter //
CRE ATE TRIGGER `mac_trig` AFTER INS ERT ON `radacct` FOR EACH ROW
IF ( SEL ECT * FROM `radcheck` WHERE (`UserName` = NEW.`UserName` AND `Attribute` = 'Calling-Station-Id') ) < 1
THEN IN SERT INTO `radcheck` (`id`, `UserName`, `Attribute`, `op`, `Value`)
VALUES ( NULL, NEW.`UserName`, 'Calling-Station-Id', '==' ,NEW.`CallingStationId`);
END IF;
 END//

Erre syntax error-t dob, de ennek ellenére a trigger létrejön, de nem működik. Ha kézzel próbálom hívni a triggerben lévő INS ERT-et, akkor is hibát dob (illegal mix of collations for operation =), de a sort beszúrja.

Mi lehet a baj?

Petya

Úgy is próbáltam.

De valami akkor sem oké, ugyanis:

mysql> delimiter //
mysql> CRE ATE TRIG GER mac_trig AFTER INS ERT ON radacct FOR EACH ROW
    -> IF ( SEL ECT * FROM radcheck WHERE (UserName = NEW.UserName AND Attribute = Calling-Station-Id) ) < 1
    -> THEN INSE RT INTO radcheck (id, UserName, Attribute, op, Value)
    -> VALUE S ( NULL, NEW.UserName, 'Calling-Station-Id', '==' ,NEW.CallingStationId);
    -> END IF;
    -> END//
Query OK, 0 rows affected (0.02 sec)

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END' at line 1
mysql>

Ennek ellenére a trigger létrejön.

Próbálom aktiválni a triggert:

mysql>  INS ERT INTO `radacct` ( `RadAcctId` , `AcctSessionId` , `AcctUniqueId` , `UserName` , `Realm` , `NASIPAddress` , `NASPortId` , `NASPortType` , `AcctStartTime` , `AcctStopTime` , `AcctSessionTime` , `AcctAuthentic` , `ConnectInfo_start` , `ConnectInfo_stop` , `AcctInputOctets` , `AcctOutputOctets` , `CalledStationId` , `CallingStationId` , `AcctTerminateCause` , `ServiceType` , `FramedProtocol` , `FramedIPAddress` , `AcctStartDelay` , `AcctStopDelay` )
    -> VAL UES (
    -> NULL , '', '', 'triggerteszt', '', '', NULL , NULL , '0000-00-00 00:00:00', '0000-00-00 00:00:00', NULL , NULL , NULL , NULL , NULL , NULL , '', 'dfgydgdfg', '', NULL , NULL , '', NULL , NULL
    -> );
ERROR 1267 (HY000): Illegal mix of collations (utf8_hungarian_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
mysql>

Itt megtörténik az IN SERT, de a trigger nem fut le.

Petya

Hello!

Megint felhozom, hátha valaki tud segíteni.


mysql> DELIMITER //
mysql> CRE ATE TRIGGER mac_trig AFTER INS ERT ON radacct FOR EACH ROW
-> BEGIN
-> DECLARE cnt int(10);
-> SET cnt = 0;
-> SE LECT id INTO cnt FROM radcheck WHERE (UserName = NEW.UserName AND Attribute = Calling-Station-Id);
-> IF cnt = 0 THEN
-> INS ERT INTO radcheck (id, UserName, Attribute, op, Value)
-> VALUES ( NULL, NEW.UserName, 'Calling-Station-Id', '==' ,NEW.CallingStationId);
-> END IF;
-> END;// 

Most már sikerült elérni, hogy a trigger létrehozásakor nincs hibaüzenet, de INS ERT-kor ugyanúgy "illegal mix of collations", és nem fut le a trigger.

Petya

Próbálkozom, de pontosan melyik collation-knek kell stimmelni?


 INS ERT INTO `radacct` ( `RadAcctId` , `AcctSessionId` , `AcctUniqueId` , `UserName` , `Realm` , `NASIPAddress` , `NASPortId` , `NASPortType` , `AcctStartTime` , `AcctStopTime` , `AcctSessionTime` , `AcctAuthentic` , `ConnectInfo_start` , `ConnectInfo_stop` , `AcctInputOctets` , `AcctOutputOctets` , `CalledStationId` , `CallingStationId` , `AcctTerminateCause` , `ServiceType` , `FramedProtocol` , `FramedIPAddress` , `AcctStartDelay` , `AcctStopDelay` )
VALUES (
NULL , '', '', 'triggerteszt', '', '', NULL , NULL , '0000-00-00 00:00:00', '0000-00-00 00:00:00', NULL , NULL , NULL , NULL , NULL , NULL , '', 'asdgsdgsdg', '', NULL , NULL , '', NULL , NULL
)

#1267 - Illegal mix of collations (utf8_hungarian_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '=' 

Maga az adatbázis, és az összes tábla utf8_hungarian_ci-ben van. Az illető két tábla mezői viszont tényleg keverve vannak, az egyikben utf8_hungarian_ci, a másikban pedig utf8_general_ci a mezők collation-je.

Meg lehet ezt változtatni úgy, hogy vannak adatok a táblában? Próbáltam kidumpolni, és a dumpon megadni a mező collation-t, de erre hibát dobott.

Mindennhol utf8_hungarian_ci a collation, ennek ellenére a dump behúzásakor ut8_general_ci-re állnak be a mezők. Honnan veszi ezt a default értéket? Hogyan tudom megváltoztatni?

Petya

Minden szöveges oszlopnak van collationja, és minden adatbázisnak és táblának van default collationje. (Ez adja meg a rendezést a stringeken, pl. magyarban Czirók < Csipek )

phpmyadmin-al könnyen meg tudod változtatni a collation akár oszlopra, akár adatbázisra, egyébként:

ALTER TABLE `my_table` DEFAULT CHARACTER SET latin1 COLLATE latin1_general_ci

ALTER TABLE `my_table` COLLATE utf8-general_ci

Nem biztos, hogy érdemes megváltoztatni, lehet, hogy akkor más fog megborulni:
dinamikusan is castolhatsz egyik collationből a másikba (ez része az attribútum típusának):

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;

http://dev.mysql.com/doc/refman/5.0/en/charset-convert.html

Az hogy hol van gond - kivételesen - látszik a hibaüzenetből: "="

--
The Net is indeed vast and infinite...
http://gablog.eu