Gooi een fout in een MySQL trekker

stemmen
136

Als ik een trigger before the updateop een tafel, hoe kan ik gooi een fout die de update voorkomt op die tafel?

De vraag is gesteld op 01/08/2008 om 13:12
bron van user
In andere talen...                            


6 antwoorden

stemmen
113

Met ingang van MySQL 5.5, kunt u het gebruiken SIGNALsyntax om een uitzondering te gooien :

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

State 45000 is een generieke staat vertegenwoordigen "onverwerkte door de gebruiker gedefinieerde uitzondering".


Hier is een volledig voorbeeld van de aanpak:

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;
antwoordde op 25/08/2011 om 12:14
bron van user

stemmen
52

Hier is een hack die kunnen werken. Het is niet schoon, maar het lijkt erop dat het zou kunnen werken:

In wezen, je gewoon proberen om een ​​kolom die niet bestaat bij te werken.

antwoordde op 01/08/2008 om 14:02
bron van user

stemmen
28

Helaas heeft het antwoord van @RuiDC niet werken in MySQL versies ouder dan 5.5, omdat er geen uitvoering van SIGNAAL voor opgeslagen procedures.

De oplossing die ik heb gevonden is om een signaal te gooien van een te simuleren table_name doesn't existfout, waardoor een aangepaste foutmelding in het table_name.

De hack zou kunnen worden uitgevoerd met behulp van triggers of met behulp van een opgeslagen procedure. Ik beschrijf beide opties hieronder na de door @RuiDC voorbeeld.

Met behulp van triggers

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 ;

Met behulp van een opgeslagen procedure

Opgeslagen procedures stelt u in staat om dynamische sql, die mogelijk de inkapseling van fout generatie de functionaliteit van de in een procedure maakt gebruik. Het contrapunt is dat we moeten de controle van de toepassingen in te voegen / updatemethoden, zodat ze alleen gebruik maken van onze opgeslagen procedure (niet direct privileges het verlenen om INSERT IGNORE / 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 ;
antwoordde op 28/01/2012 om 16:46
bron van user

stemmen
10

De volgende procedure is (op MySQL5) een manier om aangepaste fouten te gooien, en meldt ze op hetzelfde moment:

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.");
antwoordde op 08/11/2012 om 17:15
bron van user

stemmen
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;
antwoordde op 12/08/2016 om 18:08
bron van user

stemmen
4

Een andere (hack) methode (als je niet op 5.5+ om wat voor reden) die u kunt gebruiken:

Als u een verplicht veld, vervolgens binnen een trigger te stellen het vereiste veld op een ongeldige waarde, zoals NULL. Dit zal werken voor zowel INSERT negeren en UPDATE. Let wel dat als NULL is een geldige waarde voor het gewenste veld (voor sommige gekke reden) dan is deze aanpak niet zal werken.

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

Als je op 5.5+ dan kunt u het signaal staat te gebruiken, zoals beschreven in andere antwoorden:

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
antwoordde op 09/04/2016 om 23:11
bron van user

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