Πέτα ένα σφάλμα σε μια σκανδάλη MySQL

ψήφοι
136

Αν έχω ένα trigger before the updateσε ένα τραπέζι, πώς μπορώ να ρίξει ένα σφάλμα που εμποδίζει την ενημέρωση σχετικά με αυτό το τραπέζι;

Δημοσιεύθηκε 01/08/2008 στις 13:12
πηγή χρήστη
Σε άλλες γλώσσες...                            


6 απαντήσεις

ψήφοι
113

Από MySQL 5.5, μπορείτε να χρησιμοποιήσετε τη SIGNALσύνταξη για να ρίξει μια εξαίρεση :

signal sqlstate '45000' set message_text = 'My Error Message';

Κράτος 45000 είναι ένα γενικό κρατικό αντιπροσωπεύει «ανεπίλυτη ορίζονται από το χρήστη εξαίρεση».


Εδώ είναι ένα πιο ολοκληρωμένο παράδειγμα της προσέγγισης:

delimiter //
use test//
create table trigger_test
(
    id int not null
)//
drop trigger if exists trg_trigger_test_ins //
create trigger trg_trigger_test_ins before insert on trigger_test
for each row
begin
    declare msg varchar(128);
    if new.id < 0 then
        set msg = concat('MyTriggerError: Trying to insert a negative value in trigger_test: ', cast(new.id as char));
        signal sqlstate '45000' set message_text = msg;
    end if;
end
//

delimiter ;
-- run the following as seperate statements:
insert into trigger_test values (1), (-1), (2); -- everything fails as one row is bad
select * from trigger_test;
insert into trigger_test values (1); -- succeeds as expected
insert into trigger_test values (-1); -- fails as expected
select * from trigger_test;
Απαντήθηκε 25/08/2011 στις 12:14
πηγή χρήστη

ψήφοι
52

Εδώ είναι ένα hack που μπορεί να λειτουργήσει. Δεν είναι καθαρό, αλλά φαίνεται σαν να μπορούσε να λειτουργήσει:

Ουσιαστικά, μπορείτε απλά να προσπαθήσουμε να ενημερώσετε μια στήλη που δεν υπάρχει.

Απαντήθηκε 01/08/2008 στις 14:02
πηγή χρήστη

ψήφοι
28

Δυστυχώς, η απάντηση που παρέχεται από @RuiDC δεν λειτουργεί σε εκδόσεις MySQL πριν από την 5.5, διότι δεν υπάρχει εφαρμογή των ΣΗΜΑ για αποθηκευμένες διαδικασίες.

Η λύση που έχω βρει είναι να προσομοιώσει ένα σήμα ρίχνοντας ένα table_name doesn't existσφάλμα, πιέζοντας ένα προσαρμοσμένο μήνυμα σφάλματος σε το table_name.

Η αμυχή θα μπορούσε να εφαρμοστεί χρησιμοποιώντας εναύσματα ή χρησιμοποιώντας μια αποθηκευμένη διαδικασία. Έχω περιγράψει και τις δύο παρακάτω επιλογές ακολουθώντας το παράδειγμα που χρησιμοποιείται από @RuiDC.

χρησιμοποιώντας ωθήσεις

DELIMITER $$
-- before inserting new id
DROP TRIGGER IF EXISTS before_insert_id$$
CREATE TRIGGER before_insert_id
    BEFORE INSERT IGNORE  ON test FOR EACH ROW
    BEGIN
        -- condition to check
        IF NEW.id < 0 THEN
            -- hack to solve absence of SIGNAL/prepared statements in triggers
            UPDATE `Error: invalid_id_test` SET x=1;
        END IF;
    END$$

DELIMITER ;

Χρησιμοποιώντας μια αποθηκευμένη διαδικασία

Αποθηκευμένες διαδικασίες σας επιτρέπει να χρησιμοποιήσετε τη δυναμική SQL, η οποία καθιστά δυνατή την ενθυλάκωση της λειτουργικότητας γενιάς λάθος σε μία διαδικασία. Η αντίστιξη είναι ότι θα πρέπει να ελέγχουν οι αιτήσεις εισάγετε τις μεθόδους / ενημέρωση, έτσι ώστε να χρησιμοποιούν μόνο αποθηκευμένη διαδικασία μας (όχι τη χορήγηση άμεσων προνόμια για την εισαγωγή αγνόησης / UPDATE).

DELIMITER $$
-- my_signal procedure
CREATE PROCEDURE `my_signal`(in_errortext VARCHAR(255))
BEGIN
    SET @sql=CONCAT('UPDATE `', in_errortext, '` SET x=1');
    PREPARE my_signal_stmt FROM @sql;
    EXECUTE my_signal_stmt;
    DEALLOCATE PREPARE my_signal_stmt;
END$$

CREATE PROCEDURE insert_test(p_id INT)
BEGIN
    IF NEW.id < 0 THEN
         CALL my_signal('Error: invalid_id_test; Id must be a positive integer');
    ELSE
        INSERT IGNORE  INTO test (id) VALUES (p_id);
    END IF;
END$$
DELIMITER ;
Απαντήθηκε 28/01/2012 στις 16:46
πηγή χρήστη

ψήφοι
10

Η ακόλουθη διαδικασία είναι (σε ​​mysql5) έναν τρόπο να ρίξει έθιμο λάθη, και να συνδεθείτε ταυτόχρονα:

create table mysql_error_generator(error_field varchar(64) unique) engine INNODB;
DELIMITER $$
CREATE PROCEDURE throwCustomError(IN errorText VARCHAR(44))
BEGIN
    DECLARE errorWithDate varchar(64);
    select concat("[",DATE_FORMAT(now(),"%Y%m%d %T"),"] ", errorText) into errorWithDate;
    INSERT IGNORE  IGNORE INTO mysql_error_generator(error_field) VALUES (errorWithDate);
    INSERT IGNORE  INTO mysql_error_generator(error_field) VALUES (errorWithDate);
END;
$$
DELIMITER ;


call throwCustomError("Custom error message with log support.");
Απαντήθηκε 08/11/2012 στις 17:15
πηγή χρήστη

ψήφοι
6
CREATE TRIGGER sample_trigger_msg 
    BEFORE INSERT IGNORE 
FOR EACH ROW
    BEGIN
IF(NEW.important_value) < (1*2) THEN
    DECLARE dummy INT;
    SELECT 
           Enter your Message Here!!!
 INTO dummy 
        FROM mytable
      WHERE mytable.id=new.id
END IF;
END;
Απαντήθηκε 12/08/2016 στις 18:08
πηγή χρήστη

ψήφοι
4

Μια άλλη μέθοδος (hack) (αν δεν είναι σε 5.5+ για κάποιο λόγο), ώστε να μπορείτε να χρησιμοποιήσετε:

Εάν έχετε ένα απαιτούμενο πεδίο, στη συνέχεια, μέσα σε μια σκανδάλη που τον απαιτούμενο χώρο σε μια μη έγκυρη τιμή, όπως NULL. Αυτό θα λειτουργήσει τόσο για αγνόησης INSERT και UPDATE. Να σημειωθεί ότι αν NULL είναι μια έγκυρη τιμή για τον υποχρεωτικό πεδίο (για κάποιο τρελό λόγο) τότε αυτή η προσέγγιση δεν θα λειτουργήσει.

BEGIN
    -- Force one of the following to be assigned otherwise set required field to null which will throw an error
    IF (NEW.`nullable_field_1` IS NULL AND NEW.`nullable_field_2` IS NULL) THEN
        SET NEW.`required_id_field`=NULL;
    END IF;
END

Αν είστε σε 5.5+, στη συνέχεια, μπορείτε να χρησιμοποιήσετε την κατάσταση του σήματος, όπως περιγράφεται σε άλλες απαντήσεις:

BEGIN
    -- Force one of the following to be assigned otherwise use signal sqlstate to throw a unique error
    IF (NEW.`nullable_field_1` IS NULL AND NEW.`nullable_field_2` IS NULL) THEN
        SIGNAL SQLSTATE '45000' set message_text='A unique identifier for nullable_field_1 OR nullable_field_2 is required!';
    END IF;
END
Απαντήθηκε 09/04/2016 στις 23:11
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more