Conflit Trigger on Insert et Procédure
SQL AnyWhere 10
J'ai besoin d'une SEQUENCE, semble que cela n'existe pas en version 10.
J'ai donc fait une fonction qui va me trouver le Premier Numéro disponible (il y a une volonté de recycler les numéros supprimés), c'est un peu différent d'une SEQUENCE, je l'avoue !
Code la fonction
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| DROP FUNCTION GetCensureNumberSequenceNextValue;
CREATE FUNCTION GetCensureNumberSequenceNextValue (
@TableName sysname,
@SequenceFieldName sysname
)
RETURNS INTEGER
NOT DETERMINISTIC
BEGIN
DECLARE @cpt INTEGER;
DECLARE @found INTEGER;
DECLARE @newid INTEGER;
DECLARE @count INTEGER;
SET @newid = 0;
SET @found = 0;
SET @cpt = 1;
EXECUTE IMMEDIATE
'SELECT COUNT(*) INTO @count FROM '||@TableName;
WHILE @cpt <= @count AND @newid = 0 LOOP
SET @found = 0;
EXECUTE IMMEDIATE
'SELECT 1 INTO @found FROM '||@TableName||' WHERE '||@SequenceFieldName||' = @cpt';
IF @found = 0 THEN
SET @newid = @cpt
ELSE
SET @newid = 0
END IF;
SET @cpt = @cpt + 1;
END LOOP;
IF @newid = 0 THEN
SET @newid = @cpt;
END IF;
RETURN @newid;
END; |
je l'ai testé via
Code:
1 2
| INSERT INTO Machin(NumeroBidule, NomMachin)
VALUES (GetCensureNumberSequenceNextValue ('Machin', 'NumeroBidule'), 'BOB') |
C'est parfait, j'ai bien un NumeroBidule avec les valeurs que j'attendais, cela bouche les trous puis cela incrémente naturellement par la suite !
D'un point de vue performance, pas de soucis, la table restera très petite et des insertions très ponctuelles !
A savoir qu'un code similaire existe dans l'application que je maintiens mais coder directement en C++ Builder (il y a autant de fois le code dupliqué qu'il doit exister de Séquence, oui c'est vilain), je voudrais uniformiser et l'intégrer directement à la Base de données
au départ mon but était de l'intégrer à un Trigger comme ceci
Code:
1 2 3 4 5 6 7 8 9 10
| DROP TRIGGER InsertMachinNumeroBidule;
CREATE TRIGGER InsertMachinNumeroBidule
AFTER INSERT ON Machin
REFERENCING NEW AS NewNumeroBidule
FOR EACH ROW
BEGIN
IF NewNumeroBidule.NumeroBidule IS NULL THEN
SELECT GetCensureNumberSequenceNextValue('Machin', 'NumeroBidule') INTO NewNumeroBidule.NumeroBidule
END IF;
END; |
Mais c'est la que les choses se gatent !
Citation:
Erreur ! Impossible d'insérer la ligne.
COMMIT/ROLLBACK n'est pas autorisé dans l'opération atomique
[Sybase][ODBC Driver][SQL Anywhere]COMMIT/ROLLBACK n'est pas autorisé dans l'opération atomique
SQLCODE: -267
SQLSTATE: 42000
Faut-il utiliser un CURSOR et mettre le code de la fonction directement dans le TRIGGER, du coup, je n'ai plus un code uniformiser et donc retour à un code dupliqué (autant le laisser en C++)
Puis-je quand même utiliser une fonction et du SQL dynamique ?
Je n'ai pas bien compris comment récupérer le CURSOR d'un EXECUTE, j'ai trouvé un code Sybase V15 ou SQL Server 2008 qui ne fonctionne pas sous la version AnyWhere 10 !