[ biske86 @ 02.09.2010. 18:40 ] @
Otvorim transakciju i hoću da ubacim jedan red u tabeli t1 i onda hoću da proverim da li je došlo do greške. Ako jeste onda onda ne nastavljam rad a ako je sve u redu onda ubacim red u tabeli t2. Da li je ovako nešto moguće u mysql-u?
[ bogdan.kecman @ 02.09.2010. 19:16 ] @
Citat:

hoću da ubacim jedan red u tabeli t1 i onda hoću da proverim da li je došlo do greške


sta znaci "hocu da proverim da li je doslo do greske" ?

svaki mysql statement vraca kod greske (ok ili id greske) .. sve sto treba da proveris je kada izvrsis query sta ti je vratio kao status .. zavisno kako izvrsavas upite to ide razlicito ...

npr ako to radis iz C-a: http://dev.mysql.com/doc/refman/5.5/en/mysql-query.html
Citat:

Return Values
Zero if the statement was successful. Nonzero if an error occurred.

Errors

*CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.

*CR_SERVER_GONE_ERROR
The MySQL server has gone away.

*CR_SERVER_LOST
The connection to the server was lost during the query.

*CR_UNKNOWN_ERROR
An unknown error occurred.


ako to radis iz php-a: http://www.php.net/manual/en/function.mysql-query.php
Citat:

Return Values
For SELECT, SHOW, DESCRIBE, EXPLAIN and other statements returning resultset, mysql_query() returns a resource on success, or FALSE on error.
For other type of SQL statements, INSERT, UPDATE, DELETE, DROP, etc, mysql_query() returns TRUE on success or FALSE on error.

(koja je greska pokupis sa mysql_error())


Standardno unutar stored procedure ne mozes da "iniciras gresku" pre verzije 5.5 posto signal i resignal nisu podrzani. Od 5.5 (koji bi btw svaki dan trebalo da postane GA) signal i resignal su implementirani: http://dev.mysql.com/doc/refman/5.5/en/signal-resignal.html

Unutar stored procedure greske ne proveravas direktno nego pises handler za greske: http://dev.mysql.com/doc/refman/5.5/en/declare-handler.html


[ biske86 @ 02.09.2010. 19:38 ] @
sta znaci "hocu da proverim da li je doslo do greske" ?

Pa probam da ubacim neki red u tabeli i ne može da se ubaci zato što sam narušio integritet podataka. Nije ni bitno samo ne može da se ubaci red u tabeli. Ako je to u pitanju onda neću da izvršavam sledeću naredbu za ubacivanje reda u tabeli t2.

Ovo sam pitao za Procedure.
[ bogdan.kecman @ 02.09.2010. 19:52 ] @
kao sto sam ti napisao, "za procedure" pravis handler ( http://dev.mysql.com/doc/refman/5.5/en/declare-handler.html ) i tako detektujes gresku ... ne mozes da sa " IF (bilo greske) .. " odradis posao

generalno ti kada ti se desi greska uglavnom hoces da abortiras transakciju tako da ako ti transakcija pocinje i zavrsava se u stored proceduri kazes mu samo da u error handleru odradi rollback i izadje napolje i to je to, bas te briga u kom trenutku u proceduri se desila greska (tj ti napises proceduru kao da je sve uvek ok .. begin, insert, insert, select, update, insert, insert ... insert, commit a stavis error handler koji ce da odradi rollback i izadje napolje ako se desi greska tako da ako se desi greska posle prvog ili posle 10tog inserta svejedno ce cela transakcija da bude bacena u vodu)

imas primer ovde: http://www.devshed.com/c/a/MySQL/Error-Handling/ (i naravno ovde: http://dev.mysql.com/doc/refman/5.5/en/declare-handler.html )



[ bogdan.kecman @ 02.09.2010. 20:26 ] @
btw, evo ti primer

Code:


mysql> DROP TABLE IF EXISTS `d1`;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE `d1` (
    ->   `id` int(11) NOT NULL,
    ->   `a` char(10) DEFAULT NULL,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.03 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO `d1` (id, a) VALUES (100, 'bbb');
Query OK, 1 row affected (0.01 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)


mysql> DROP PROCEDURE IF EXISTS p ;
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER $$
mysql> 
mysql> CREATE PROCEDURE p ()
    -> BEGIN
    ->   DECLARE EXIT HANDLER FOR SQLEXCEPTION
    ->   BEGIN
    ->     SELECT "ERROR";
    ->     ROLLBACK;
    ->   END;
    ->   SET autocommit=0;
    -> 
    ->   START TRANSACTION;
    ->   DELETE FROM `d1`;
    ->   INSERT INTO `d1` (id, a) VALUES (1,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (2,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (3,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (4,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (5,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (6,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (7,'aaa');
    -> 
    ->   INSERT INTO `d1` (id, a) VALUES (3,'aaa');
    -> 
    ->   INSERT INTO `d1` (id, a) VALUES (8,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (9,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (10,'aaa');
    ->   COMMIT;
    -> END$$
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> call p();
+-------+
| ERROR |
+-------+
| ERROR |
+-------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> select * from d1;
+-----+------+
| id  | a    |
+-----+------+
| 100 | bbb  |
+-----+------+
1 row in set (0.00 sec)

mysql> 



dakle kao sto vidis hendler je zakinuo celu transakciju
naravno ako nemas gresku (ona trojka) onda to prodje ok:

Code:

mysql> DROP TABLE IF EXISTS `d1`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `d1` (
    ->   `id` int(11) NOT NULL,
    ->   `a` char(10) DEFAULT NULL,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.03 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO `d1` (id, a) VALUES (100, 'bbb');
Query OK, 1 row affected (0.01 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP PROCEDURE IF EXISTS p ;
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER $$
mysql> CREATE PROCEDURE p ()
    -> BEGIN
    ->   DECLARE EXIT HANDLER FOR SQLEXCEPTION
    ->   BEGIN
    ->     SELECT "ERROR";
    ->     ROLLBACK;
    ->   END;
    ->   SET autocommit=0;
    -> 
    ->   START TRANSACTION;
    ->   DELETE FROM `d1`;
    ->   INSERT INTO `d1` (id, a) VALUES (1,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (2,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (3,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (4,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (5,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (6,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (7,'aaa');
    -> 
    ->   -- INSERT INTO `d1` (id, a) VALUES (3,'aaa');
    -> 
    ->   INSERT INTO `d1` (id, a) VALUES (8,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (9,'aaa');
    ->   INSERT INTO `d1` (id, a) VALUES (10,'aaa');
    ->   COMMIT;
    -> END$$
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> call p();
Query OK, 0 rows affected (0.00 sec)

mysql> select * from d1;
+----+------+
| id | a    |
+----+------+
|  1 | aaa  |
|  2 | aaa  |
|  3 | aaa  |
|  4 | aaa  |
|  5 | aaa  |
|  6 | aaa  |
|  7 | aaa  |
|  8 | aaa  |
|  9 | aaa  |
| 10 | aaa  |
+----+------+
10 rows in set (0.00 sec)


nadam se da je jasnije
[ biske86 @ 24.09.2010. 20:47 ] @
Jasno je ko dan. Hvala isprobao sam ovaj primer koji si dao i radi odlično.
[ biske86 @ 26.09.2010. 13:21 ] @
Citat:
bogdan.kecman: btw, evo ti primer
Code:


    ->   DECLARE EXIT HANDLER FOR SQLEXCEPTION
    ->   BEGIN
    ->     SELECT "ERROR";
    ->     ROLLBACK;
    ->   END;



Da li je moguće da umesto ovog Select "ERROR" stavim recimo SET poruka="naziv tacne greske"? poruka je izlazni parametar procedure.
Hoću da javim korisniku kakva je to greška koja se desila (nije bitno što će biti na elgleskom). Nadam se da sam bio jasan šta mi treba.
[ bogdan.kecman @ 27.09.2010. 00:01 ] @
skoro pa sam siguran da moze da se izbaci bar kod greske ali da me ubijes ne mogu da se setim kako :(

SHOW ERRORS; ce ti odraditi to umesto SELECT "ERROR"; dakle izbacice zadnju gresku (nisam probao, trebalo bi da radi i u sp) ali nemam pojma kako to da izvadis u varijablu, mislim da toga nema u IS bazi ali mozes da probas da prodjes kroz svih par tabela tamo, mozda nadjes nesto :)


EDIT: evo ga feature request: http://bugs.mysql.com/bug.php?id=11660 ... na zalost jos uvek nije ni u jednom build-u iako postoji patch i za 5.0 i 5.1 i 5.5 ... da li ce ili nece biti videcemo (obzirom da je jedan veliki klijent upravo trazio da se to "pogura")

[Ovu poruku je menjao bogdan.kecman dana 27.09.2010. u 03:14 GMT+1]
[ bogdan.kecman @ 27.09.2010. 17:43 ] @
za 5.5 imas implementiran signal i resignal, ne rade bas to sto ti hoces ali vrlo korisno ako radis sa sp-ovima: http://dev.mysql.com/doc/refman/5.5/en/signal-resignal.html
[ biske86 @ 20.10.2010. 16:33 ] @
Imam problem sa jednom procedurom. Naime pozivam je iz php-a i postavio sam kada kliknem na dugme sačuvaj da se pozove procedura SP_NASTAVNIK_INSERT i da isčitam parametar p_poruka i da prikažem poruku.. Kada unesem za parametar p_Katedra vrednost koja ne postoji onda mi se pravilno prikazuje greška. Ali kada za parametar p_BrojRadovaSaSCIListe koji je int tipa unesem tekst onda mi se uopšte ne prikazuje poruka ni da je dobro ni da je loše. Šta mislite o ovom problemu. Da li je do mysql ili php?

Code (sql):
-- --------------------------------------------------------------------------------
-- Routine DDL
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_NASTAVNIK_INSERT`(OUT p_poruka VARCHAR(255), p_Ime VARCHAR(25), p_Prezime VARCHAR(35), p_ImeRoditelja VARCHAR(25), p_DatumRodjenja DATE, p_JMBG CHAR(13), p_BrojRadovaUDomacimCasopisima tinyint(4), p_BrojRadovaSaSCIListe tinyint(4), p_Pol VARCHAR(6), p_Katedra VARCHAR(40))
BEGIN
   
    DECLARE v_polid tinyint;
    DECLARE v_katedraid tinyint;
   
    DECLARE exit handler FOR sqlexception
    BEGIN
        ROLLBACK;
        SET p_poruka='Greška! Unos podataka nije izvršen.';
    END;
    SET names utf8;
    SET v_polid=F_GET_POLID(p_Pol);
    SET v_katedraid=F_GET_KATEDRAID(p_katedra);
   
    BEGIN
        SET autocommit=0;
        START TRANSACTION;
        INSERT INTO NASTAVNIK(Ime, Prezime, ImeRoditelja, DatumRodjenja, JMBG, BrojRadovaUDomacimCasopisima, BrojRadovaSaSCIListe, PolID, KatedraID) VALUES (p_Ime, p_Prezime, p_ImeRoditelja, p_DatumRodjenja, p_JMBG, p_BrojRadovaUDomacimCasopisima, p_BrojRadovaSaSCIListe, v_PolID, v_KatedraID);
        commit;
        SET p_poruka='Unos podataka je uspešno izvršen!';
    END;
                           
END