SQL2b.LMD - Les modifications avancées

SIO > S1_Commun > S1C8_Donnees > sql2b_lmd2_avance.md

?>

Aller plus loin : INSERT INTO SELECT, UPDATE avec jointure, etc...

INSERT INTO spéciaux

Insérer dans une table en utilisant le résultat d'une requête, c'est possible ...
			<h3>Simple et efficace pour faire des copies de tables ou des extractions</h3>

On va utiliser le résultat d'une requête pour insérer de nouveaux enregistrements dans une table existante.

[sql]
				<ul>
 - INSERT INTO uneTable **SELECT  une_requete** ;</li>
				</ul>
			</div>
Attention, les champs issus de la requête doivent correspondre aux champs de la table ou, du moins, à ceux indiqués derrière **INSERT INTO uneTable**.  
Voir aussi ce lien vers <a href="http://www.w3schools.com/sql/sql_insert_into_select.asp">w3Schools::insert into select</a>  
			<h3>Mieux, utilisons SELECT ... INTO ... FROM  !!!</h3>
Attention les yeux!! Si vous n'êtes pas prêt, ne lisez pas la suite, votre cerveau pourrait s'embrouiller.  
<sql>
				<ul>
 - SELECT [liste de champs ou *] 
						<ul>
		 - **INTO nouvelleTable**</li>
		 - FROM [liste de tables]</li>
		 - [suite normale de la requete SELECT]</li>
						</ul>
					;</li>
				</ul>
			</div>
La table **nouvelleTable** est créée à cette occasion contrairement à **INSERT INTO** où la table doit déjà exister.  
Voir aussi ce lien vers <a href="http://www.w3schools.com/sql/sql_select_into.asp">w3Schools::select into</a> (c'est pas le même)  
		</div>
		<p><a href="#top">Top of page</a>  
 
===== Update de fous ===== 
<abstract>Ou comment mettre à jour une table avec une contrainte sur une seconde table</abstract>
			<h3>1) Imagine ...</h3>
On voudrait faire une surprise au client 'Timken' et augmenter la quantité de tous ses articles de 1% pour toutes ses commandes du joli mois de mai de cette année ...
				<br>Comment faire ? La date ni le nom du client ne sont mentionnés dans la table contenir qui est à modifier !!!<p>
Alors ??? hummm?? pourtant on n'a pas le droit de mettre plusieurs tables derrière UPDATE, n'est ce pas?.<p>
Eh bien voilà la solution! : on utilise des jointures avec JOIN et le tour est joué<br>Oh! la belle requête ...<p>
<sql>
				<ul>
 - UPDATE Contenir
						<ul>
		 - **JOIN Commande ON Contenir.numCde=Commande.numCde**</li>
		 - **JOIN Client ON Client.id=idClient**</li>
		 - SET qty=qty*1.01</li>
		 - WHERE YEAR(dateCde)=YEAR(CURDATE()) AND MONTH(dateCde)=05 AND nomCli='Timken'</li>
						</ul>
					;</li>
				</ul>
			</div>
Remarquer en passant l'usage des fonctions YEAR(), MONTH() et CURDATE(), c'est mieux qu'un between tordu.<p>
 
			<h3>2) Autre (mauvaise) surprise pour les clients</h3>
Comment augmenter de 3% le prix des 10 articles les plus commandés ?
				<br>(re)Oh! la (re)belle requête ... encore plus sioux et compliquée à souhait qu'avant.<p>
			<div class="code codeBg">
				<ul>
 - UPDATE Article
						<ul>
		 - JOIN
								<ul>
			 - (
									<ul>
					 - SELECT refArt, sum(qty) FROM Contenir</li>
					 - GROUP BY refArt </li>
					 - ORDER BY sum(qty) DESC </li>
					 - LIMIT 0, 10</li>
									</ul>
									) **meilleureVente**</li>
			 - ON **meilleureVente**.refArt=Article.refArt</li>
								</ul>
		 - SET prixHTArt=prixHTArt*1.03</li>
						</ul>
					;</li>
				</ul>
			</div>
Remarquer en passant la sous requête utilisée comme une table et renommée en **meilleureVente** ; LIMIT permet de n'avoir que les 10 premières lignes<p>
 
			<h3>3) Dernier cas <span style="font-size:.7em">(après on va prendre un truc pour la tête)</span></h3>
Et si je veux modifier le champ chTA d'une table TA avec le contenu du champ chTB d'une autre table TB ?
				<br>On admettra que les deux tables sont jointes par les champs clés (primaires ou secondaires) cjTA et cjTB.<p>
<sql>
UPDATE TA
 JOIN TB ON cjTB = cjTA
 SET **chTA=chTB**
;

Vous suivez ?

 
			<h3>4) Tiens ? non, encore un exemple <span style="font-size:.7em">(on est mûr pour le mur)</span></h3>

Admettons qu'il y ai un champ totalHT dans la commande, comment mettre ce champ à jour avec la somme des montants des articles?

				<br>TADAAAAA .... voilà la réponse (c'est pas minion, ça ?).<p>

				<ul>

  • UPDATE Commande

						<ul>
		 - JOIN (
								<ul>
				 - SELECT cdeNum, sum(qty*prixHTArt) AS montant </li>
				 - FROM Contenir JOIN Article ON Contenir.refAret=Article.refArt </li>
				 - GROUP BY cdeNum </li>
								</ul>
							) montants ON montants.cdeNum=Commande.cdeNum</li>
		 - SET **Commande.totalHT=montants.montant**</li>
						</ul>
					;</li>
				</ul>
			</div>

Y a quelqu'un ?    Ah? non !    Ils sont tous morts. ... dommage, je m'amusais bien, pourtant.

			<br><span style="font-size:.7em">La prochaine fois, je le fais en alsacien ou en breton, ou en corse. 
				<span style="font-size:.7em">yess&nbsp;&nbsp;&nbsp;
				<span style="font-size:.7em">je suis le roi de la jointure</span></span></span><p>
		</div>
		<p><a href="#top">Top of page</a>  
 

Conclusion

Je vais m'arrêter là car si je continue, on en aura pour l'année. Plus j'approfondi le sujet, plus je découvre des trucs.
Rappel de sites de tutos et références sur le SQL : MySQL ou w3schools et bien d'autres encore.