2010-01-13 1 views
5

J'essaie d'insérer une seule ligne qui n'existe pas déjà ou n'existe pas. Je voudrais éviter de le sélectionner en premier et/ou d'obtenir un -803 s'il existe. J'ai fait des recherches et j'ai essayé d'ignorer et de fusionner les instructions, mais je continue d'obtenir des erreurs de syntaxe sur les deux. Dans tous les cas, je n'essaie pas de copier les données d'une autre table - ainsi, la fusion n'est pas vraiment appropriée.
DB2 SQL n'a-t-il pas un moyen d'émettre un encart à l'épreuve des pannes et de ne pas avoir à coder autour de cela? En d'autres termes, existe-t-il une syntaxe d'insertion qui garantit que les données seront ajoutées si elles n'existent pas ou retourneront un état zéro même si c'est le cas?Essayer d'éviter l'insertion -803 dans DB2

Répondre

2

En bref, la réponse est non. En définitive, tout dépend des contraintes que vous avez établies sur votre table. Si vous essayez d'exécuter une insertion sur une table qui a une contrainte unique sur une colonne et que les données existent déjà que vous essayez d'insérer, vous obtiendrez une erreur dans DB2 (et tout autre SGBDR).

Dans ce cas, la meilleure option est probablement d'écrire une procédure stockée qui vérifie si l'enregistrement existe déjà avant de le créer.

+2

Mieux encore: Ne perdez pas de temps à vérifier l'existence, demandez à la procédure stockée de faire l'insertion, et il suffit de gérer l'erreur -803 (SQL0803N). Encore mieux: demandez à l'application de vérifier le code de retour de l'insertion et de gérer l'erreur -803. –

+0

Merci pour la réponse rapide. J'espérais que DB2 avait un équivalent au paramètre "ignore", mais pas de chance. Mike –

+0

J'ai essayé de gérer le -803 et de faire une mise à jour, mais cela laisse une trace de pile dans le journal même lorsque le processus global est réussi, ce qui amène les autres à poser des questions.Donc, je change le code pour faire une vérification d'existence en premier. Merci pour toutes les suggestions. –

7

MERGE est est approprié, car vous pouvez fournir dynamiquement des valeurs dans la clause USING (voir l'exemple 5 dans http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm).

Mais MERGE est une fonctionnalité DB2 V8.2! Vous êtes probablement sur V8.1, n'est-ce pas?

Si vous implémentez la vérification de l'existence comme ceci:

SELECT 
if (found) UPDATE else INSERT 

méfiez-vous des problèmes de concurrence: Deux threads simultanés peuvent à la fois trouver aucune colonne, puis les deux essayer d'insérer, même s'il y a une transaction autour du code ci-dessus. Pour vous assurer que cela ne se produira pas, vous devez acquérir un verrou de mise à jour avec Lecture répétée dans l'instruction SELECT ci-dessus en utilisant WITH RR USE AND KEEP UPDATE LOCKS.

+0

Les problèmes de concurrence sont-ils toujours un problème si vous faites un INSERT, attrapez le '-803', puis faites le' UPDATE'? –

2

Vous pouvez faire l'instruction de mise à jour, si cela renvoie 0 résultats mis à jour, puis faites l'instruction d'insertion.

2

Vous pouvez le faire à l'aide de la table sysibm.sysdummy (ou mieux nommée dual à partir d'Oracle ou de versions ultérieures de DB2). Cela fonctionnera très bien dans le cas où vous voulez insérer une ligne qui n'existe pas mais retourner 0 si elle existe. AFAIK, vous ne pouvez pas mettre à jour une ligne en utilisant cette méthode, vous aurez besoin d'utiliser la fusion pour cela.

Pour ce faire, vous aurez besoin d'une clé primaire ou unique sur votre table. Vous insérez dans la table, en sélectionnant toutes vos valeurs à partir du dual dans le processus où une ligne n'existe pas dans votre table correspondant à votre index principal ou unique.

insert into table (column1, column2, column3, column4, column5) 
select 'A', 'B', 'C', 'D', 'E' from dual where not exists (select * from table where column1 = 'A'); 

J'ai trouvé cela très utile pour les cas où j'ai plusieurs processus à une table insertion et je ne peux pas garantir l'ordre de ces inserts. Vous pouvez détecter si l'insertion a été réussie ou non par la valeur de retour, qui sera 1 si elle a réussi ou 0 sinon