web-dev-qa-db-fra.com

Comment abandonner l'opération INSERT dans le déclencheur MySql?

J'ai une table contenant une URL et une chaîne représentant ses paramètres. Le problème est que je veux qu'une URL et une chaîne de paramètres soient la contrainte unique pour la table - c'est-à-dire qu'aucune entrée ne peut avoir la même chaîne d'URL ET de paramètre. La chaîne de paramètres peut être de longueur arbitraire (plus de 800 octets ou plus, ce qui correspond à la longueur maximale d'une clé MySql, donc je ne peux pas utiliser Unique (url, params) car cela génère une erreur ...).

J'ai pensé à utiliser des déclencheurs pour ce faire, mais comment lancer une exception/déclencher une erreur si le déclencheur découvre que l'insertion est sur le point d'insérer une entrée en double? J'imagine que je voudrais avoir une MySqlException levée comme MySql le fait avec des clés primaires en double, etc. afin que je puisse l'attraper dans mon code C #.

J'ai deux éléments dans le déclencheur dont j'ai besoin pour obtenir de l'aide: ... Abandonner une exception en C # ... Comment lancer une exception, etc. en C #? ... Autoriser l'insertion ... - comment autoriser l'insertion s'il n'y a pas d'entrée en double?

Voici le code de déclenchement:

CREATE TRIGGER urls_check_duplicates
BEFORE INSERT ON urls
FOR EACH ROW

BEGIN
DECLARE num_rows INTEGER;

SELECT COUNT(*)
INTO num_rows
FROM urls
WHERE url = NEW.url AND params = NEW.params;

IF num_rows > 0 THEN
   ... ABORT/throw exception to C# ...
ELSE
   ... Allow insert ...
END
31
johnrl

Les commentaires dans la documentation mysql sur les déclencheurs suggèrent qu'il n'y a pas une telle fonctionnalité dans mysql. Le mieux que vous puissiez faire est de créer un tableau séparé pour vos erreurs de déclenchement, comme suggéré sur la même page .

8
soulmerge

Je suis tombé sur cela et bien que la solution fonctionne, je suis plus tard tombé sur ce qui me semble être une meilleure solution. Je soupçonne que ce n'était pas une option lors de la réponse à cette question.

CREATE TRIGGER `TestTable_SomeTrigger`
BEFORE UPDATE ON `test_table`
FOR EACH ROW
BEGIN
    DECLARE msg VARCHAR(255);
    IF (SomeTestToFail = "FAIL!") THEN
        set msg = "DIE: You broke the rules... I will now Smite you, hold still...";
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
    END IF;

    -- Do any other code here you may want to occur if it's all OK or leave blank it will be
    --  skipped if the above if is true
END$$

Cela renverra maintenant un message d'erreur Nice (ou diabolique!) Que vous pouvez intercepter. Pour plus d'informations à ce sujet, voir: http://dev.mysql.com/doc/refman/5.5/en/signal.html

J'espère que ça aidera quelqu'un d'autre!

70
GazB

Si votre définition de table est pour une valeur NOT NULL, vous pouvez définir NEW sur NULL, ce qui ne ferait pas l'insertion. Vous devrez peut-être activer le mode SQL strict pour que cela fonctionne correctement.

6
g33kz0r