OVH Cloud OVH Cloud

insert conditionnel

27 réponses
Avatar
Etienne SOBOLE
c'est possible de faire un insert dans une table sous condition?

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée n'existe
pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée n'existe pas
deja !!!

merci
Etienne

10 réponses

1 2 3
Avatar
\(¯`·..Yttrium ...·´¯\)
"Etienne SOBOLE" a écrit dans le message de news:
429f0c34$0$4069$
c'est possible de faire un insert dans une table sous condition?

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée n'existe
pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée n'existe


pas
deja !!!



Bonjour,

Solution 1 : Faire la vérification prélablement avec le langage que tu
utilises, si c'est possible (je ne connais pas l'environnement dans lequel
tu bosses)
Solution 2 : Mettre un index unique sur le champ lien, si un meme
enregistrement existe déjà, tu aura un erreur 1062, (si tu es sous MySql),
et l'enregistrement ne pourra pas
avoir lieu.

Pour ajouter la condition en SQL je crains qu'il ne faille passer par un
trigger ou autre chose de la sorte, mais cela sans certitude aucune.
A confirmer donc
Avatar
Etienne SOBOLE
Solution 1 : Faire la vérification prélablement avec le langage que tu
utilises, si c'est possible (je ne connais pas l'environnement dans lequel
tu bosses)



hum.
c'est ce que je fais actuellement.

Solution 2 : Mettre un index unique sur le champ lien, si un meme
enregistrement existe déjà, tu aura un erreur 1062, (si tu es sous MySql),
et l'enregistrement ne pourra pas
avoir lieu.



oui en passant par une transaction on peux aussi s'en sortir, mais j'aurai
autant que possible souhaité éviter de baser ma solution sur un message
d'erreur

Pour ajouter la condition en SQL je crains qu'il ne faille passer par un
trigger ou autre chose de la sorte, mais cela sans certitude aucune.
A confirmer donc



Ouai le tigger ca marche, mais c'est trop dépendant du SGBD ;)

Merci en tout cas.
Avatar
Daniel
Bonjour,

"Etienne SOBOLE" writes:

c'est possible de faire un insert dans une table sous condition?



sous mysql tu as la commande insert.... on duplicate key qui le fait

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée n'exis te
pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée n'e xiste pas
deja !!!



ci joint copie de l'aide

Si vous spécifiez la clause ON DUPLICATE KEY UPDATE (nouveau en MySQL
4.1.0), et qu'une ligne insérée engendre un doublon pour une clé
PRIMARY ou UNIQUE, une commande UPDATE sera faite à la place de
l'insertion. Par exemple, les commandes ont le même effet :
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=c+1;
mysql> UPDATE table SET c=c+1 WHERE a=1;


--
suivre ce lien pour répondre:
http://cerbermail.com/?2KrV3YZXnn
Daniel
;-)
Avatar
Hugues
Etienne SOBOLE a écrit :
c'est possible de faire un insert dans une table sous condition?

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée n'existe
pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée n'existe pas
deja !!!

merci
Etienne





Perso, en Oracle, je fais rarement des vérifications de ce genre de
chose avant de faire l'insert.
Je met plutot un index unique qui va générer une exception la societe
est deja la.
Si c'est du pro*c derriere, j'oubli de verifier le code retour de la requete
Si c'est du pl/sql ou un langage style powerbuilder, je traite
l'exception, avec un truc du style

begin
insert...
exception
when unique_index_violation (j'ai oublié le vrai nom de l'exception)
then null;
end;


D'un point de vu PERFORMANCE, ça n'a rien a voir.

si tu verifie puis insert sans index sur le contact, Oracle va faire :
PARSE / EXECUTE / FETCH pour la verification
PARSE / EXECUTE pour l'insert
sans compter que le select de verif va necessiter l'utilisation d'un
index... Si y a rien d'unique, ça pu

si tu as l'index unique, Oracle va faire :
PARSE / EXECUTE
Dans le parse, le plan d'exec sera plus performant du fait de la
presence de l'index
Dans le execute, il ira egalement bcp plus vite car tous les traitements
fait au niveau du noyau sont plus performant. Il vaut mieux que ce soit
le noyau qui decide de faire un requete plutot que le programmeur dans
son langage evolué.

Pour les anglophones, tout ça est expliqué en détail dans les docs de
tuning d'oracle. Mais c'est un peu comme quand on programme en ada,
c'est plus rapide d'utiliser les exceptions que de faire tous les tests
à la main. En plus, le code est plus lisible.
Avatar
Hugues
Etienne SOBOLE a écrit :
Solution 1 : Faire la vérification prélablement avec le langage que tu
utilises, si c'est possible (je ne connais pas l'environnement dans lequel
tu bosses)




hum.
c'est ce que je fais actuellement.


Solution 2 : Mettre un index unique sur le champ lien, si un meme
enregistrement existe déjà, tu aura un erreur 1062, (si tu es sous MySql),
et l'enregistrement ne pourra pas
avoir lieu.




oui en passant par une transaction on peux aussi s'en sortir, mais j'aurai
autant que possible souhaité éviter de baser ma solution sur un message
d'erreur


Pour ajouter la condition en SQL je crains qu'il ne faille passer par un
trigger ou autre chose de la sorte, mais cela sans certitude aucune.
A confirmer donc




Ouai le tigger ca marche, mais c'est trop dépendant du SGBD ;)




Et surtout, il faut eviter au max les triggers. D'un point de vu perf,
c'est la cata. Ca va aider pour ton point algorithme, mais ça va
ralentir tous les autres insert dans cette table.

Merci en tout cas.


Avatar
Fred Brouard - SQLpro
Dans mon nouveau bouquin :

http://www.pearsoneducation.fr/espace/livre.asp?idEspaceu&idLivre#10&dep=0
http://www.amazon.fr/exec/obidos/ASIN/2744070955/


je donne cet exercice là :


Exercice 10
Enoncé :
Soit la table T_TEST (COL1 INT, COL2 CHAR(4)), contenant les données suivantes :
COL1 COL2
------ ------
1 NORD
3 SUD
Ecrivez une requête permettant d'insérer une ligne si cette ligne n'existe pas
déjà dans la table.

Solution :
Le principe est de faire un INSERT avec une sous requête. La sous requête compte
le nombre de ligne qui comporte les mêmes données que celle à insérer. Si le
nombre de ligne contenant les mêmes données est supérieur à zéro, alors la ligne
existe déjà. Dans ce cas, il convient que la sous requête ne retourne rien :
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD'
HAVING COUNT(*) < 1
Ainsi le tuple ne sera inséré que si les données n'existe pas.

Pour certains SGBDR, on peut utiliser le NOT EXIST qui sera sans doute plus
optimisé :
Solution pour Oracle
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM DUAL
WHERE NOT EXISTS (SELECT *
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD')
Oracle utilise une pseudo table de nom DUAL qui sert à remplir la clause FROM
sans préciser un objet réellement existant (table ou vue).
Solution pour MS SQL Server :
INSERT INTO T_TEST
SELECT 1, 'NORD'
WHERE NOT EXISTS (SELECT *
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD')
L'écriture pour SQL Server est encore plus sobre, car ce SGBDR ne requiert pas
obligatoirement de clause FROM pour exécuter une telle requête.


A toi de t'en inspirer !

A +

Etienne SOBOLE a écrit:
c'est possible de faire un insert dans une table sous condition?

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée n'existe
pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée n'existe pas
deja !!!

merci
Etienne





--
Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
************************ www.datasapiens.com *************************
Avatar
Hugues
Fred Brouard - SQLpro a écrit :
Dans mon nouveau bouquin :

http://www.pearsoneducation.fr/espace/livre.asp?idEspaceu&idLivre#10&dep=0

http://www.amazon.fr/exec/obidos/ASIN/2744070955/


je donne cet exercice là :


Exercice 10
Enoncé :
Soit la table T_TEST (COL1 INT, COL2 CHAR(4)), contenant les données
suivantes :
COL1 COL2
------ ------
1 NORD
3 SUD
Ecrivez une requête permettant d'insérer une ligne si cette ligne
n'existe pas déjà dans la table.

Solution :
Le principe est de faire un INSERT avec une sous requête. La sous
requête compte le nombre de ligne qui comporte les mêmes données que
celle à insérer. Si le nombre de ligne contenant les mêmes données est
supérieur à zéro, alors la ligne existe déjà. Dans ce cas, il convient
que la sous requête ne retourne rien :
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD'
HAVING COUNT(*) < 1
Ainsi le tuple ne sera inséré que si les données n'existe pas.

Pour certains SGBDR, on peut utiliser le NOT EXIST qui sera sans doute
plus optimisé :
Solution pour Oracle
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM DUAL
WHERE NOT EXISTS (SELECT *
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD')



l'index unique est plus performant.
Avec certaines versions d'oracle (je n'ai pas encore testé la 10g), il
est plus performant d'ajouter un test sur le rownum
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM DUAL
WHERE NOT EXISTS (SELECT *
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD'
AND ROWNUM < 1)

ce qui permet de ne retourner que la premiere ligne dans le sous select.
J'avais vu une différence sur des gros traitements batchs (plan
d'execution avec un STOP dedans)

Dans tous les cas, je suis persuadé que l'index unique sera plus
performant. Ou encore mieux une contrainte d'intégrité unique.

Oracle utilise une pseudo table de nom DUAL qui sert à remplir la clause
FROM sans préciser un objet réellement existant (table ou vue).
Solution pour MS SQL Server :
INSERT INTO T_TEST
SELECT 1, 'NORD'
WHERE NOT EXISTS (SELECT *
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD')
L'écriture pour SQL Server est encore plus sobre, car ce SGBDR ne
requiert pas obligatoirement de clause FROM pour exécuter une telle
requête.


A toi de t'en inspirer !

A +

Etienne SOBOLE a écrit:

c'est possible de faire un insert dans une table sous condition?

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée
n'existe pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée
n'existe pas deja !!!

merci
Etienne




Avatar
Etienne SOBOLE
Soit la table T_TEST (COL1 INT, COL2 CHAR(4)), contenant les données
suivantes :
COL1 COL2
------ ------
1 NORD
3 SUD
Ecrivez une requête permettant d'insérer une ligne si cette ligne n'existe
pas déjà dans la table.

Solution :
Le principe est de faire un INSERT avec une sous requête. La sous requête
compte le nombre de ligne qui comporte les mêmes données que celle à
insérer. Si le nombre de ligne contenant les mêmes données est supérieur à
zéro, alors la ligne existe déjà. Dans ce cas, il convient que la sous
requête ne retourne rien :
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD'
HAVING COUNT(*) < 1
Ainsi le tuple ne sera inséré que si les données n'existe pas.



Super!
Ca marche nickel.

merci
Etienne
Avatar
Etienne SOBOLE
Avec certaines versions d'oracle (je n'ai pas encore testé la 10g), il est
plus performant d'ajouter un test sur le rownum
INSERT INTO T_TEST
SELECT 1, 'NORD'
FROM DUAL
WHERE NOT EXISTS (SELECT *
FROM T_TEST
WHERE COL1 = 1
AND COL2 = 'NORD'
AND ROWNUM < 1)



oui mais tout le monde n'est pas sous oracle ;)
Avatar
Fred Brouard - SQLpro
Sachez aussi que la norme SQL à défini dans sa version SQL:2003 la combinaison
de l'INSERT et l'UPDATE.

Voici ce que j'en dis dans mon bouquin :
"
6.4 insertion ou modification avec MERGE

L'ordre MERGE introduit par SQL:2003, n'est pas à proprement parlé un ordre à
lui tout seul, mais la combinaison d'un ordre INSERT et d'un UPDATE suivant que
les données correspondent a tel ou tel critère.

Sa syntaxe est la suivante :

MERGE INTO <table_cible> [ [ AS ] <nom_corrélation_cible> ]
USING <requête_reference> [ [ AS ] <nom_corrélation_requête> ]
ON <prédicat>
WHEN MATCHED THEN <requête_merge_update>
WHEN NOT MATCHED THEN <requête_merge_insert> }

Si le prédicate est vrai, alors les lignes alimente la requête de modification
(UPDATE). Dans le cas contraire (FALSE ou UNKNOWN) les lignes sont insérées. Les
requêtes <requête_merge_update> et <requête_merge_insert> ne doivent pas
spécifier la table puisque c'est la table cible qui est impactée dans tous les cas.

Exemple :
MERGE INTO T_UTILISATEUR_USR USR
USING (SELECT USR_ID,
USR_ID + (SELECT MAX(USR_ID)
FROM T_UTILISATEUR_USR) AS NEW_USR_ID,
USR_NOM, USR_PRENOM, USR_TITRE,
USR_MAIL, USR_ORGANISATION
FROM T_UTILISATEUR_USR) AS USS
ON USR.USR_NOM = USS.USR_NOM
AND USR.USR_ID <> USS.USR_ID
WHEN MATCHED THEN
UPDATE
SET USR_NOM = lower(USR_NOM),
USR_PRENOM = lower(USR_PRENOM)
WHEN NOT MATCHED THEN
INSERT (USR_ID, USR_NOM,
USR_PRENOM, USR_TITRE,
USR_MAIL, USR_ORGANISATION)
VALUES (USS.NEW_USR_ID,
UPPER(USS.USR_NOM),
UPPER(USS.USR_PRENOM), DEFAULT,
USS.USR_MAIL, 'BORLAND')
Dans cet exemple on compare les utilisateurs entre eux : s'il sont homonyme
(même nom, mais pas même identifiant) alors une mise à jour intervient et noms
et prénoms sont mis en minuscule. Dans le cas contraire il y a insertion, avec
nom et prénom en majuscule et la valeur BORLAND comme organisation. Le calcul du
nouvel identifiant étant réalisée dans le premier SELECT (colonne d'alias
NEW_USR_ID).
"

Dans ton cas tu pourrais faire juste un WHEN NOT MATCHED...

A +

Etienne SOBOLE a écrit:
c'est possible de faire un insert dans une table sous condition?

j'ai un table qui relie un contact a une société
et je voudrai faire l'insertion dans cette table que si l'entrée n'existe
pas deja !

genre
INSERT INTO lien WHERE idsoc = 5 AND idctc = 9 .... if l'entrée n'existe pas
deja !!!

merci
Etienne





--
Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
************************ www.datasapiens.com *************************
1 2 3