<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le Blog SQL Server d&#039;ElSüket &#187; Snippets</title>
	<atom:link href="https://blog.developpez.com/elsuket/pcategory/snippets/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/elsuket</link>
	<description>Nicolas Souquet - Expert SQL Server</description>
	<lastBuildDate>Mon, 05 Apr 2021 07:32:41 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Redémarrer la trace par défaut</title>
		<link>https://blog.developpez.com/elsuket/p13143/snippets/redemarrer-la-trace-par-defaut</link>
		<comments>https://blog.developpez.com/elsuket/p13143/snippets/redemarrer-la-trace-par-defaut#comments</comments>
		<pubDate>Thu, 02 Mar 2017 08:00:02 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Utilitaires]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=1377</guid>
		<description><![CDATA[SQL Server fournit de nombreux outils de monitoring d&#8217;arrière-plan par défaut, comme le journal SQL Server, la session d&#8217;événements étendus system_health, mais aussi une trace SQL Profiler. Cette dernière est enregistrée dans un fichier dans le répertoire des journaux, et &#8230; <a href="https://blog.developpez.com/elsuket/p13143/snippets/redemarrer-la-trace-par-defaut">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>SQL Server fournit de nombreux outils de monitoring d&rsquo;arrière-plan par défaut, comme le journal SQL Server, la session d&rsquo;événements étendus <em>system_health</em>, mais aussi une trace <em>SQL Profiler</em>. Cette dernière est enregistrée dans un fichier dans le répertoire des journaux, et SQL Server conserve 6 fichiers de cette trace.</p>
<p>Elle capture, entre autres, les événements d&rsquo;échec d&rsquo;authentification, la création d&rsquo;objets dans TempDB, les warnings sur Hash et Sort, les grossissements de fichiers, et de nombreux autres événements. Ceux-ci peuvent aider à comprendre, a posteriori, ce qui a causé une grande consommation de CPU, des latences disque, &#8230;</p>
<p>Comme cette trace est écrite sur disque, il peut malencontreusement arriver que ce dernier devienne plein, provoquant alors l&rsquo;arrêt automatique et forcé de la trace. Ce léger incident (l&rsquo;arrêt de la trace, pas l&rsquo;absence d&rsquo;espace disque libre !) n&rsquo;empêche aucunement l&rsquo;instance de fonctionner, ou au moins d&rsquo;être accessible. Cependant, comment peut-on redémarrer cette trace sans redémarrer l&rsquo;instance SQL Server ?</p>
<p><span id="more-1377"></span></p>
<p>En effet, la documentation nous indique que la trace par défaut n&rsquo;est démarrée que lorsque l&rsquo;instance démarre aussi &#8230; nous allons voir que c&rsquo;est incomplet. Une fois le disque supportant la trace disposant à nouveau d&rsquo;espace disque libre, on constate que la trace par défaut est arrêtée à l&rsquo;aide de l&rsquo;instruction suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">traces</span></div></td></tr></tbody></table></div>
<p>Lorsque la trace par défaut est active, cette requête retourne une ligne, dont la colonne <em>id</em> est à 1. On peut vérifier que c&rsquo;est la trace par défaut à l&rsquo;aide de la valeur de la colonne <em>is_default</em> : 1 si c&rsquo;est le cas, 0 à l&rsquo;inverse :</p>
<p><img src="http://i.imgur.com/msPoxLS.png" alt="" /></p>
<p>Dans la situation de l&rsquo;incident que nous évoquons, cette même requête ne retournera pas de ligne (ou tout du moins aucune dont la colonne <em>is_default</em> est à 1). Pour démarrer la trace par défaut, il suffit de s&rsquo;en remettre à l&rsquo;option de configuration d&rsquo;instance <em>default trace enabled</em> :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">configurations</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'%trace%'</span></div></td></tr></tbody></table></div>
<p><img src="http://i.imgur.com/swPu4gE.png" alt="" /></p>
<p>On voit que c&rsquo;est une option avancée et dynamique, ce qui signifie qu&rsquo;un redémarrage de l&rsquo;instance SQL Server n&rsquo;est pas nécessaire. Dès lors, pour réactiver la trace par défaut, il suffit de positionner cette option à 0, puis immédiatement ensuite à 1, ce qui est sa valeur par défaut :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Activation de la modification des options d'instance avancées</span><br />
<span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'show advanced options'</span>, <span style="color: #000;">1</span><br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO<br />
<br />
<span style="color: #008080;">-- Désactivation de la trace par défaut</span><br />
<span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'default trace enabled'</span>, <span style="color: #000;">0</span><br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO<br />
<br />
<span style="color: #008080;">-- Ré-activation de la trace par défaut</span><br />
<span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'default trace enabled'</span>, <span style="color: #000;">1</span><br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO<br />
<br />
<span style="color: #008080;">-- Désactivation de la modification des options d'instance avancées</span><br />
<span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'show advanced options'</span>, <span style="color: #000;">0</span><br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO</div></td></tr></tbody></table></div>
<p>Sur exécution de ce lot, l&rsquo;onglet <em>Messages</em> du panneau de résultats de <em>SQL Server Management Studio</em> affiche :</p>
<p><em>Configuration option &lsquo;show advanced options&rsquo; changed from 0 to 1. Run the RECONFIGURE statement to install.<br />
Configuration option &lsquo;default trace enabled&rsquo; changed from 1 to 0. Run the RECONFIGURE statement to install.<br />
Configuration option &lsquo;default trace enabled&rsquo; changed from 0 to 1. Run the RECONFIGURE statement to install.<br />
Configuration option &lsquo;show advanced options&rsquo; changed from 1 to 0. Run the RECONFIGURE statement to install.</em></p>
<p>Et l&rsquo;on voit alors que la trace a été démarrée, en interrogeant une nouvelle fois la vue <em>sys.traces</em>.<br />
On trouvera aussi dans les journal de SQL Server les lignes suivantes :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Recherche de l'heure de dernier démarrage de l'instance SQL Server</span><br />
<span style="color: #0000FF;">SELECT</span> sqlserver_start_time <span style="color: #0000FF;">FROM</span> sys.<span style="color: #202020;">dm_os_sys_info</span><br />
<br />
<span style="color: #008080;">-- Recherche du démarrage de la trace par défaut</span><br />
<span style="color: #0000FF;">EXEC</span> xp_readerrorlog <span style="color: #000;">0</span>, <span style="color: #000;">1</span>, N<span style="color: #FF0000;">'Trace ID 1'</span></div></td></tr></tbody></table></div>
<p><img src="http://i.imgur.com/e2rFeEt.png" alt="" /></p>
<p>Ici on voit bien que la trace par défaut a été démarré par le système (le SPID est inférieur à 50), quelques millisecondes après le démarrage de celui-ci. Elle a ensuite été redémarrée par nos soins un peu plus tard.</p>
<p>Petite note finale : les fonctionnalités <em>SQL Trace</em> et <em>SQL Profiler</em> sont obsolètes, et remplacées par la fonctionnalité d&#039;<a href="http://blog.developpez.com/elsuket/p11065/moteur-de-base-de-donnees-sql-server/evenements_etendus_sql_server_2008" title="Les Événements Étendus avec SQL Server 2008" target="_blank">événements étendus</a>, plus puissante et performante. Vous pouvez voir comment les utiliser dans <a href="http://blog.developpez.com/elsuket/p13085/moteur-de-base-de-donnees-sql-server/evenements-etendus/troubleshooting-avec-les-evenements-etendus-en-video" title="Troubleshooting avec les événements étendus en vidéo" target="_blank">cette vidéo</a>, en gardant bien à l&rsquo;esprit que dès SQL Server 2012, une interface graphique intégrée à <em>SQL Server Management Studio</em> permet de créer une session sans écrire de code, et de visualiser les événements capturés à la façon de ce que permet SQL Profiler.</p>
<p>Enfin, pour interroger un fichier de trace SQL Profiler, il suffit d&rsquo;utiliser la fonction <a href="https://msdn.microsoft.com/en-us/library/ms188425.aspx"><em>sys.fn_trace_gettable()</em></a>. Donc pour en faire l&rsquo;analyse, on peut utiliser le lot suivant :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br />134<br />135<br />136<br />137<br />138<br />139<br />140<br />141<br />142<br />143<br />144<br />145<br />146<br />147<br />148<br />149<br />150<br />151<br />152<br />153<br />154<br />155<br />156<br />157<br />158<br />159<br />160<br />161<br />162<br />163<br />164<br />165<br />166<br />167<br />168<br />169<br />170<br />171<br />172<br />173<br />174<br />175<br />176<br />177<br />178<br />179<br />180<br />181<br />182<br />183<br />184<br />185<br />186<br />187<br />188<br />189<br />190<br />191<br />192<br />193<br />194<br />195<br />196<br />197<br />198<br />199<br />200<br />201<br />202<br />203<br />204<br />205<br />206<br />207<br />208<br />209<br />210<br />211<br />212<br />213<br />214<br />215<br />216<br />217<br />218<br />219<br />220<br />221<br />222<br />223<br />224<br />225<br />226<br />227<br />228<br />229<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">DECLARE</span> @events <span style="color: #0000FF;">TABLE</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; event_id <span style="color: #0000FF;">tinyint</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , event_name sysname<br />
<span style="color: #808080;">&#41;</span><br />
<br />
<span style="color: #0000FF;">INSERT</span> @events <span style="color: #0000FF;">VALUES</span> <span style="color: #808080;">&#40;</span><span style="color: #000;">0</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">1</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">2</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">3</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">4</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">5</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">6</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">7</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">8</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">9</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">10</span>, <span style="color: #FF0000;">'RPC:Completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">11</span>, <span style="color: #FF0000;">'RPC:Starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">12</span>, <span style="color: #FF0000;">'SQL:BatchCompleted'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">13</span>, <span style="color: #FF0000;">'SQL:BatchStarting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">14</span>, <span style="color: #FF0000;">'Audit Login'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">15</span>, <span style="color: #FF0000;">'Audit Logout'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">16</span>, <span style="color: #FF0000;">'Attention'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">17</span>, <span style="color: #FF0000;">'ExistingConnection'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">18</span>, <span style="color: #FF0000;">'Audit Server Starts and Stops'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">19</span>, <span style="color: #FF0000;">'DTCTransaction'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">20</span>, <span style="color: #FF0000;">'Audit Login Failed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">21</span>, <span style="color: #FF0000;">'EventLog'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">22</span>, <span style="color: #FF0000;">'ErrorLog'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">23</span>, <span style="color: #FF0000;">'Lock:Released'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">24</span>, <span style="color: #FF0000;">'Lock:Acquired'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">25</span>, <span style="color: #FF0000;">'Lock:Deadlock'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">26</span>, <span style="color: #FF0000;">'Lock:Cancel'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">27</span>, <span style="color: #FF0000;">'Lock:Timeout'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">28</span>, <span style="color: #FF0000;">'Degree of Parallelism Event (7.0 Insert)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">29</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">30</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">31</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">32</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">33</span>, <span style="color: #FF0000;">'Exception'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">34</span>, <span style="color: #FF0000;">'SP:CacheMiss'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">35</span>, <span style="color: #FF0000;">'SP:CacheInsert'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">36</span>, <span style="color: #FF0000;">'SP:CacheRemove'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">37</span>, <span style="color: #FF0000;">'SP:Recompile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">38</span>, <span style="color: #FF0000;">'SP:CacheHit'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">39</span>, <span style="color: #FF0000;">'Deprecated'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">40</span>, <span style="color: #FF0000;">'SQL:StmtStarting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">41</span>, <span style="color: #FF0000;">'SQL:StmtCompleted'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">42</span>, <span style="color: #FF0000;">'SP:Starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">43</span>, <span style="color: #FF0000;">'SP:Completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">44</span>, <span style="color: #FF0000;">'SP:StmtStarting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">45</span>, <span style="color: #FF0000;">'SP:StmtCompleted'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">46</span>, <span style="color: #FF0000;">'Object:Created'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">47</span>, <span style="color: #FF0000;">'Object:Deleted'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">48</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">49</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">50</span>, <span style="color: #FF0000;">'SQL Transaction'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">51</span>, <span style="color: #FF0000;">'Scan:Started'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">52</span>, <span style="color: #FF0000;">'Scan:Stopped'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">53</span>, <span style="color: #FF0000;">'CursorOpen'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">54</span>, <span style="color: #FF0000;">'TransactionLog'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">55</span>, <span style="color: #FF0000;">'Hash Warning'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">56</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">57</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">58</span>, <span style="color: #FF0000;">'Auto Stats'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">59</span>, <span style="color: #FF0000;">'Lock:Deadlock Chain'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">60</span>, <span style="color: #FF0000;">'Lock:Escalation'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">61</span>, <span style="color: #FF0000;">'OLE DB Errors'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">62</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">63</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">64</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">65</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">66</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">67</span>, <span style="color: #FF0000;">'Execution Warnings'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">68</span>, <span style="color: #FF0000;">'Showplan Text (Unencoded)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">69</span>, <span style="color: #FF0000;">'Sort Warnings'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">70</span>, <span style="color: #FF0000;">'CursorPrepare'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">71</span>, <span style="color: #FF0000;">'Prepare SQL'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">72</span>, <span style="color: #FF0000;">'Exec Prepared SQL'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">73</span>, <span style="color: #FF0000;">'Unprepare SQL'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">74</span>, <span style="color: #FF0000;">'CursorExecute'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">75</span>, <span style="color: #FF0000;">'CursorRecompile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">76</span>, <span style="color: #FF0000;">'CursorImplicitConversion'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">77</span>, <span style="color: #FF0000;">'CursorUnprepare'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">78</span>, <span style="color: #FF0000;">'CursorClose'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">79</span>, <span style="color: #FF0000;">'Missing Column Statistics'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">80</span>, <span style="color: #FF0000;">'Missing Join Predicate'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">81</span>, <span style="color: #FF0000;">'Server Memory Change'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">82</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">83</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">84</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">85</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">86</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">87</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">88</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">89</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">90</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">91</span>, <span style="color: #FF0000;">'User Configurable (0-9)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">92</span>, <span style="color: #FF0000;">'Data File Auto Grow'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">93</span>, <span style="color: #FF0000;">'Log File Auto Grow'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">94</span>, <span style="color: #FF0000;">'Data File Auto Shrink'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">95</span>, <span style="color: #FF0000;">'Log File Auto Shrink'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">96</span>, <span style="color: #FF0000;">'Showplan Text'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">97</span>, <span style="color: #FF0000;">'Showplan All'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">98</span>, <span style="color: #FF0000;">'Showplan Statistics Profile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">99</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">100</span>, <span style="color: #FF0000;">'RPC Output Parameter'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">101</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">102</span>, <span style="color: #FF0000;">'Audit Statement GDR Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">103</span>, <span style="color: #FF0000;">'Audit Object GDR Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">104</span>, <span style="color: #FF0000;">'Audit AddLogin Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">105</span>, <span style="color: #FF0000;">'Audit Login GDR Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">106</span>, <span style="color: #FF0000;">'Audit Login Change Property Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">107</span>, <span style="color: #FF0000;">'Audit Login Change Password Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">108</span>, <span style="color: #FF0000;">'Audit Add Login to Server Role Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">109</span>, <span style="color: #FF0000;">'Audit Add DB User Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">110</span>, <span style="color: #FF0000;">'Audit Add Member to DB Role Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">111</span>, <span style="color: #FF0000;">'Audit Add Role Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">112</span>, <span style="color: #FF0000;">'Audit App Role Change Password Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">113</span>, <span style="color: #FF0000;">'Audit Statement Permission Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">114</span>, <span style="color: #FF0000;">'Audit Schema Object Access Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">115</span>, <span style="color: #FF0000;">'Audit Backup/Restore Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">116</span>, <span style="color: #FF0000;">'Audit DBCC Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">117</span>, <span style="color: #FF0000;">'Audit Change Audit Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">118</span>, <span style="color: #FF0000;">'Audit Object Derived Permission Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">119</span>, <span style="color: #FF0000;">'OLEDB Call Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">120</span>, <span style="color: #FF0000;">'OLEDB QueryInterface Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">121</span>, <span style="color: #FF0000;">'OLEDB DataRead Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">122</span>, <span style="color: #FF0000;">'Showplan XML'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">123</span>, <span style="color: #FF0000;">'SQL:FullTextQuery'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">124</span>, <span style="color: #FF0000;">'Broker:Conversation'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">125</span>, <span style="color: #FF0000;">'Deprecation Announcement'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">126</span>, <span style="color: #FF0000;">'Deprecation Final Support'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">127</span>, <span style="color: #FF0000;">'Exchange Spill Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">128</span>, <span style="color: #FF0000;">'Audit Database Management Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">129</span>, <span style="color: #FF0000;">'Audit Database Object Management Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">130</span>, <span style="color: #FF0000;">'Audit Database Principal Management Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">131</span>, <span style="color: #FF0000;">'Audit Schema Object Management Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">132</span>, <span style="color: #FF0000;">'Audit Server Principal Impersonation Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">133</span>, <span style="color: #FF0000;">'Audit Database Principal Impersonation Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">134</span>, <span style="color: #FF0000;">'Audit Server Object Take Ownership Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">135</span>, <span style="color: #FF0000;">'Audit Database Object Take Ownership Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">136</span>, <span style="color: #FF0000;">'Broker:Conversation Group'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">137</span>, <span style="color: #FF0000;">'Blocked Process Report'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">138</span>, <span style="color: #FF0000;">'Broker:Connection'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">139</span>, <span style="color: #FF0000;">'Broker:Forwarded Message Sent'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">140</span>, <span style="color: #FF0000;">'Broker:Forwarded Message Dropped'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">141</span>, <span style="color: #FF0000;">'Broker:Message Classify'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">142</span>, <span style="color: #FF0000;">'Broker:Transmission'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">143</span>, <span style="color: #FF0000;">'Broker:Queue Disabled'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">144</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">145</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">146</span>, <span style="color: #FF0000;">'Showplan XML Statistics Profile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">148</span>, <span style="color: #FF0000;">'Deadlock Graph'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">149</span>, <span style="color: #FF0000;">'Broker:Remote Message Acknowledgement'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">150</span>, <span style="color: #FF0000;">'Trace File Close'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">151</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">152</span>, <span style="color: #FF0000;">'Audit Change Database Owner'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">153</span>, <span style="color: #FF0000;">'Audit Schema Object Take Ownership Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">154</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">155</span>, <span style="color: #FF0000;">'FT:Crawl Started'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">156</span>, <span style="color: #FF0000;">'FT:Crawl Stopped'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">157</span>, <span style="color: #FF0000;">'FT:Crawl Aborted'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">158</span>, <span style="color: #FF0000;">'Audit Broker Conversation'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">159</span>, <span style="color: #FF0000;">'Audit Broker Login'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">160</span>, <span style="color: #FF0000;">'Broker:Message Undeliverable'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">161</span>, <span style="color: #FF0000;">'Broker:Corrupted Message'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">162</span>, <span style="color: #FF0000;">'User Error Message'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">163</span>, <span style="color: #FF0000;">'Broker:Activation'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">164</span>, <span style="color: #FF0000;">'Object:Altered'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">165</span>, <span style="color: #FF0000;">'Performance statistics'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">166</span>, <span style="color: #FF0000;">'SQL:StmtRecompile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">167</span>, <span style="color: #FF0000;">'Database Mirroring State Change'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">168</span>, <span style="color: #FF0000;">'Showplan XML For Query Compile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">169</span>, <span style="color: #FF0000;">'Showplan All For Query Compile'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">170</span>, <span style="color: #FF0000;">'Audit Server Scope GDR Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">171</span>, <span style="color: #FF0000;">'Audit Server Object GDR Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">172</span>, <span style="color: #FF0000;">'Audit Database Object GDR Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">173</span>, <span style="color: #FF0000;">'Audit Server Operation Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">175</span>, <span style="color: #FF0000;">'Audit Server Alter Trace Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">176</span>, <span style="color: #FF0000;">'Audit Server Object Management Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">177</span>, <span style="color: #FF0000;">'Audit Server Principal Management Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">178</span>, <span style="color: #FF0000;">'Audit Database Operation Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">180</span>, <span style="color: #FF0000;">'Audit Database Object Access Event'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">181</span>, <span style="color: #FF0000;">'TM: Begin Tran starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">182</span>, <span style="color: #FF0000;">'TM: Begin Tran completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">183</span>, <span style="color: #FF0000;">'TM: Promote Tran starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">184</span>, <span style="color: #FF0000;">'TM: Promote Tran completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">185</span>, <span style="color: #FF0000;">'TM: Commit Tran starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">186</span>, <span style="color: #FF0000;">'TM: Commit Tran completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">187</span>, <span style="color: #FF0000;">'TM: Rollback Tran starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">188</span>, <span style="color: #FF0000;">'TM: Rollback Tran completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">189</span>, <span style="color: #FF0000;">'Lock:Timeout (timeout &amp;gt; 0)'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">190</span>, <span style="color: #FF0000;">'Progress Report: Online Index Operation'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">191</span>, <span style="color: #FF0000;">'TM: Save Tran starting'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">192</span>, <span style="color: #FF0000;">'TM: Save Tran completed'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">193</span>, <span style="color: #FF0000;">'Background Job Error'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">194</span>, <span style="color: #FF0000;">'OLEDB Provider Information'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">195</span>, <span style="color: #FF0000;">'Mount Tape'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">196</span>, <span style="color: #FF0000;">'Assembly Load'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">197</span>, <span style="color: #FF0000;">'Reserved'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">198</span>, <span style="color: #FF0000;">'XQuery Static Type'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">199</span>, <span style="color: #FF0000;">'QN: subscription'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">200</span>, <span style="color: #FF0000;">'QN: parameter table'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">201</span>, <span style="color: #FF0000;">'QN: template'</span><span style="color: #808080;">&#41;</span><br />
, <span style="color: #808080;">&#40;</span><span style="color: #000;">202</span>, <span style="color: #FF0000;">'QN: dynamics'</span><span style="color: #808080;">&#41;</span><br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FTG.<span style="color: #202020;">DatabaseName</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , E.<span style="color: #202020;">event_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , FTG.<span style="color: #202020;">ApplicationName</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">COUNT</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">*</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> occurences<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">MIN</span><span style="color: #808080;">&#40;</span>FTG.<span style="color: #202020;">StartTime</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> first_time<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">MAX</span><span style="color: #808080;">&#40;</span>FTG.<span style="color: #202020;">StartTime</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> last_time<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , FTG.<span style="color: #202020;">SessionLoginName</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , E.<span style="color: #202020;">event_id</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #AF0000;">fn_trace_gettable</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #0000FF;">LEFT</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">path</span>, <span style="color: #FF00FF;">LEN</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">path</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">-</span> <span style="color: #FF00FF;">CHARINDEX</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'\'</span>, <span style="color: #FF00FF;">REVERSE</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">path</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">'\Log.trc'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">traces</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; is_default <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #000;">6</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> FTG<br />
<span style="color: #0000FF;">LEFT</span> <span style="color: #808080;">JOIN</span> &nbsp; &nbsp; &nbsp; @events <span style="color: #0000FF;">AS</span> E<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> E.<span style="color: #202020;">event_id</span> <span style="color: #808080;">=</span> FTG.<span style="color: #202020;">EventClass</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FTG.<span style="color: #202020;">EventClass</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">BETWEEN</span> <span style="color: #000;">65527</span> <span style="color: #808080;">AND</span> <span style="color: #000;">65528</span><br />
<span style="color: #0000FF;">GROUP</span> <span style="color: #0000FF;">BY</span>&nbsp; &nbsp; &nbsp; &nbsp; FTG.<span style="color: #202020;">DatabaseName</span>, E.<span style="color: #202020;">event_name</span>, FTG.<span style="color: #202020;">ApplicationName</span>, E.<span style="color: #202020;">event_id</span>, FTG.<span style="color: #202020;">SessionLoginName</span><br />
<span style="color: #0000FF;">ORDER</span> <span style="color: #0000FF;">BY</span>&nbsp; &nbsp; &nbsp; &nbsp; first_time</div></td></tr></tbody></table></div>
<p>Alors bon traçage à tous !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sys.dm_exec_query_profiles : la DMV qui détaille les noeuds d&#8217;un plan d&#8217;exécution réel</title>
		<link>https://blog.developpez.com/elsuket/p13089/moteur-de-base-de-donnees-sql-server/indexation/sys-dm_exec_query_profiles-la-dmv-qui-detaille-les-noeuds-dun-plan-dexecution-reel</link>
		<comments>https://blog.developpez.com/elsuket/p13089/moteur-de-base-de-donnees-sql-server/indexation/sys-dm_exec_query_profiles-la-dmv-qui-detaille-les-noeuds-dun-plan-dexecution-reel#comments</comments>
		<pubDate>Tue, 09 Aug 2016 08:00:57 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Indexation]]></category>
		<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[SQL Server 2014]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=1266</guid>
		<description><![CDATA[La lecture du plan d&#8217;exécution réel peut s&#8217;avérer être une tâche laborieuse, surtout lorsque le plan contient de nombreux opérateurs ou nœuds. Introduite avec SQL Server 2014, la vue de gestion dynamique sys.dm_exec_query_profiles nous permet de voir quel(s) nœud(s) d&#8217;un &#8230; <a href="https://blog.developpez.com/elsuket/p13089/moteur-de-base-de-donnees-sql-server/indexation/sys-dm_exec_query_profiles-la-dmv-qui-detaille-les-noeuds-dun-plan-dexecution-reel">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>La lecture du plan d&rsquo;exécution réel peut s&rsquo;avérer être une tâche laborieuse, surtout lorsque le plan contient de nombreux opérateurs ou nœuds.</p>
<p>Introduite avec SQL Server 2014, la vue de gestion dynamique <em>sys.dm_exec_query_profiles</em> nous permet de voir quel(s) nœud(s) d&rsquo;un <a href="http://blog.developpez.com/elsuket/p12879/moteur-de-base-de-donnees-sql-server/capture-manuelle-de-plans-de-requete" title="Capture manuelle de plans de requête">plan d&rsquo;exécution réel</a> consomme le plus de ressources et /ou de temps. C&rsquo;est donc un formidable outil qui peut faire largement diminuer la recherche des points noueux d&rsquo;une requête à l&rsquo;étude.</p>
<p><span id="more-1266"></span></p>
<p><a href="https://msdn.microsoft.com/en-us/library/dn223301.aspx">La documentation</a> de cette DMV montre qu&rsquo;elle expose de nombreuses colonnes, qui nous renseignent de façon très précise sur la consommation de ressources physiques de chaque opérateur du plan de requête, notamment avec le nombre de millisecondes après lequel un opérateur s&rsquo;est exécuté pour la première et la dernière fois. Pour simplifier l&rsquo;analyse des requêtes, on peut s&rsquo;en tenir à quelques unes d&rsquo;entre-elles, comme dans la requête suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; physical_operator_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_query_profiles</span></div></td></tr></tbody></table></div>
<p>La colonne <em>node_id</em> nous donne le numéro de l&rsquo;opérateur dans le plan de requête. Il faut noter que l&rsquo;opérateur racine de l&rsquo;arbre de résolution qu&rsquo;est le plan de requête, et qui se situe en haut et à gauche dans le plan d&rsquo;exécution graphique, est le seul dans tout plan à ne pas porter de <em>NodeID</em>. L&rsquo;opérateur qui le précède porte le <em>NodeID</em> 0, et celui qui précède ce dernier le <em>NodeID</em> 1, et ainsi de suite. Le plus grand numéro de <em>NodeID</em> est à l&rsquo;opérateur qui est le plus à droite et en bas du plan d&rsquo;exécution graphique.</p>
<p>La colonne <em>session_id</em> va nous permettre de spécifier sur quelle session porte notre étude : pour que cette vue expose des lignes, il est nécessaire que l&rsquo;option de session SET STATISTICS XML soit positionnée à ON pour la requête à étudier. Ceci équivaut à l&rsquo;activation de l&rsquo;option d&rsquo;inclusion du plan d&rsquo;exécution réel dans la barre d&rsquo;outil de SQL Server Management Studio (SSMS) avant l&rsquo;exécution d&rsquo;une requête. Ceci est normal, puisque comme pour toutes les tâches de monitoring, elle viennent avec un coût : celui-ci pourrait devenir trop élevé si toutes les requêtes étaient auditées à ce niveau de détail, d&rsquo;autant que ce type d&rsquo;information est utilisé par les DBAs, et pas par les applications qui interagissent avec la base de données.</p>
<p>Supposons que la requête (très simple) que l&rsquo;on souhaite étudier est la suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sales.<span style="color: #202020;">SalesOrderDetail</span> <span style="color: #0000FF;">AS</span> SOD<br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; Production.<span style="color: #202020;">Product</span> <span style="color: #0000FF;">AS</span> P<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> SOD.<span style="color: #202020;">ProductID</span> <span style="color: #808080;">=</span> P.<span style="color: #202020;">ProductID</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P.<span style="color: #202020;">ListPrice</span> <span style="color: #808080;">&amp;</span>gt; <span style="color: #000;">1000</span></div></td></tr></tbody></table></div>
<p>On peut récupérer le session_id de plusieurs manières :</p>
<ul>
<li>Il est indiqué dans la barre d&rsquo;état de toute fenêtre de requête sous SSMS, en bas à droite;</li>
<li>Si l&rsquo;on a conservé les options par défaut de SSMS, il est aussi indiqué sur l&rsquo;onglet de la fenêtre de requête;</li>
<li>On peut exécuter SELECT @@SPID dans la même fenêtre de requête que celle à étudier.</li>
</ul>
<p><img src="http://i.imgur.com/JLFuhns.png" alt="" /></p>
<p>Ne soyez pas perturbé par l&rsquo;option de session <em>SET STATISTICS IO, TIME ON</em> positionné juste avant la requête : je l&rsquo;utilise toujours pour diagnostiquer une requête, car cela expose le temps CPU, la durée totale, et surtout, le nombre d&rsquo;IOs produit par la requête pour chaque table participant à celle-ci. On peut adjoindre l&rsquo;option <em>XML</em> à la liste <em>IO, TIME</em> si on le souhaite.</p>
<p>Les lecteurs aux yeux affûtés auront remarqué que dans la capture d&rsquo;écran ci-dessus, il y a un deuxième onglet ouvert : en effet, on doit utiliser une fenêtre de requête pour celle à étudier, et une autre pour lire la sortie de la vue <em>sys.dm_exec_query_profiles</em> pour cette session. Pour cet exemple, on peut reprendre la première requête, et rajouter la clause WHERE adéquate : la session qui va exécuter la requête à l&rsquo;étude porte le <em>session_id</em> 51 :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; physical_operator_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_query_profiles</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; session_id <span style="color: #808080;">=</span> <span style="color: #000;">51</span> <span style="color: #008080;">-- session_id de la requête à l'étude</span></div></td></tr></tbody></table></div>
<p>L&rsquo;exercice consiste donc à démarrer l&rsquo;exécution de la requête à l&rsquo;étude, puis à basculer vers la fenêtre de requête qui spécifie la vue <em>sys.dm_exec_query_profiles</em> avant la fin de l&rsquo;exécution de la requête à l&rsquo;étude. Pour la requête de cet exemple, cela nous donne :</p>
<p><img src="http://i.imgur.com/FJozDlw.png" alt="" /></p>
<p>On constate ainsi des écarts importants entre le nombre de lignes estimé et réel pour les opérateurs dont le <em>NodeID</em> est 0 et 4, mais il y a un problème : alors que la somme des valeurs de la colonne <em>elapsed_time_ms</em> nous donne 15, la sortie dans l&rsquo;onglet <em>Messages</em> est la suivante (légèrement écourtée, notamment les IOs physiques et de LOBs, pour les besoins de l&rsquo;article) :</p>
<blockquote><p>(29382 row(s) affected)<br />
Table &lsquo;Workfile&rsquo;. Scan count 0, logical reads 0<br />
Table &lsquo;Worktable&rsquo;. Scan count 0, logical reads 0<br />
Table &lsquo;SalesOrderDetail&rsquo;. Scan count 1, logical reads 1246<br />
Table &lsquo;Product&rsquo;. Scan count 1, logical reads 15</p>
<p> SQL Server Execution Times:<br />
   CPU time = 156 ms,  elapsed time = <strong>1225</strong> ms.</p></blockquote>
<p>Il y a bien sûr le temps de consommation du jeu de lignes de résultat par SSMS. On peut le confirmer en éliminant le résultat une fois la requête exécutée : pour ce faire, il suffit de faire un clic-droit dans un zone vierge de la requête &gt; <em>Query options</em> &#8230; &gt; <em>Results</em> / <em>Grid</em> &gt; et de cocher la case <em>Discard results after execution</em>.</p>
<p>La question qui vient maintenant est : comment faire pour les requêtes dont l&rsquo;exécution est bien plus longue ? Et dans tous les cas, la durée d&rsquo;exécution des requêtes n&rsquo;étant pas précisément prédictible même après une ou deux exécutions, comment capturer les valeurs qu&rsquo;expose cette DMV en s&rsquo;approchant le plus possible de la fin de la requête ? On peut pour cela écrire une boucle qui va stocker le contenu de la DMV à intervalles réguliers et fréquents, et qui vérifie à chaque tour que la requête est toujours en cours d&rsquo;exécution :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">NOCOUNT</span> <span style="color: #0000FF;">ON</span><br />
GO<br />
<br />
<span style="color: #0000FF;">DECLARE</span> @session_id <span style="color: #0000FF;">int</span> <span style="color: #808080;">=</span> <span style="color: #000;">51</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @delay <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">8</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'00:00:00.010'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @i <span style="color: #0000FF;">int</span> <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
<br />
<span style="color: #0000FF;">IF</span> <span style="color: #FF00FF;">OBJECT_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TempDB.dbo.#query_profile_global'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">IS</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DROP</span> <span style="color: #0000FF;">TABLE</span> #query_profile_global<br />
<br />
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> #query_profile_global<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; physical_operator_name <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id <span style="color: #0000FF;">int</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_name</span> sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , index_name sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , time_stamp <span style="color: #0000FF;">datetime</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span><br />
<br />
<span style="color: #0000FF;">DECLARE</span> @query_profile <span style="color: #0000FF;">TABLE</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; physical_operator_name <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id <span style="color: #0000FF;">int</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_name</span> sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , index_name sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , time_stamp <span style="color: #0000FF;">datetime</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span><br />
<br />
<span style="color: #0000FF;">WHILE</span> <span style="color: #808080;">EXISTS</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_requests</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; session_id <span style="color: #808080;">=</span> @session_id<br />
<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INSERT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INTO</span> @query_profile<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; QP.<span style="color: #202020;">physical_operator_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">node_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">elapsed_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">cpu_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">estimate_row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">logical_read_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">rewind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">rebind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">end_of_scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , O.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> <span style="color: #FF00FF;">object_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , I.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> index_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">GETDATE</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> time_stamp<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_query_profiles</span> <span style="color: #0000FF;">AS</span> QP<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">LEFT</span> <span style="color: #808080;">JOIN</span> &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">objects</span> <span style="color: #0000FF;">AS</span> O<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> QP.<span style="color: #FF00FF;">object_id</span> <span style="color: #808080;">=</span> O.<span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">LEFT</span> <span style="color: #808080;">JOIN</span> &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">indexes</span> <span style="color: #0000FF;">AS</span> I<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> QP.<span style="color: #202020;">index_id</span> <span style="color: #808080;">=</span> I.<span style="color: #202020;">index_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> QP.<span style="color: #FF00FF;">object_id</span> <span style="color: #808080;">=</span> I.<span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; QP.<span style="color: #202020;">session_id</span> <span style="color: #808080;">=</span> @session_id <span style="color: #008080;">-- spid running query</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @i <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INSERT</span>&nbsp; <span style="color: #0000FF;">INTO</span> #query_profile_global<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; @query_profile<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">UPDATE</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #query_profile_global<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; physical_operator_name <span style="color: #808080;">=</span> QP.<span style="color: #202020;">physical_operator_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , node_id <span style="color: #808080;">=</span> QP.<span style="color: #202020;">node_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms <span style="color: #808080;">=</span> QP.<span style="color: #202020;">elapsed_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms <span style="color: #808080;">=</span> QP.<span style="color: #202020;">cpu_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , row_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">estimate_row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">logical_read_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , rewind_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">rewind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , rebind_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">rebind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">end_of_scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_name</span> <span style="color: #808080;">=</span> QP.<span style="color: #FF00FF;">object_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , index_name <span style="color: #808080;">=</span> QP.<span style="color: #202020;">index_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , scan_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , time_stamp <span style="color: #808080;">=</span> QP.<span style="color: #202020;">time_stamp</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @query_profile <span style="color: #0000FF;">AS</span> QP<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; #query_profile_global <span style="color: #0000FF;">AS</span> QFG<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> QFG.<span style="color: #202020;">node_id</span> <span style="color: #808080;">=</span> QP.<span style="color: #202020;">node_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WAITFOR</span> DELAY @delay<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DELETE</span> <span style="color: #0000FF;">FROM</span> @query_profile<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @i <span style="color: #808080;">+=</span> <span style="color: #000;">1</span><br />
<span style="color: #0000FF;">END</span><br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #0000FF;">DISTINCT</span> <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; #query_profile_global<br />
<span style="color: #0000FF;">ORDER</span> &nbsp; <span style="color: #0000FF;">BY</span> node_id<br />
<span style="color: #008080;">--ORDER BY elapsed_time_ms DESC</span></div></td></tr></tbody></table></div>
<p>Ici on stocke le contenu de la DMV toutes les 10 ms. Le délai entre chaque boucle peut être adapté : si l&rsquo;on sait que la requête dure environ quart d&rsquo;heure, une récupération du contenu de la vue toutes les secondes est suffisante. Cette valeur peut donc être adaptée suivant la durée d&rsquo;exécution globale de la requête. Il faut aussi veiller à exécuter ce lot de requêtes dans le même contexte de base de données que celui sous lequel on exécute la requête à étudier. En effet, cela permet d&rsquo;obtenir le nom de l&rsquo;objet de base de données accédé :</p>
<p><img src="http://i.imgur.com/vdDfdkK.png" /></p>
<p>On constate dans la sortie du lot de requêtes interrogeant la DMV que, par exemple, l&rsquo;opérateur de <em>NodeID</em> 4 est l&rsquo;accès à l&rsquo;index cluster de la table <em>SalesOrderDetail</em>, et qu&rsquo;il a traité 121317 lignes. Voyons si cela est reflété par le plan d&rsquo;exécution réel graphique de la requête :</p>
<p><img src="http://i.imgur.com/Z6l9xMA.png" alt="" /></p>
<p>Le numéro de <em>NodeID</em> 4 est bien l&rsquo;opérateur exposé par la DMV, et si l&rsquo;on lit la ligne de la bulle dont le libellé est <em>Actual number of rows</em>, on a bien 121317.</p>
<p>Pour l&rsquo;étude des requêtes plus lourdes, la DMV <em>sys.dm_exec_query_profiles</em> nous permettra de repérer immédiatement les opérateurs les plus consommateurs de ressources, et donc de travailler directement sur ceux-ci en se reportant au plan de requête, puis à la requête elle-même pour en revoir l&rsquo;écriture et éventuellement l&rsquo;indexation.</p>
<p>Bonne optimisation !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vérifier la validité d&#8217;un SIRET &#8211; Algorithme de Luhn</title>
		<link>https://blog.developpez.com/elsuket/p13056/snippets/verifier-la-validite-dun-siret-algorithme-de-luhn</link>
		<comments>https://blog.developpez.com/elsuket/p13056/snippets/verifier-la-validite-dun-siret-algorithme-de-luhn#comments</comments>
		<pubDate>Thu, 23 Jun 2016 18:54:56 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[Utilitaires]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=1233</guid>
		<description><![CDATA[Lors d&#8217;un chargement massif de données et/ou d&#8217;une migration, il est possible que la qualité des données soient altérées. Il faut alors tester leur qualité et valider chaque écart. Parmi ceux-ci, on peut trouver les numéro SIRET, qui permet l&#8217;identification &#8230; <a href="https://blog.developpez.com/elsuket/p13056/snippets/verifier-la-validite-dun-siret-algorithme-de-luhn">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Lors d&rsquo;un chargement massif de données et/ou d&rsquo;une migration, il est possible que la qualité des données soient altérées. Il faut alors tester leur qualité et valider chaque écart. Parmi ceux-ci, on peut trouver les numéro SIRET, qui permet l&rsquo;identification d&rsquo;un établissement ou d&rsquo;une entreprise Française.</p>
<p>Cet identifiant numérique est constitué de 14 chiffres, et est articulé en trois parties :</p>
<ul>
<li>le SIREN</li>
<li>le Numéro Interne de Classement, à quatre chiffres : c&rsquo;est l&rsquo;ordre de création de l’établissement par l&rsquo;entreprise Française</li>
<li>une clé de contrôle, constituée d&rsquo;un seul chiffre</li>
</ul>
<p>Ce dernier est calculé à l&rsquo;aide de l&rsquo;<a href="https://fr.wikipedia.org/wiki/Formule_de_Luhn">algorithme de Luhn</a>. Cet algorithme est aussi utilisé pour valider les numéros de carte bleue, et de nombreux identifiants distribués par les administrations de beaucoup de pays. Nous allons nous en servir pour vérifier la validité de SIRETs en l&rsquo;implémentant spécifiquement pour ce type d&rsquo;identifiant.</p>
<p><span id="more-1233"></span></p>
<p>L&rsquo;algorithme est descriptible comme suit :</p>
<ol>
<li>Pour chaque chiffre dont l&rsquo;index dans la chaîne est impair, on le multiplie par 2; si le résultat est supérieur à 9, on additionne les chiffes qui constituent ce résultat. Ceci revient à multiplier par 2 le chiffre, diviser le résultat par 10, puis ajouter la multiplication par 2 de ce même chiffre modulo 10.</li>
<li>On additionne ensuite les chiffres du résultat un à un, avec les chiffres de l&rsquo;identifiant qui n&rsquo;ont pas été traités, c&rsquo;est à dire ceux dont l&rsquo;index dans la chaîne est pair. Ceci inclut le chiffre de l&rsquo;identifiant qui est clé.</li>
<li>Si le résultat obtenu est un multiple de 10, alors l&rsquo;identifiant est valide. Ceci revient à vérifier que le résultat modulo 10 vaut zéro.</li>
</ol>
<p>La traduction en SQL donne :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CASE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> laColonneSIRET <span style="color: #0000FF;">IS</span> <span style="color: #808080;">NULL</span> <span style="color: #0000FF;">THEN</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #FF00FF;">LEN</span><span style="color: #808080;">&#40;</span>laColonneSIRET<span style="color: #808080;">&#41;</span> <span style="color: #808080;">&amp;</span>lt; <span style="color: #000;">14</span> <span style="color: #0000FF;">THEN</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #000;">0</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">bit</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> laColonneSIRET <span style="color: #808080;">LIKE&amp;</span>#039;<span style="color: #808080;">%</span><span style="color: #808080;">&#91;</span><span style="color: #808080;">^</span><span style="color: #000;">0</span><span style="color: #808080;">-</span><span style="color: #000;">9</span><span style="color: #808080;">&#93;</span><span style="color: #808080;">%&amp;</span>#039; <span style="color: #0000FF;">THEN</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #000;">0</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">bit</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">1</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">1</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">3</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">3</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">5</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">5</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">7</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">7</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">9</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">9</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">11</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">11</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">13</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #000;">2</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">13</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">---</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">2</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">4</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">6</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">8</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">10</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">12</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SUBSTRING</span><span style="color: #808080;">&#40;</span>laColonneSIRET, <span style="color: #000;">14</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span> <span style="color: #808080;">%</span> <span style="color: #000;">10</span> <span style="color: #808080;">=</span> <span style="color: #000;">0</span> <span style="color: #0000FF;">THEN</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #000;">1</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">bit</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">ELSE</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #000;">0</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">bit</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">END</span> <span style="color: #0000FF;">AS</span> is_valid_SIRET</div></td></tr></tbody></table></div>
<p>On peut l&#039;utiliser directement dans une vue, comme dans le pseudo code suivant :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE VIEW maVue<br />
AS<br />
SELECT&nbsp; desColonnes<br />
&nbsp; &nbsp; &nbsp; &nbsp; , CASE<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN laColonneSIRET IS NULL THEN NULL<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN LEN(laColonneSIRET) &amp;lt; 14 THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN laColonneSIRET LIKE&amp;#039;%[^0-9]%&amp;#039; THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 * CAST(SUBSTRING(laColonneSIRET, 1, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 1, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 3, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 3, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 5, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 5, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 7, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 7, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 9, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 9, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 11, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 11, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 13, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(laColonneSIRET, 13, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ---<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 2, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 4, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 6, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 8, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 10, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 12, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(laColonneSIRET, 14, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) % 10 = 0 THEN CAST(1 AS bit) ELSE CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; END AS is_valid_SIRET<br />
FROM&nbsp; &nbsp; dbo.maTable</div></td></tr></tbody></table></div>
<p>Si l&#039;on souhaite l&#039;utiliser en colonne calculée, on peut utiliser ce CASE directement dans la définition de ladite colonne, ou bien définir une fonction scalaire comme suit :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE FUNCTION fn_scl_is_valid_SIRET<br />
&nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@_siret char(14)<br />
&nbsp; &nbsp; &nbsp; &nbsp; )<br />
RETURNS bit<br />
WITH SCHEMABINDING<br />
AS<br />
BEGIN<br />
&nbsp; &nbsp; &nbsp; &nbsp; DECLARE @ok bit<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT&nbsp; @ok = CASE<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @_siret IS NULL THEN NULL<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN LEN(@_siret) &amp;lt; 14 THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @_siret LIKE&amp;#039;%[^0-9]%&amp;#039; THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 * CAST(SUBSTRING(@_siret, 1, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 1, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 3, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 3, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 5, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 5, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 7, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 7, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 9, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 9, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 11, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 11, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 13, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@_siret, 13, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ---<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 2, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 4, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 6, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 8, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 10, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 12, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@_siret, 14, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) % 10 = 0 THEN CAST(1 AS bit) ELSE CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; END<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; RETURN @ok<br />
END</div></td></tr></tbody></table></div>
<p>Et en ce qui concerne la création de la colonne calculée, on peut l&#039;ajouter à l&#039;aide du pseudo-T-SQL suivant :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER TABLE maTable<br />
ADD is_valid_SIRET AS(dbo.fn_scl_is_valid_SIRET(laColonneSIRET))</div></td></tr></tbody></table></div>
<p>Enfin, si l&#039;on souhaite exécuter cette vérification au sein d&#039;une requête, on peut s&#039;en remettre à une fonction de table en ligne. Ce type de fonction n&#039;étant appelé qu&#039;une seule fois, il s&#039;avérera plus performant à l&#039;exécution sur un grand nombre de lignes que l&#039;appel à une fonction scalaire : ces dernières sont appelées autant de fois qu&#039;il y a de lignes de résultat. Ce qui donne :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE FUNCTION fn_it_is_valid_SIRET<br />
&nbsp; &nbsp; &nbsp; &nbsp; (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @siret char(14)<br />
&nbsp; &nbsp; &nbsp; &nbsp; )<br />
RETURNS TABLE<br />
WITH SCHEMABINDING<br />
AS<br />
RETURN&nbsp; <br />
(<br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT&nbsp; CASE<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN LEN(COALESCE(@siret,&amp;#039;&amp;#039;)) &amp;lt; 14 THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @siret LIKE&amp;#039;%[^0-9]%&amp;#039; THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @siret IS NULL THEN CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN (<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 * CAST(SUBSTRING(@siret, 1, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 1, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 3, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 3, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 5, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 5, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 7, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 7, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 9, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 9, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 11, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 11, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 13, 1) AS tinyint) / 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 2 * CAST(SUBSTRING(@siret, 13, 1) AS tinyint) % 10<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ---<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 2, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 4, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 6, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 8, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 10, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 12, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + CAST(SUBSTRING(@siret, 14, 1) AS tinyint)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) % 10 = 0 THEN CAST(1 AS bit) ELSE CAST(0 AS bit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END AS is_valid_SIRET<br />
)</div></td></tr></tbody></table></div>
<p>On peut alors l&#039;utiliser à l&#039;aide de l&#039;opérateur APPLY, comme dans l&#039;exemple suivant :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; S.*<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , F.is_valid_SIRET<br />
FROM&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dbo.maTableAvecUneColonneSIRET AS S<br />
CROSS APPLY &nbsp; &nbsp; dbo.fn_it_is_valid_SIRET(S.laColonneSIRET) AS F</div></td></tr></tbody></table></div>
<p>Bonne validation de SIRETs !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sauvegardes de bases de données et envoi d&#8217;email avec SQL Server Express</title>
		<link>https://blog.developpez.com/elsuket/p12612/snippets/sauvegardes-de-bases-de-donnees-et-envoi-demail-avec-sql-server-express</link>
		<comments>https://blog.developpez.com/elsuket/p12612/snippets/sauvegardes-de-bases-de-donnees-et-envoi-demail-avec-sql-server-express#comments</comments>
		<pubDate>Sun, 11 May 2014 10:01:01 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[Utilitaires]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[BACKUP]]></category>
		<category><![CDATA[sauvegarde]]></category>
		<category><![CDATA[SQL Server Express]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=1006</guid>
		<description><![CDATA[Windows Server Update Services (WSUS) est une application qui permet de gérer et distribuer les patch que Microsoft publie pour ses produits. Elle est supportée par SQL Server Express (with Adanced Services), et de ce fait : On ne dispose &#8230; <a href="https://blog.developpez.com/elsuket/p12612/snippets/sauvegardes-de-bases-de-donnees-et-envoi-demail-avec-sql-server-express">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><em>Windows Server Update Services</em> (WSUS) est une application qui permet de gérer et distribuer les patch que Microsoft publie pour ses produits. Elle est supportée par SQL Server Express (with Adanced Services), et de ce fait :</p>
<ul>
<li>On ne dispose pas de l&rsquo;Agent SQL Server</li>
<li>On ne peut pas utiliser des plans de maintenance pour gérer les sauvegardes</li>
<li>On ne peut pas envoyer d&rsquo;emails</li>
<li>La compression des fichiers de backup, introduite avec SQL Server 2008, n&rsquo;est pas prise en charge</li>
</ul>
<p>Si donc on souhaite planifier les sauvegardes de base de données, et envoyer un email en cas d&rsquo;échec, on peut :</p>
<ul>
<li>Remplacer un job de l&rsquo;Agent SQL Server par une tâche du Planificateur de Tâches de Windows</li>
<li>Écrire une procédure stockée d&rsquo;assembly pour envoyer des emails</li>
</ul>
<p>Cet article détaille les étapes à suivre pour ce faire.<br />
<span id="more-1006"></span></p>
<p><span style="font-weight:bold;font-family:Verdana;font-size:18px">Une procédure stockée d&rsquo;assembly pour envoyer des emails</span></p>
<p>Si l&rsquo;Agent SQL Server n&rsquo;est pas disponible, l&rsquo;intégration CLR l&rsquo;est. Ainsi en quelques lignes de code C#, on peut envoyer des e-mails de façon assez similaire à ce qu&rsquo;on peut faire sous les éditions non-Express de SQL Server avec la procédure stockée système <em>msdb.dbo.sp_send_dbmail</em>.</p>
<p>Pour créer une procédure stockée d&rsquo;assembly sous Visual Studio 2012 ou ultérieur, il faut tout d&rsquo;abord installer <em>SQL Server Data Tools</em>. Pour ce faire, vous pouvez lire <a href="http://blog.developpez.com/elsuket/p12610/utilitaires/ssdt-bi-et-ssdt-ou-lun-ou-lautre-et-aussi-les-deux" title="SSDT-BI et SSDT : ou l’un, ou l’autre, et aussi les deux !">ce billet</a>. Notez qu&rsquo;il n&rsquo;est pas nécessaire d&rsquo;avoir Visual Studio déjà installé.</p>
<p>Une fois Visual Studio démarré, il suffit de créer un nouveau projet à partir de la page de démarrage, ou bien de suivre <em>File</em> &gt; <em>New</em> &gt; <em>Project</em>, et de choisir un projet SQL Server :</p>
<p><img src="http://i.imgur.com/3Doxf4q.png" alt="" /></p>
<p>Il faut faire attention à la version du framework .NET. Par exemple, si l&rsquo;on souhaite que l&rsquo;assembly soit exécutable par SQL Server 2008, il faut spécifier la version 3.5. Une fois que l&rsquo;on a validé le tout par OK, nous pouvons ajouter une procédure stockée :</p>
<p><img src="http://i.imgur.com/YbADCND.png" alt="" /></p>
<p>Comme je préfère C# à VB.NET, j&rsquo;ai choisi une procédure stockée C#, mais si vous préférez VB.NET, rien ne s&rsquo;y oppose. Notons que par défaut, le langage de la procédure stockée n&rsquo;est pas pré-sélectionné.</p>
<p><img src="http://i.imgur.com/Fb6O7pN.png" alt="" /></p>
<p>Une fois que l&rsquo;on a validé le tout par un clic sur <em>Add</em>, on peut écrire :</p>
<div class="codecolorer-container csharp vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="csharp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System.Net</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System.Net.Mail</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System.Data</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System.Data.SqlClient</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">System.Data.SqlTypes</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008080;">Microsoft.SqlServer.Server</span><span style="color: #008000;">;</span><br />
<br />
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">partial</span> <span style="color: #6666cc; font-weight: bold;">class</span> StoredProcedures<br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#91;</span>Microsoft<span style="color: #008000;">.</span><span style="color: #0000FF;">SqlServer</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Server</span><span style="color: #008000;">.</span><span style="color: #0000FF;">SqlProcedure</span><span style="color: #008000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">static</span> <span style="color: #6666cc; font-weight: bold;">void</span> spasb_mail_send <span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">string</span> sender, <span style="color: #6666cc; font-weight: bold;">string</span> recipients, <span style="color: #6666cc; font-weight: bold;">string</span> subject, <span style="color: #6666cc; font-weight: bold;">string</span> body<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SmtpClient mailServer <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SmtpClient<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;mail.myCompany.com&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; MailMessage mail <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> MailMessage<span style="color: #008000;">&#40;</span>sender, recipients, subject, body<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; mail<span style="color: #008000;">.</span><span style="color: #0000FF;">IsBodyHtml</span> <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span><span style="color: #008000;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; mailServer<span style="color: #008000;">.</span><span style="color: #0000FF;">Send</span><span style="color: #008000;">&#40;</span>mail<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Ce qui, même pour l&rsquo;ultra-débutant C# que je suis, est loin d&rsquo;être complexe. Avant de builder le projet, il nous faut configurer l&rsquo;assembly pour lui permettre d&rsquo;accéder à des ressources externes, ce qui se fait après un clic-droit sur le projet, et choisi <em>Properties</em> (ou pour les aficionados du raccourci clavier, ALT + Entrée). Dans la page <em>SQLCLR</em>, nous commutons donc la liste déroulante <em>Permission Level</em> sur EXTERNAL_ACCESS. De la même façon, dans la page <em>SQLCLR Build</em>, nous commutons la liste déroulante <em>Configuration</em> sur <em>Release</em>, ce qui permet un léger gain de performances. Ce n&rsquo;est pas très important dans notre cas, mais si l&rsquo;assembly est plus complexe, cela peut le devenir.</p>
<p><img src="http://i.imgur.com/TW1gYM4.png" alt="" /></p>
<p>Après un clic sur <em>Build</em> &gt; <em>Build Solution</em>, nous pouvons aller chercher le fichier dll dans le dossier de la solution. Dans cet exemple, il s&rsquo;agit de <em>D:\SQLServer\Assemblies\SQLServerExpressDatabaseMail\SQLServerExpressDatabaseMail\bin\Debug</em>, et le fichier est nommé <em>SQLServerExpressDatabaseMail.dll</em>.</p>
<p><img src="http://i.imgur.com/vjePpel.png" alt="" /></p>
<p>De retour dans <em>SQL Server Management Studio</em>, une fois connecté à l&rsquo;instance SQL Server Express, il est tout d&rsquo;abord nécessaire d&rsquo;activer la prise en charge de la CLR par cette dernière. Cela se fait sans redémarrage de l&rsquo;instance, en quelques instruction :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'clr enabled'</span>, <span style="color: #000;">1</span><br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO</div></td></tr></tbody></table></div>
<p>Il est maintenant requis de déclarer la base de données dans laquelle nous allons enregistrer la procédure stockée d&rsquo;assembly comme &laquo;&nbsp;digne de confiance&nbsp;&raquo;. Ceci nous permet d&rsquo;emprunter l&rsquo;identité de SQL Server pour exécuter cette procédure qui va accéder à des ressources en dehors de la base de données : en l’occurrence, un serveur de mails (mais ce peut être le système de fichiers, un webservice, &#8230;). Là encore, une simple commande suffit :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">DATABASE</span> DBA<br />
<span style="color: #0000FF;">SET</span> TRUSTW<span style="color: #808080;">OR</span>THY <span style="color: #0000FF;">ON</span><br />
GO</div></td></tr></tbody></table></div>
<p>Nous devons maintenant enregistrer l&rsquo;assembly dans la base de données, ce que l&rsquo;on peut faire une fois que l&rsquo;on a copié l&rsquo;assembly dans un dossier de notre choix, sur le serveur hébergeant l&rsquo;instance SQL Server Express / WSUS. Dans cet exemple, nous utilisons le dossier C:\SQLServer\.</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">USE</span> DBA<br />
GO<br />
<br />
<span style="color: #0000FF;">CREATE</span> ASSEMBLY SQLServerExpressDatabaseMail<br />
<span style="color: #0000FF;">FROM</span> <span style="color: #FF0000;">'C:\SQLServer\SQLServerExpressDatabaseMail.dll'</span><br />
<span style="color: #0000FF;">WITH</span> PERMISSION_SET <span style="color: #808080;">=</span> EXTERNAL_ACCESS<br />
GO</div></td></tr></tbody></table></div>
<p>On peut vérifier l&rsquo;enregistrement de l&rsquo;assembly en interrogeant la vue système <em>sys.assemblies</em>. En ce point, on n&rsquo;a plus besoin du fichier dll : le binaire de celle-ci est maintenant enregistré dans la base de données (de nom DBA dans cet exemple).<br />
Créons maintenant la procédure stockée :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">PROCEDURE</span> dbo.<span style="color: #202020;">spasb_mail_send</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @_sender <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @_recipients <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @_subject <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @_body <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">4000</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">EXTERNAL</span> NAME SQLServerExpressDatabaseMail.<span style="color: #202020;">StoredProcedures</span>.<span style="color: #202020;">spasb_mail_send</span><br />
GO</div></td></tr></tbody></table></div>
<p>Et testons enfin :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">EXEC</span> dbo.<span style="color: #202020;">spasb_mail_send</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">'it@myCompany.com'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF0000;">'me@myCompany.com'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF0000;">'Test Mail from Assembly Stored Procedure'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF0000;">'Hey Hey !'</span></div></td></tr></tbody></table></div>
<p><span style="font-weight:bold;font-family:Verdana;font-size:18px">Une procédure stockée pour gérer les sauvegardes</span></p>
<p>Voici une procédure stockée générique qui permet de sauvegarder une base de données en particulier, ou toutes les bases de données hébergées par une instance SQL Server. Dans le second cas, les sauvegardes du fichier du journal des transactions n&rsquo;est pas supportée. En revanche, on peut exécuter cette procédure stockée sur toutes les versions de SQL Server, à partir de 2005. Enfin, le cryptage des sauvegardes, introduit avec SQL Server 2014 n&rsquo;est pas supporté non plus. Cela exige que quelques prérequis soient en place, et ceux-là sortent du cadre de cet article.</p>
<p>La procédure stockée d&rsquo;assembly est référencée dans le bloc CATCH final : pour toute erreur, on envoie un email.</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br />134<br />135<br />136<br />137<br />138<br />139<br />140<br />141<br />142<br />143<br />144<br />145<br />146<br />147<br />148<br />149<br />150<br />151<br />152<br />153<br />154<br />155<br />156<br />157<br />158<br />159<br />160<br />161<br />162<br />163<br />164<br />165<br />166<br />167<br />168<br />169<br />170<br />171<br />172<br />173<br />174<br />175<br />176<br />177<br />178<br />179<br />180<br />181<br />182<br />183<br />184<br />185<br />186<br />187<br />188<br />189<br />190<br />191<br />192<br />193<br />194<br />195<br />196<br />197<br />198<br />199<br />200<br />201<br />202<br />203<br />204<br />205<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">PROCEDURE</span> dbo.<span style="color: #202020;">databaseBackup_manage</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @_backup_type <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">12</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @_database_name <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">128</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">=</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @_backup_server_network_path <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @_print_only <span style="color: #0000FF;">bit</span> <span style="color: #808080;">=</span> <span style="color: #000;">0</span><br />
<span style="color: #0000FF;">AS</span><br />
<span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">NOCOUNT</span> <span style="color: #0000FF;">ON</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DECLARE</span> @<span style="color: #0000FF;">sql</span> <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">4000</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @err_msg <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">2048</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @compression <span style="color: #0000FF;">bit</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @checkum <span style="color: #0000FF;">bit</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @mail_subject <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">4000</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">=</span> <span style="color: #FF00FF;">@@SERVERNAME</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">' Backups'</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- SQL Server 2005 ne supporte pas l'affectation directe de valeurs*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- à des variables lors de la déclaration</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; @compression <span style="color: #808080;">=</span> <span style="color: #000;">0</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span> TRY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Gestion de la compression des sauvegardes</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- SQL Server 2008 Enterprise et Developer</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'ProductVersion'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">32</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'10.0%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Edition'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">64</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'Enterprise%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">OR</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Edition'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">64</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'Developer%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">OR</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- SQL Server 2008 R2 Enterprise, Standard et Developer</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Et toute version après celle-ci</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'ProductVersion'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">32</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'10.50%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">OR</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">LEFT</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'ProductVersion'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">32</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span>, <span style="color: #000;">2</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF0000;">'.'</span>, <span style="color: #FF0000;">''</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">tinyint</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">&amp;</span>gt; <span style="color: #000;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Edition'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">64</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'Enterprise%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">OR</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Edition'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">64</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'Standard%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">OR</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">SERVERPROPERTY</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Edition'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">64</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'Developer%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @compression <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Vérifie que le chemin réseau commence par un double anti-slash</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @_backup_server_network_path <span style="color: #808080;">NOT</span> <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'\\%'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> <span style="color: #FF0000;">'The network path '</span> <span style="color: #808080;">+</span> @_backup_server_network_path <span style="color: #808080;">+</span> <span style="color: #FF0000;">' is not valid.'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Ajoute l'anti-slash à la fin du chemin réseau, le cas échéant</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span> @_backup_server_network_path <span style="color: #808080;">=</span> @_backup_server_network_path <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #FF00FF;">CHARINDEX</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'\'</span>, <span style="color: #FF00FF;">REVERSE</span><span style="color: #808080;">&#40;</span>@_backup_server_network_path<span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">&amp;</span>gt; <span style="color: #000;">1</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'\'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span> <span style="color: #FF0000;">''</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @_database_name <span style="color: #0000FF;">IS</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">--------------------------------------------------</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Sauvegarde d'une base de données en particulier</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">--------------------------------------------------</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">EXISTS</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">databases</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">=</span> @_database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> <span style="color: #FF0000;">'La base de données '</span><span style="color: #FF0000;">''</span> <span style="color: #808080;">+</span> @_database_name <span style="color: #808080;">+</span> <span style="color: #FF0000;">''</span><span style="color: #FF0000;">' n'</span><span style="color: #FF0000;">'existe pas.'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">EXISTS</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">databases</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">=</span> @_database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; state_desc <span style="color: #808080;">=</span> <span style="color: #FF0000;">'ONLINE'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; user_access_desc <span style="color: #808080;">=</span> <span style="color: #FF0000;">'MULTI_USER'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; source_database_id <span style="color: #0000FF;">IS</span> <span style="color: #808080;">NULL</span> <span style="color: #008080;">-- La base de données n'est pas un snapshot</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; database_id &nbsp;<span style="color: #000;">2</span> <span style="color: #008080;">-- La base de données n'est pas TempDB</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> <span style="color: #FF0000;">'La base de données '</span><span style="color: #FF0000;">''</span> <span style="color: #808080;">+</span> @_database_name <span style="color: #808080;">+</span> <span style="color: #FF0000;">''</span><span style="color: #FF0000;">' n'</span><span style="color: #FF0000;">'est pas disponible ou est une capture intantanée.'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Vérifie le type de backup</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @_backup_type <span style="color: #808080;">NOT</span> <span style="color: #808080;">IN</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'FULL'</span>, <span style="color: #FF0000;">'DIFFERENTIAL'</span>, <span style="color: #FF0000;">'LOG'</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> <span style="color: #FF0000;">'The backup type '</span><span style="color: #FF0000;">''</span> <span style="color: #808080;">+</span> @_backup_type <span style="color: #808080;">+</span> <span style="color: #FF0000;">''</span><span style="color: #FF0000;">' is invalid.'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @<span style="color: #0000FF;">sql</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'BACKUP '</span> <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> @_backup_type <span style="color: #808080;">IN</span> <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'FULL'</span>, <span style="color: #FF0000;">'DIFFERENTIAL'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'DATABASE '</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> @_backup_type <span style="color: #808080;">=</span> <span style="color: #FF0000;">'LOG'</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'LOG '</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> <span style="color: #808080;">+</span> @_database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF0000;">' TO DISK = '</span><span style="color: #FF0000;">''</span> <span style="color: #808080;">+</span> @_backup_server_network_path <span style="color: #808080;">+</span> <span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">@@SERVERNAME</span>, <span style="color: #FF0000;">'\'</span>, <span style="color: #FF0000;">'_'</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">'\'</span> <span style="color: #808080;">+</span> @_database_name <span style="color: #808080;">+</span> <span style="color: #FF0000;">'_'</span> <span style="color: #808080;">+</span> @_backup_type <span style="color: #808080;">+</span> <span style="color: #FF0000;">'_'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">CONVERT</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">char</span><span style="color: #808080;">&#40;</span><span style="color: #000;">19</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF00FF;">GETDATE</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span>, <span style="color: #000;">120</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF0000;">':'</span>, <span style="color: #FF0000;">'-'</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF0000;">' '</span>, <span style="color: #FF0000;">'_'</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">'.bak'</span><span style="color: #FF0000;">''</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF0000;">' WITH '</span> <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span> @_backup_type<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #FF0000;">'DIFFERENTIAL'</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'DIFFERENTIAL, '</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #FF0000;">'FULL'</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'INIT, '</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span> <span style="color: #FF0000;">''</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span> @compression <span style="color: #0000FF;">WHEN</span> <span style="color: #000;">1</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'COMPRESSION, '</span> <span style="color: #0000FF;">ELSE</span> <span style="color: #FF0000;">''</span> <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF0000;">'CHECKSUM'</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @_print_only <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">PRINT</span> @<span style="color: #0000FF;">sql</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span> TRY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_executesql</span> @<span style="color: #0000FF;">sql</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> TRY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span> CATCH<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> @_database_name <span style="color: #808080;">+</span> <span style="color: #FF0000;">' | '</span> <span style="color: #808080;">+</span> ERR<span style="color: #808080;">OR</span>_MESSAGE<span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> CATCH<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">--------------------------------------------------------</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Sauvegarde de toutes les bases de données disponibles</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">--------------------------------------------------------</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @_backup_type <span style="color: #808080;">=</span> <span style="color: #FF0000;">'LOG'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> <span style="color: #FF0000;">'On ne prend pas une sauvegarde du fichier du journal des transactions de toutes les bases de données.'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DECLARE</span> @database_list <span style="color: #0000FF;">TABLE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; database_name <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">128</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INSERT</span>&nbsp; <span style="color: #0000FF;">INTO</span> @database_list<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span>name, <span style="color: #FF0000;">' '</span>, <span style="color: #FF0000;">''</span><span style="color: #808080;">&#41;</span> <span style="color: #008080;">-- Certaines bases de données ne respectent pas la convention de nommage SQL ANSI.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">databases</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; source_database_id <span style="color: #0000FF;">IS</span> <span style="color: #808080;">NULL</span> <span style="color: #008080;">-- La base de données n'est pas un snapshot</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; state_desc <span style="color: #808080;">=</span> <span style="color: #FF0000;">'ONLINE'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; user_access_desc <span style="color: #808080;">=</span> <span style="color: #FF0000;">'MULTI_USER'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; database_id &nbsp;<span style="color: #000;">2</span> <span style="color: #008080;">-- On exclut TempDB</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHILE</span> <span style="color: #808080;">EXISTS</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; @database_list<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #0000FF;">TOP</span> <span style="color: #000;">1</span> @_database_name <span style="color: #808080;">=</span> database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; @database_list<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @<span style="color: #0000FF;">sql</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'BACKUP DATABASE '</span> <span style="color: #808080;">+</span> @_database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF0000;">' TO DISK = '</span><span style="color: #FF0000;">''</span> <span style="color: #808080;">+</span> @_backup_server_network_path <span style="color: #808080;">+</span> <span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">@@SERVERNAME</span>, <span style="color: #FF0000;">'\'</span>, <span style="color: #FF0000;">'_'</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">'\'</span> <span style="color: #808080;">+</span> @_database_name <span style="color: #808080;">+</span> <span style="color: #FF0000;">'_'</span> <span style="color: #808080;">+</span> @_backup_type <span style="color: #808080;">+</span> <span style="color: #FF0000;">'_'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #FF00FF;">REPLACE</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">CONVERT</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">char</span><span style="color: #808080;">&#40;</span><span style="color: #000;">19</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF00FF;">GETDATE</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span>, <span style="color: #000;">120</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF0000;">':'</span>, <span style="color: #FF0000;">'-'</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF0000;">' '</span>, <span style="color: #FF0000;">'_'</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">+</span> <span style="color: #FF0000;">'.bak'</span><span style="color: #FF0000;">''</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF0000;">' WITH '</span> <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span> @_backup_type<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #FF0000;">'DIFFERENTIAL'</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'DIFFERENTIAL, '</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHEN</span> <span style="color: #FF0000;">'FULL'</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'INIT, '</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> <span style="color: #808080;">+</span> <span style="color: #0000FF;">CASE</span> @compression <span style="color: #0000FF;">WHEN</span> <span style="color: #000;">1</span> <span style="color: #0000FF;">THEN</span> <span style="color: #FF0000;">'COMPRESSION, '</span> <span style="color: #0000FF;">ELSE</span> <span style="color: #FF0000;">''</span> <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">+</span> <span style="color: #FF0000;">'CHECKSUM'</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @_print_only <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">PRINT</span> @<span style="color: #0000FF;">sql</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span> TRY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> <span style="color: #AF0000;">sp_executesql</span> @<span style="color: #0000FF;">sql</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> TRY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span> CATCH<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @err_msg <span style="color: #808080;">=</span> @_database_name <span style="color: #808080;">+</span> <span style="color: #FF0000;">' | '</span> <span style="color: #808080;">+</span> ERR<span style="color: #808080;">OR</span>_MESSAGE<span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">RAISERROR</span><span style="color: #808080;">&#40;</span>@err_msg, <span style="color: #000;">16</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> CATCH<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DELETE</span>&nbsp; <span style="color: #0000FF;">FROM</span> @database_list<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; database_name <span style="color: #808080;">=</span> @_database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> TRY<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span> CATCH<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">-- Envoie un email en cas d'erreur</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> dbo.<span style="color: #202020;">spasb_mail_send</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @_sender <span style="color: #808080;">=</span> <span style="color: #FF0000;">'it@myCompany.com'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @_recipients <span style="color: #808080;">=</span> <span style="color: #FF0000;">'it@myCompany.com'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @_subject <span style="color: #808080;">=</span> @mail_subject<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @_body <span style="color: #808080;">=</span> @err_msg<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span> CATCH<br />
<span style="color: #0000FF;">END</span></div></td></tr></tbody></table></div>
<p><span style="font-weight:bold;font-family:Verdana;font-size:18px">Remplacer l&rsquo;Agent SQL Server par le Planificateur de Tâches de Windows</span></p>
<p>Nous voilà à l&rsquo;étape finale : prendre des sauvegardes de base de données régulièrement. Pour ce faire, on peut tout à fait utiliser le <em>Planificateur de Tâches de Windows</em> : en effet, on peut appeler l&rsquo;utilitaire en ligne de commandes <em>SQLCMD</em> (la <a href="http://technet.microsoft.com/fr-fr/library/ms162773.aspx">documentation</a>, l&rsquo;<a href="http://technet.microsoft.com/fr-fr/library/ms180944.aspx">utilisation</a>, et un <a href="http://technet.microsoft.com/fr-fr/library/ms170207%28v=sql.105%29.aspx">exemple</a>), qui permet d&rsquo;interagir avec une instance SQL Server. Cet outil permet de passer en paramètre un script, d&rsquo;exécuter une requête, mais surtout d&rsquo;enregistrer la sortie dans un fichier. Cette dernière fonctionnalité facilite la tâche d&rsquo;investigation sur l&rsquo;échec d&rsquo;exécution de code.</p>
<p>Une fois l&rsquo;application <em>Planificateur de Tâches</em> démarrée, on créé une tâche assez simplement :</p>
<p><img src="http://i.imgur.com/ZSHAIHP.png" alt="" /></p>
<p>Une fois passé la première page ou nous nommons la tâche, un clic sur <em>Next</em> nous amène à la planification. Pour <em>Windows Server Update Services</em>, on peut estimer qu&rsquo;une sauvegarde complète par jour est suffisante. Évidemment, cela varie avec la criticité de l&rsquo;application. Nous spécifions donc une exécution quotidienne :</p>
<p><img src="http://i.imgur.com/QdAUdsn.png" alt="" /></p>
<p>Nous planifions l&rsquo;exécution à minuit et une minute :</p>
<p><img src="http://i.imgur.com/JXOESBU.png" alt="" /></p>
<p>Et nous choisissons de démarrer une application :</p>
<p><img src="http://i.imgur.com/ImwrMln.png" alt="" /></p>
<p>Dans la saisie texte <em>Program / Script</em>, nous spécifions l&rsquo;invite de commandes. En ce qui concerne les arguments, nous écrivons :</p>
<ul>
<li>Pour SQL Server 2008 :<br />
<code class="codecolorer dos default"><span class="dos">&quot;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE&quot;</span></code></li>
<li>Pour SQL Server 2012 :<br />
<code class="codecolorer dos default"><span class="dos">&quot;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\SQLCMD.EXE&quot;</span></code></li>
<li>Pour SQL Server 2014 :<br />
<code class="codecolorer dos default"><span class="dos">&quot;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn\SQLCMD.EXE&quot;</span></code></li>
</ul>
<p>En ce qui concerne les arguments, nous passons :</p>
<p><code class="codecolorer dos default"><span class="dos">sqlcmd -E -S WSUS -i &quot;C:\SQLServer\WSUSBackup.sql&quot; -o &quot;C:\SQLServerBackup\FullBackupLog.txt&quot;</span></code></p>
<p>Attention, la casse des options est importante.</p>
<ul>
<li>-E pour spécifier une connexion approuvée</li>
<li>-S : l&rsquo;instance SQL Server à laquelle on souhaite se connecter</li>
<li>-i : le chemin et le nom du fichier de script T-SQL</li>
<li>-o : le fichier qui capturera les libellés des messages d&rsquo;information, d&rsquo;avertissement ou d&rsquo;erreurs, le cas échéant</li>
</ul>
<p>Ce qui donne :</p>
<p><img src="http://i.imgur.com/6I12ozL.png" alt="" /></p>
<p>Un clic sur <em>Next</em> nous offre une fenêtre de résumé, et on peut valider le tout. Si l&rsquo;on souhaite ajouter des planifications ou modifier d&rsquo;autres options pour cette tâche, il suffit de cocher la case <em>Open the Properties dialog for this task when I click Finish</em>.</p>
<p>Nous créons ensuite un fichier <em>WSUSBackup.sql</em> dans un répertoire <em>C:\SQLServer\</em> sur la machine qui héberge l&rsquo;application WSUS. Ce fichier appelle la procédure stockée <em>DBA.dbo.databaseBackup_manage</em> comme suit :</p>
<p><code class="codecolorer text default"><span class="text">EXEC DBA.dbo.databaseBackup_manage 'FULL', NULL, '\\monPartageDeBackup\', 0</span></code></p>
<p>Et voilà nos sauvegardes de base de données en place.</p>
<p><span style="font-weight:bold;font-family:Verdana;font-size:18px">Utiliser PowerShell pour supprimer les fichiers de sauvegardes trop anciens</span></p>
<p>Dans la liste des actions de la tâche que nous venons de créer, nous pouvons en ajouter une qui aura :</p>
<ul>
<li>Pour programme : <code class="codecolorer text default"><span class="text">powershell</span></code></li>
<li>Pour arguments : <code class="codecolorer text default"><span class="text">-file &quot;C:\SQLServer\DeleteOldBackupFiles.ps1&quot;</span></code></li>
</ul>
<p>Le fichier <em>DeleteOldBackupFiles.ps1</em> contient la commande suivante, qui supprime tous les fichiers créés il y a plus de 7 jours, y compris dans les sous-dossiers du partage de backup (-Recurse) :</p>
<p><code class="codecolorer powershell default"><span class="powershell"><span style="color: #008080; font-weight: bold;">Get-ChildItem</span> <span style="color: #800000;">'\\monPartageDeBackup\'</span> <span style="color: #008080; font-style: italic;">-Recurse</span> <span style="color: pink;">|</span> <span style="color: #0000FF;">Where</span> <span style="color: #000000;">&#123;</span><span style="color: #000080;">$_</span>.CreationTime <span style="color: #FF0000;">-lt</span> <span style="color: #000000;">&#40;</span><span style="color: #008080; font-weight: bold;">Get-Date</span><span style="color: #000000;">&#41;</span>.AddDays<span style="color: #000000;">&#40;</span><span style="color: pink;">-</span><span style="color: #804000;">7</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#125;</span> <span style="color: pink;">|</span> <span style="color: #008080; font-weight: bold;">Remove-Item</span> <span style="color: #008080; font-style: italic;">-Force</span></span></code></p>
<p>Par défaut, PowerShell ne permet pas l&rsquo;exécution de scripts. Pour l&rsquo;autoriser, il faut démarrer l&rsquo;interface PowerShell, et exécuter <code class="codecolorer powershell default"><span class="powershell"><span style="color: #008080; font-weight: bold;">Set-ExecutionPolicy</span> RemoteSigned</span></code> (en accord avec votre Administrateur Systèmes !).</p>
<p>Retenons également que les statistiques de colonne et d&rsquo;index de la base de données supportant WSUS ne sont pas maintenues. Ce sera probablement suffisant pour générer une lenteur après quelques mois d&rsquo;exploitation, dont votre Administrateur Systèmes vous demandera l&rsquo;origine <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>ElSüket.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Auditer les processus bloqués : l&#8217;événement blocked process report</title>
		<link>https://blog.developpez.com/elsuket/p12049/snippets/auditer-les-processus-bloques-levenement-blocked-process-report</link>
		<comments>https://blog.developpez.com/elsuket/p12049/snippets/auditer-les-processus-bloques-levenement-blocked-process-report#comments</comments>
		<pubDate>Sat, 15 Jun 2013 10:46:31 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Non documenté]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Utilitaires]]></category>
		<category><![CDATA[%%lockres%%]]></category>
		<category><![CDATA[blocage]]></category>
		<category><![CDATA[blocked process report]]></category>
		<category><![CDATA[blocked process threshold]]></category>
		<category><![CDATA[blocking]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[événements étendus]]></category>
		<category><![CDATA[Extended Events]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[lock]]></category>
		<category><![CDATA[lock monitor]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[sp_configure]]></category>
		<category><![CDATA[timeout]]></category>
		<category><![CDATA[verrou]]></category>
		<category><![CDATA[waitresource]]></category>
		<category><![CDATA[XE]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=604</guid>
		<description><![CDATA[SQL Server 2005 a introduit un évènement capturable par SQL Profiler et par les Notifications d’évènements, qui permet de retrouver les processus qui ont été bloqués. Avec la sortie de SQL Server 2008 et l&#8217;introduction des Évènements Étendus, il nous &#8230; <a href="https://blog.developpez.com/elsuket/p12049/snippets/auditer-les-processus-bloques-levenement-blocked-process-report">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>SQL Server 2005 a introduit un évènement capturable par <em><a href="http://elsuket.developpez.com/tutoriels/sqlserveur/fichier-trace-cote-serveur/">SQL Profiler</a></em> et par les <em>Notifications d’évènements</em>, qui permet de retrouver les processus qui ont été bloqués. Avec la sortie de SQL Server 2008 et l&rsquo;introduction des <em><a href="http://elsuket.developpez.com/tutoriels/sqlserveur/EvenementsEtendusSQLServer2008/">Évènements Étendus</a></em>, il nous est également possible de capturer cet évènement.</p>
<p>Dans cet article, je vous propose de voir comment paramétrer SQL Server pour capturer cet évènement, puis de vous aider à interpréter le document XML qui décrit la situation de blocage.<br />
<span id="more-604"></span><br />
Toute exécution de requête résulte en l&rsquo;acquisition de verrous, dont la granularité (ligne, page, clé, partition, table, base de données, ou encore et plus rarement compilation) et le mode (partagé, exclusif, de mise à jour, ou d&rsquo;intention) varient. Le verrouillage de ressources est une opération de base pour le moteur de stockage de tout moteur de bases de données SQL, qui garantit l&rsquo;intégrité de la base de données à travers toutes les opérations de manipulation de données que celle-ci supporte. Cependant, il arrive que lorsqu&rsquo;un processus a posé un verrou sur une ressource, d&rsquo;autres processus doivent simultanément accéder à cette même ressource : ces processus sont alors bloqués. Comme il est possible que le processus bloquant ne libère ledit verrou qu&rsquo;après une durée relativement longue, les effets possibles d&rsquo;une telle situation sur nos applications peuvent aller de requêtes dont la durée d&rsquo;exécution est élevée jusqu&rsquo;à l&rsquo;expiration du délai d&rsquo;attente d&rsquo;une réponse pour l&rsquo;exécution d&rsquo;un requête : le fameux <em>timeout</em>.</p>
<p>Il est néanmoins possible, à l&rsquo;aide d&rsquo;une trace SQL Profiler ou des Évènements Étendus, de capturer ces situations, qui sont décrites par un document XML.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Configurer l&rsquo;instance SQL Server</strong></p>
<p>Le seuil de durée de blocage à partir de laquelle on souhaite capturer un tel évènement est configurable à l&rsquo;aide de l&rsquo;option d&rsquo;instance <em>blocked process threshold</em>. On accède à ce paramètre :</p>
<p>&#8211; soit à l&rsquo;aide de <em>SQL Server Management Studio</em> (SSMS), après un clic-droit sur l&rsquo;instance dans l&rsquo;Explorateur d&rsquo;Objets (F8), et avoir choisi l&rsquo;option <em>Propriétés</em> :</p>
<p><img src="http://img855.imageshack.us/img855/6901/gq2.png" alt="" /></p>
<p>&#8211; soit à l&rsquo;aide de la procédure stockée système <em>sp_configure</em> :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">configurations</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">LIKE</span> <span style="color: #FF0000;">'%block%'</span></div></td></tr></tbody></table></div>
<p><img src="http://img836.imageshack.us/img836/9273/zx81.png" alt="" /></p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Activation de la modification d'options d'instance avancées</span><br />
<span style="color: #0000FF;">EXEC</span> sys.<span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'show advanced options'</span>, <span style="color: #000;">1</span> <br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO<br />
<br />
<span style="color: #008080;">-- Configuration du seuil de durée de blocage à 5 secondes</span><br />
<span style="color: #0000FF;">EXEC</span> sys.<span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'blocked process threshold'</span>, <span style="color: #000;">5</span><br />
GO <br />
<span style="color: #0000FF;">RECONFIGURE</span>; <br />
GO<br />
<br />
<span style="color: #008080;">-- Désactivation de la modification d'options d'instance avancées</span><br />
<span style="color: #0000FF;">EXEC</span> sys.<span style="color: #AF0000;">sp_configure</span> <span style="color: #FF0000;">'show advanced options'</span>, <span style="color: #000;">0</span><br />
GO<br />
<span style="color: #0000FF;">RECONFIGURE</span><br />
GO</div></td></tr></tbody></table></div>
<p>La console de SSMS affiche, à l&rsquo;exécution de ce lot de requêtes :</p>
<p><img src="http://img28.imageshack.us/img28/4259/1ug.png" alt="" /></p>
<p>Veillez à ne pas mettre un seuil trop bas : sans cela, on aurait le processus d&rsquo;arrière plan LOCK MONITOR qui s&rsquo;exécuterait constamment. Or ce dernier, qui est aussi en charge de détecter les deadlocks, est gourmand en ressources CPU. En s&rsquo;exécutant fréquemment, il pourrait donc impacter négativement les performances générales de l&rsquo;instance SQL Server. D&rsquo;un autre côté, 5 secondes est une durée très longue sur une base de données qui supporte une charge de travail OLTP conséquente. On trouve ce processus avec la requête suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; session_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , status<br />
&nbsp; &nbsp; &nbsp; &nbsp; , command<br />
&nbsp; &nbsp; &nbsp; &nbsp; , wait_type<br />
&nbsp; &nbsp; &nbsp; &nbsp; , wait_time<br />
&nbsp; &nbsp; &nbsp; &nbsp; , last_wait_type<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_requests</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; command <span style="color: #808080;">=</span> <span style="color: #FF0000;">'LOCK MONITOR'</span></div></td></tr></tbody></table></div>
<p>Si l&rsquo;on exécute maintenant cette requête de façon répétée, on voit que la valeur de la colonne <em>wait_time</em> croit jusqu&rsquo;à atteindre 5000, mais ne dépasse jamais cette valeur : cette colonne affiche sa valeur en millisecondes, et montre bien que le processus cherche les processus bloqués toutes les 5 secondes.</p>
<p>Il faut aussi noter qu&rsquo;avec cette configuration, si un processus reste bloqué 15 secondes, l’évènement sera généré 3 fois pour la même situation de blocage.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Capture avec SQL Profiler</strong></p>
<p>Une fois cela fait, nous démarrons SQL Profiler, et dans l&rsquo;onglet de sélection des évènements, dans la catégorie <em>Errors and Warnings</em> (et non pas dans la catégorie <em>Locks</em>), nous trouvons l’évènement <em>Blocked process report</em> :</p>
<p><img src="http://img546.imageshack.us/img546/5205/hptk.png" alt="" /></p>
<p>Nous configurons l’évènement comme suit, où le champ <em>TextData</em> contiendra le document XML décrivant la situation de blocage :</p>
<p><img src="http://img19.imageshack.us/img19/2305/n66.png" alt="" /></p>
<p><strong>N.B.</strong> : N&rsquo;oubliez pas le champ <em>Mode</em>, qui procure le type de verrou acquis.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Capture avec les Évènements Étendus (XE)</strong></p>
<p>Pour les lecteurs qui n&rsquo;ont pas encore eu le temps de se familiariser avec cette fonctionnalité, qui est vouée au remplacement futur de SQL Profiler, et dont la puissance en fait mon outil de diagnostic favori, vous pouvez vous aider de l&rsquo;<a href="http://elsuket.developpez.com/tutoriels/sqlserveur/EvenementsEtendusSQLServer2008/">article</a> que j&rsquo;ai publié sur le sujet.</p>
<p>Si l&rsquo;on souhaite capturer en permanence toute situation de blocage, l&rsquo;avantage revient à XE, puisqu&rsquo;on peut stocker ces évènements dans une cible dite anneau de mémoire (ring buffer). Cette structure consomme très peu de mémoire et fonctionne à l&rsquo;image d&rsquo;un FIFO : lorsqu&rsquo;il est plein, la capture d&rsquo;un nouvel évènement donne lieu à l&rsquo;éviction du plus vieil évènement pour le stockage de celui-ci. Avec SQL Profiler, il est nécessaire de mettre en place une trace côté serveur et de gérer le fichier de trace et l&rsquo;espace disque. En revanche, une fois que l&rsquo;on a démarré la session XE, on peut &laquo;&nbsp;l&rsquo;oublier&nbsp;&raquo;.</p>
<p>Pour les lecteurs familiers de XE et de Profiler, sachez que le document XML produit par ces deux fonctionnalités pour un même évènement de blocage est identique, ce qui n&rsquo;est pas le cas avec les deadlocks (XE produit un document XML mal formé, qui rend impossible son enregistrement en document de type .xdl en vue de son interprétation graphique dans SSMS).</p>
<p>La définition d&rsquo;une telle session est simple :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Définition de la session</span><br />
<span style="color: #0000FF;">CREATE</span> EVENT <span style="color: #0000FF;">SESSION</span> blocked_process_report_RB <span style="color: #0000FF;">ON</span> SERVER<br />
<span style="color: #0000FF;">ADD</span> EVENT sqlserver.<span style="color: #202020;">blocked_process_report</span><br />
<span style="color: #0000FF;">ADD</span> TARGET package0.<span style="color: #202020;">ring_buffer</span> <span style="color: #808080;">&#40;</span><span style="color: #0000FF;">SET</span> MAX_MEM<span style="color: #808080;">OR</span>Y <span style="color: #808080;">=</span> <span style="color: #000;">4096</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">WITH</span> <span style="color: #808080;">&#40;</span>MAX_DISPATCH_LATENCY <span style="color: #808080;">=</span> <span style="color: #000;">5</span> SECONDS<span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #008080;">-- Démarrage de la session</span><br />
<span style="color: #0000FF;">ALTER</span> EVENT <span style="color: #0000FF;">SESSION</span> blocked_process_report_RB <span style="color: #0000FF;">ON</span> SERVER<br />
<span style="color: #0000FF;">STATE</span> <span style="color: #808080;">=</span> <span style="color: #0000FF;">START</span><br />
<br />
<span style="color: #008080;">-- Vérification</span><br />
<span style="color: #0000FF;">SELECT</span>&nbsp; name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , create_time<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_xe_sessions</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">=</span> <span style="color: #FF0000;">'blocked_process_report_RB'</span></div></td></tr></tbody></table></div>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Le test</strong></p>
<p>Pour l&rsquo;exemple, nous avons la trace SQL Profiler et la session XE ci-dessus actifs.<br />
Nous créons la table suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> blocked_process_report_test<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cle <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">16</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">CONSTRAINT</span> UQ_blocked_process_report_test <span style="color: #0000FF;">UNIQUE</span> <span style="color: #0000FF;">CLUSTERED</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , valeur <span style="color: #0000FF;">tinyint</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span></div></td></tr></tbody></table></div>
<p>Puis, dans une première fenêtre de requête (A) sous SSMS, nous ajoutons la ligne suivante, sans valider la transaction :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BEGIN</span> <span style="color: #0000FF;">TRANSACTION</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INSERT</span>&nbsp; <span style="color: #0000FF;">INTO</span> dbo.<span style="color: #202020;">blocked_process_report_test</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cle<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , valeur<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">VALUES</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">'TEST'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #000;">12</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span></div></td></tr></tbody></table></div>
<p>Dans une seconde fenêtre de requête (B), nous exécutons :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">UPDATE</span>&nbsp; dbo.<span style="color: #202020;">blocked_process_report_test</span><br />
<span style="color: #0000FF;">SET</span> &nbsp; &nbsp; valeur <span style="color: #808080;">=</span> <span style="color: #000;">15</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; cle <span style="color: #808080;">=</span> <span style="color: #FF0000;">'TEST'</span></div></td></tr></tbody></table></div>
<p>Ceci fait que la requête B doit attendre que la requête A soit terminée pour réaliser l&rsquo;UPDATE, ce qui ne peut se faire que si l&rsquo;on valide (COMMIT) ou annule (ROLLBACK) la transaction : nous ne le faisons pas ici, pour l&rsquo;exemple. Nous laissons aussi la requête B s&rsquo;exécuter 10 secondes, de façon à bien voir que l’évènement est capturé deux fois pour la même situation de blocage.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Ce que capture SQL Profiler</strong></p>
<p>L&rsquo;interface affiche bien deux captures de l’évènement :</p>
<p><img src="http://img705.imageshack.us/img705/8171/5kt.png" alt="" /></p>
<p>Notez que les valeurs pour la colonne <em>Duration</em> sont données ici en microsecondes : on voit donc qu&rsquo;il y a un léger décalage entre la détection du blocage et sa capture. Toutes les informations dont nous avons besoin sont donc sous nos yeux: la ressource à la source de la situation de blocage, ainsi que les requêtes impliquées dans celle-ci.</p>
<p>Il est possible de charger le fichier de trace dans une table à l&rsquo;aide de la fonction <a href="http://msdn.microsoft.com/fr-fr/library/ms188425.aspx">sys.fn_trace_gettable()</a>. Cela permet l&rsquo;écriture d&rsquo;une requête utilisant les méthodes SQLXML, qui extrait directement les informations intéressantes de chaque document XML. La requête est similaire à celle que je donne dans la section suivante.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Ce que capture la session XE</strong></p>
<p>Ici il nous est nécessaire d&rsquo;écrire une requête faisant appel aux fonctions SQLXML pour dépouiller le document XML sans se fatiguer :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #FF00FF;">DATEADD</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">hour</span>, <span style="color: #FF00FF;">DATEDIFF</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">hour</span>, <span style="color: #FF00FF;">GETUTCDATE</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span>, <span style="color: #FF00FF;">GETDATE</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span>, doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/@timestamp)[1]'</span>, <span style="color: #FF0000;">'datetime'</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> log_date_time<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;transaction_id&quot;]/value)[1]'</span>, <span style="color: #FF0000;">'bigint'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> transaction_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;database_name&quot;]/value)[1]'</span>, <span style="color: #FF0000;">'nvarchar(128)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> database_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;duration&quot;]/value)[1]'</span>, <span style="color: #FF0000;">'int'</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">/</span> <span style="color: #000;">1000</span> <span style="color: #0000FF;">AS</span> duration_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;resource_owner_type&quot;]/text)[1]'</span>, <span style="color: #FF0000;">'varchar(10)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> resource_owner_type<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;lock_mode&quot;]/text)[1]'</span>, <span style="color: #FF0000;">'varchar(10)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> lock_mode<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;blocked_process&quot;]/value/blocked-process-report/blocked-process/process/@waitresource)[1]'</span>, <span style="color: #FF0000;">'varchar(max)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> wait_resource<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;blocked_process&quot;]/value/blocked-process-report/blocked-process/process/@isolationlevel)[1]'</span>, <span style="color: #FF0000;">'varchar(max)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> blocked_tran_iso_level<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;blocked_process&quot;]/value/blocked-process-report/blocking-process/process/@isolationlevel)[1]'</span>, <span style="color: #FF0000;">'varchar(max)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> blocking_tran_iso_level<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;blocked_process&quot;]/value/blocked-process-report/blocked-process/process/inputbuf)[1]'</span>, <span style="color: #FF0000;">'varchar(max)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> blocked_statement<br />
&nbsp; &nbsp; &nbsp; &nbsp; , doc.<span style="color: #0000FF;">value</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'(event/data[@name=&quot;blocked_process&quot;]/value/blocked-process-report/blocking-process/process/inputbuf)[1]'</span>, <span style="color: #FF0000;">'varchar(max)'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> blocking_statement<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; <span style="color: #808080;">&#40;</span> &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; D.<span style="color: #202020;">n</span>.<span style="color: #202020;">query</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'.'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> doc<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span>target_data <span style="color: #0000FF;">AS</span> xml<span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">data</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">dm_xe_sessions</span> <span style="color: #0000FF;">AS</span> S &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">dm_xe_session_targets</span> <span style="color: #0000FF;">AS</span> ST<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> S.<span style="color: #202020;">address</span> <span style="color: #808080;">=</span> ST.<span style="color: #202020;">event_session_address</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; S.<span style="color: #202020;">name</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'blocked_process_report_RB'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ST.<span style="color: #202020;">target_name</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'ring_buffer'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> sub<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">CROSS</span> APPLY &nbsp; &nbsp; <span style="color: #0000FF;">data</span>.<span style="color: #202020;">nodes</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'RingBufferTarget/event'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> D<span style="color: #808080;">&#40;</span>n<span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> T</div></td></tr></tbody></table></div>
<p>La capture d&rsquo;écran du résultat a été coupée en deux pour faciliter un peu la lecture :</p>
<p><img src="http://img827.imageshack.us/img827/7796/91d.png" alt="" /></p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Interprétation du résultat</strong></p>
<p>Notre intérêt dans l&rsquo;interprétation de ce document se portera sur la propriété waitresource, que l&rsquo;on peut décrypter à l&rsquo;aide de la <a href="http://support.microsoft.com/kb/224453">documentation</a> (Voir la section <strong><em>Waitresource</em></strong>).</p>
<p>Ici, waitresource est : KEY: 5:72057594039107584 (2158b2b5a6d5), ce qui signifie :</p>
<p>&#8211; Database ID : 5<br />
&#8211; Partition ID : 72057594039107584<br />
&#8211; (2158b2b5a6d5) : le hash de la clé d&rsquo;index</p>
<p>Sur ce dernier point, il faut savoir que SQL Server utilise le hash, stocké sur 6 octets, de la clé de l&rsquo;index qui supporte la requête. Ceci conduit SQL Server à générer des valeurs de hash identiques pour des valeurs de clé différentes, ce qui peut causer d&rsquo;autre problèmes de concurrence d&rsquo;accès. C&rsquo;est une raison de plus pour choisir des clés d&rsquo;index les plus &laquo;&nbsp;étroites&nbsp;&raquo; possible, de façon à éviter ce type de collisions.</p>
<p>Voyons comment retrouver la ressource qui a été verrouillée :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">USE</span> ELSUKET<br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; O.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> table_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , I.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> index_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , P.<span style="color: #202020;">partition_number</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , P.<span style="color: #0000FF;">rows</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">partitions</span> <span style="color: #0000FF;">AS</span> p<br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">objects</span> <span style="color: #0000FF;">AS</span> O<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> O.<span style="color: #FF00FF;">object_id</span> <span style="color: #808080;">=</span> P.<span style="color: #FF00FF;">object_id</span><br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">indexes</span> <span style="color: #0000FF;">AS</span> I<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> P.<span style="color: #FF00FF;">object_id</span> <span style="color: #808080;">=</span> I.<span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> P.<span style="color: #202020;">index_id</span> <span style="color: #808080;">=</span> I.<span style="color: #202020;">index_id</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.<span style="color: #202020;">partition_id</span> <span style="color: #808080;">=</span> <span style="color: #000;">72057594039107584</span></div></td></tr></tbody></table></div>
<p><img src="http://img818.imageshack.us/img818/5617/zsbe.png" alt="" /></p>
<p>Voyons maintenant comment retrouver la clé qui a été utilisée :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; dbo.<span style="color: #202020;">blocked_process_report_test</span> <span style="color: #0000FF;">WITH</span><span style="color: #808080;">&#40;</span><span style="color: #0000FF;">INDEX</span> <span style="color: #808080;">=</span> UQ_blocked_process_report_test<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; <span style="color: #808080;">%%</span>lockres<span style="color: #808080;">%%</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'(2158b2b5a6d5)'</span></div></td></tr></tbody></table></div>
<p><img src="http://img268.imageshack.us/img268/5628/5xt.png" alt="" /></p>
<p>La fonction %%lockres%% n&rsquo;est pas documentée : il est donc recommandé de l&rsquo;utiliser avec parcimonie. La même méthodologie est utilisable dans le diagnostic des deadlocks.</p>
<p>Bon déblocage à tous !</p>
<p>ElSüket.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vous êtes sûr d&#8217;avoir les BACKUP avec CHECKSUM parce que vous utilisez l&#8217;option COMPRESSION ? Vérifiez une seconde fois !</title>
		<link>https://blog.developpez.com/elsuket/p11990/snippets/backup_checksum_compression</link>
		<comments>https://blog.developpez.com/elsuket/p11990/snippets/backup_checksum_compression#comments</comments>
		<pubDate>Sun, 26 May 2013 13:32:34 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[BACKUP]]></category>
		<category><![CDATA[CHECKSUM]]></category>
		<category><![CDATA[COMPRESSION]]></category>
		<category><![CDATA[DBCC]]></category>
		<category><![CDATA[DBCC IND]]></category>
		<category><![CDATA[DBCC PAGE]]></category>
		<category><![CDATA[maintenance plan]]></category>
		<category><![CDATA[plan de maintenance]]></category>
		<category><![CDATA[sauvegarde]]></category>
		<category><![CDATA[sys.dm_db_database_page_allocations]]></category>
		<category><![CDATA[sys.messages]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=427</guid>
		<description><![CDATA[Après avoir vu comment compresser toutes les sauvegardes de base de données dès SQL Server 2008, il est intéressant de trouver comment activer l&#8217;option CHECKSUM de l&#8217;instruction BACKUP. A ce sujet, la documentation indique : Indique que l&#8217;opération de sauvegarde &#8230; <a href="https://blog.developpez.com/elsuket/p11990/snippets/backup_checksum_compression">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Après avoir vu comment <a href="http://blog.developpez.com/elsuket/p9040/moteur-de-base-de-donnees-sql-server/compresser_tous_les_backups_sans_modifie_2008">compresser toutes les sauvegardes de base de données</a> dès SQL Server 2008, il est intéressant de trouver comment activer l&rsquo;option CHECKSUM de l&rsquo;instruction BACKUP.</p>
<p>A ce sujet, la documentation indique :</p>
<blockquote><p> Indique que l&rsquo;opération de sauvegarde vérifie dans chaque page les informations de somme de contrôle et de page endommagée, si elles sont activées et disponibles, et génère une somme de contrôle pour l&rsquo;ensemble de la sauvegarde. <strong>Ceci est le comportement par défaut pour une sauvegarde compressée</strong>.</p></blockquote>
<p>Vérifions donc si cela est vrai : nous allons créer une base de données de test, et nous allons corrompre une de ses pages afin de vérifier le comportement de la sauvegarde. En effet, l&rsquo;option CHECKSUM permet de détecter la corruption de données au moment de la sauvegarde. Cela permet en plus de ne pas se retrouver dans l’inconfortable situation de devoir restaurer une base de données à partir d&rsquo;un fichier de sauvegarde corrompu.<br />
<span id="more-427"></span><br />
<img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>La vérification de l&rsquo;intégrité des pages au niveau de la base de données</strong></p>
<p>Par défaut, lorsqu&rsquo;on crée une nouvelle base de données sous SQL Server 2005 et suivants, la vérification de l&rsquo;intégrité des pages lues à partir du disque se fait à l&rsquo;aide d&rsquo;une somme de contrôle. Celle-ci est calculée à partir du contenu de la page, puis écrite dans l&rsquo;en-tête de celle-ci au moment de l&rsquo;écriture sur disque. Lorsque la page est ensuite lue à partir du disque, la somme de contrôle est recalculée, puis comparée à celle qui est dans l&rsquo;en-tête de la page : si les valeurs sont identiques, alors la page est intègre; à l&rsquo;inverse, on obtient l&rsquo;erreur 824, qui est écrite à la fois dans les journaux de SQL Server et dans le journal d&rsquo;événements de Windows.<br />
Enfin lorsqu&rsquo;on restaure une base de données qui a été créée sous une version antérieure à 2005, il est important de changer cette option de TORN_PAGE_DETECTION à PAGE_VERIFY, car la première est conservée par défaut. L&rsquo;option TORN_PAGE_DETECTION stocke deux bits pour chaque secteur de 512 octets de toute page, dont la taille est 8192 octets. De la même façon, ces 16 * 2 bits sont stockés dans l&rsquo;en-tête de la page, et comparés à la relecture de la page. Comme cette option est moins stricte que CHECKSUM, il est donc recommandé d&rsquo;utiliser cette dernière option.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Le test</strong></p>
<p>Nous créons donc la base de données sous SQL Server 2012, puis nous vérifions l&rsquo;option du contrôle de l&rsquo;intégrité des pages :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM;<br />
GO<br />
<br />
<span style="color: #0000FF;">USE</span> TEST_CHECKSUM<br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , page_verify_option_desc<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">databases</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">=</span> <span style="color: #FF0000;">'TEST_CHECKSUM'</span></div></td></tr></tbody></table></div>
<p><img src="http://img843.imageshack.us/img843/1872/backupchecksum01.png" alt="" /></p>
<p>Nous créons ensuite une table dans cette base de données, à laquelle nous ajoutons une ligne :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">USE</span> TEST_CHECKSUM<br />
GO<br />
<br />
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> test_backup_checksum<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; id <span style="color: #0000FF;">tinyint</span> <span style="color: #0000FF;">IDENTITY</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , nom <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">16</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #0000FF;">INSERT</span> <span style="color: #0000FF;">INTO</span> dbo.<span style="color: #202020;">test_backup_checksum</span> <span style="color: #808080;">&#40;</span>nom<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">VALUES</span> <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'test_checksum'</span><span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; dbo.<span style="color: #202020;">test_backup_checksum</span></div></td></tr></tbody></table></div>
<p>Nous forçons ensuite l&rsquo;écriture des pages sur disque, à l&rsquo;aide de l&rsquo;instruction <a href="http://blog.developpez.com/elsuket/p9529/moteur-de-base-de-donnees-sql-server/lazywriter_checkpoint_aamp_ghost_cleanup">CHECKPOINT</a>, puis nous vidons le cache de données, de sorte que la prochaine fois que nous exécuterons une requête sur cette table, ses pages seront lues à partir du disque, à l&rsquo;aide de l&rsquo;instruction DBCC DROPCLEANBUFFERS.</p>
<p><strong>N.B. : </strong>N&rsquo;exécutez <strong>JAMAIS</strong> une instruction non-documentée sur une base de données qui sert une charge de production. Si tel devait être le cas, je ne peux <strong>en aucun cas être tenu pour responsable des conséquences. Vous devez limiter strictement l&rsquo;usage de cette instruction aux environnements de test</strong>.</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CHECKPOINT</span><br />
GO<br />
<br />
<span style="color: #0000FF;">DBCC</span> DROPCLEANBUFFERS<br />
GO</div></td></tr></tbody></table></div>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>L&rsquo;instruction DBCC IND, ou la DMF sys.dm_db_database_page_allocations</strong></p>
<p>Encore deux options d&rsquo;exploration de la mécanique interne de SQL Server, qui permettent de lister les pages d&rsquo;une table ou d&rsquo;un index, et qui ne sont pas documentées. Voici le prototype d&rsquo;utilisation de ces deux alternatives :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">DBCC</span> <span style="color: #808080;">IN</span>D <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TEST_CHECKSUM'</span>, <span style="color: #FF0000;">'dbo.test_backup_checksum'</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #008080;">-- le dernier argument est l'index id</span><br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; allocated_page_file_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocated_page_page_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocated_page_iam_file_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocated_page_iam_page_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , index_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , partition_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocation_unit_type_desc <span style="color: #0000FF;">AS</span> iam_chain_type<br />
&nbsp; &nbsp; &nbsp; &nbsp; , page_type_desc<br />
&nbsp; &nbsp; &nbsp; &nbsp; , page_level<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rowset_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , next_page_file_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , next_page_page_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; , previous_page_file_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; , previous_page_page_id<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_db_database_page_allocations</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF00FF;">DB_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TEST_CHECKSUM'</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">OBJECT_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'dbo.test_backup_checksum'</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #000;">0</span> <span style="color: #008080;">-- index id : 0 pour un tas, 1 pour un index cluster, plus grand pour un index non-cluster</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #808080;">NULL</span> <span style="color: #008080;">-- partition id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF0000;">'DETAILED'</span> <span style="color: #008080;">-- niveau de détail</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; is_allocated <span style="color: #808080;">=</span> <span style="color: #000;">1</span>;</div></td></tr></tbody></table></div>
<p>On remarque tout de suite que la DMF produit bien plus d&rsquo;informations que l&rsquo;instruction DBCC (nous ne donnons pas ici toutes les colonnes), et que ses arguments sont similaires à la DMF <em>sys.dm_db_index_physical_stats</em>.</p>
<p><img src="http://img689.imageshack.us/img689/1618/backupchecksum02.png" alt="" /></p>
<p>Voyons donc ce que contient la page 272, puisque c&rsquo;est elle qui contient les données (page_type_desc = DATA_PAGE) :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Activation de la sortie de la commande DBCC</span><br />
<span style="color: #0000FF;">DBCC</span> TRACEON <span style="color: #808080;">&#40;</span><span style="color: #000;">3604</span><span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #008080;">-- DBCC PAGE ([database_name_or_id], [file_id], [page_id], [option])</span><br />
<span style="color: #008080;">-- option = 0 montre seulement l'en-tête de la page</span><br />
<span style="color: #0000FF;">DBCC</span> PAGE <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TEST_CHECKSUM'</span>, <span style="color: #000;">1</span>, <span style="color: #000;">272</span>, <span style="color: #000;">0</span><span style="color: #808080;">&#41;</span>;<br />
GO</div></td></tr></tbody></table></div>
<p>Nous obtenons :</p>
<blockquote><p>PAGE: (1:272)</p>
<p>BUFFER:</p>
<p>BUF @0x000000027407BB80</p>
<p>bpage = 0x00000002649F4000          bhash = 0x0000000000000000          bpageno = (1:272)<br />
bdbid = 8                           breferences = 0                     bcputicks = 0<br />
bsampleCount = 0                    bUse1 = 33295                       bstat = 0x9<br />
blog = 0x2121215a                   bnext = 0x0000000000000000          </p>
<p>PAGE HEADER:</p>
<p>Page @0x00000002649F4000</p>
<p>m_pageId = (1:272)                  m_headerVersion = 1                 m_type = 1<br />
m_typeFlagBits = 0x0                m_level = 0                         <strong>m_flagBits = 0x8200</strong><br />
m_objId (AllocUnitId.idObj) = 84    m_indexId (AllocUnitId.idInd) = 256<br />
Metadata: AllocUnitId = 72057594043432960<br />
Metadata: PartitionId = 72057594039042048                                Metadata: IndexId = 0<br />
Metadata: ObjectId = 245575913      m_prevPage = (0:0)                  m_nextPage = (0:0)<br />
pminlen = 5                         m_slotCnt = 1                       m_freeCnt = 8069<br />
m_freeData = 121                    m_reservedCnt = 0                   m_lsn = (30:345:30)<br />
m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0<br />
<strong>m_tornBits = 1209479828</strong>             DB Frag ID = 1</p></blockquote>
<p>Si nous nous en référons à la <a href="http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-page/">documentation donnée par Paul Randal</a>, nous avons bien :</p>
<p>&#8211; <em>m_flagBits = 0x8200</em>, qui indique que l&rsquo;intégrité de la page est vérifiée par somme de contrôle<br />
&#8211; <em>m_tornBits</em> est la somme de contrôle de cette page</p>
<p>Nous allons maintenant mettre la base de données hors-ligne, puis éditer le fichier de données avec un éditeur hexadécimal, de façon à vérifier si SQL Server vérifie bien la somme à la lecture de la page :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">DATABASE</span> <span style="color: #0000FF;">SET</span> OFFL<span style="color: #808080;">IN</span>E<br />
GO</div></td></tr></tbody></table></div>
<p>En ce qui concerne la lecture en hexadécimal, j&rsquo;utilise le logiciel <a href="http://www.chmaas.handshake.de/delphi/freeware/xvi32/xvi32.htm">Hex Editor XVI32</a>. Une fois l&rsquo;outil ouvert en tant qu&rsquo;administrateur, il suffit de chercher la chaîne que nous avons ajouté comme ligne dans la table, en suivant le menu <em>Search</em> / <em>Find</em> :</p>
<p><img src="http://img850.imageshack.us/img850/1565/backupchecksum03.png" alt="" /></p>
<p>Un clic sur le bouton OK nous amène directement à l&rsquo;emplacement, où l&rsquo;on est alors libre de changer la chaîne, où j&rsquo;ai changé le &laquo;&nbsp;k&nbsp;&raquo; en &laquo;&nbsp;d&nbsp;&raquo;, puis sauvé le fichier :</p>
<p><img src="http://img833.imageshack.us/img833/341/backupchecksum04.png" alt="" /></p>
<p>Nous remettons la base de données en ligne :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">SET</span> ONL<span style="color: #808080;">IN</span>E<br />
GO</div></td></tr></tbody></table></div>
<p>Aucun problème. Exécutons un SELECT * FROM dbo.test_backup_checksum. Nous obtenons le message suivant :</p>
<blockquote><p>
Msg 824, Level 24, State 2, Line 1<br />
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0xf9ec3284; actual: 0xfe6c3284). It occurred during a read of page (1:228) in database ID 7 at offset 0x000000001c8000 in file &lsquo;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TEST_CHECKSUM.mdf&rsquo;.  Additional messages in the SQL Server error log or system event log may provide more detail. This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.</p></blockquote>
<p>Prenons maintenant une sauvegarde de cette base de données, avec COMPRESSION, mais sans spécifier l&rsquo;option CHECKSUM :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM.bak'</span><br />
<span style="color: #0000FF;">WITH</span> COMPRESSION<br />
GO</div></td></tr></tbody></table></div>
<p>Aucun problème : nous obtenons :</p>
<blockquote><p>Processed 280 pages for database &lsquo;TEST_CHECKSUM&rsquo;, file &lsquo;TEST_CHECKSUM&rsquo; on file 1.<br />
Processed 3 pages for database &lsquo;TEST_CHECKSUM&rsquo;, file &lsquo;TEST_CHECKSUM_log&rsquo; on file 1.<br />
BACKUP DATABASE successfully processed 283 pages in 0.468 seconds (4.709 MB/sec).</p></blockquote>
<p>Voyons ce que contient la table d&rsquo;historique des sauvegardes :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #FF00FF;">user_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , backup_start_date<br />
&nbsp; &nbsp; &nbsp; &nbsp; , recovery_model<br />
&nbsp; &nbsp; &nbsp; &nbsp; , has_backup_checksums<br />
&nbsp; &nbsp; &nbsp; &nbsp; , is_damaged<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; msdb.<span style="color: #202020;">dbo</span>.<span style="color: #202020;">backupset</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; database_name <span style="color: #808080;">=</span> <span style="color: #FF0000;">'TEST_CHECKSUM'</span></div></td></tr></tbody></table></div>
<p><img src="http://img195.imageshack.us/img195/6295/backupchecksum05.png" alt="" /></p>
<p>On obtient un résultat similaire avec l&rsquo;instruction RESTORE HEADERONLY (colonnes <em>HasBackupChecksums</em> et <em>IsDamaged</em> toutes deux à zéro) :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">RESTORE</span> HEADERONLY<br />
<span style="color: #0000FF;">FROM</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM.bak'</span></div></td></tr></tbody></table></div>
<p>Le fichier de sauvegarde ne dispose pas de la somme de contrôle, et n&rsquo;est pas marqué comme endommagé. Pourtant nous avons bien corrompu le fichier de données, et nous ne pouvons pas lire la table que nous avons peuplé auparavant !</p>
<p>Voyons ce que produit la même instruction, avec l&rsquo;option CHECKSUM :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM_CC.bak'</span><br />
<span style="color: #0000FF;">WITH</span> COMPRESSION, <span style="color: #FF00FF;">CHECKSUM</span><br />
GO</div></td></tr></tbody></table></div>
<blockquote><p>Msg 3043, Level 16, State 1, Line 1<br />
BACKUP &lsquo;TEST_CHECKSUM&rsquo; detected an error on page (1:228) in file &lsquo;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TEST_CHECKSUM.mdf&rsquo;.<br />
Msg 3013, Level 16, State 1, Line 1<br />
BACKUP DATABASE is terminating abnormally.</p></blockquote>
<p>Voyons maintenant la même instruction, seulement avec l&rsquo;option CHECKSUM :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM_CHK.bak'</span><br />
<span style="color: #0000FF;">WITH</span> <span style="color: #FF00FF;">CHECKSUM</span><br />
GO</div></td></tr></tbody></table></div>
<p>Nous obtenons la même erreur. Si nous interrogeons de nouveau la table d&rsquo;historique des sauvegardes pour cette base de données, nous ne trouvons que le premier backup, dont on sait qu&rsquo;il est corrompu. Pourtant nous n&rsquo;avons (presque) aucun moyen de le savoir, car ni cette table, ni l&rsquo;instruction RESTORE HEADERONLY ne permettent de vérifier que le fichier est bien intègre. On peut cependant vérifier les journaux de SQL Server à l&rsquo;aide de la procédure stockée étendue <a href="http://blog.developpez.com/elsuket/p10279/moteur-de-base-de-donnees-sql-server/gestion_lecture_journaux_sql_server"><em>xp_readerrorlog</em></a>, où l&rsquo;on trouve :</p>
<p><img src="http://img17.imageshack.us/img17/9685/backupchecksum06.png" alt="" /></p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Détecter la corruption le plus tôt possible</strong></p>
<p>Une des premières choses à faire après avoir réalisé une installation fraîche de SQL Server est d&rsquo;ajouter une liste d&rsquo;alertes de l&rsquo;Agent SQL Server, qui enverront un mail dès la détection d&rsquo;un problème de corruption. Ceci nécessite le paramétrage de Database Mail, et la mise en place d&rsquo;un opérateur SQL Agent. Voici le code qui permet d&rsquo;ajouter l&rsquo;alerte :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-------------------------------</span><br />
<span style="color: #008080;">-- Nicolas Souquet - 26/05/2013</span><br />
<span style="color: #008080;">-------------------------------</span><br />
<span style="color: #0000FF;">DECLARE</span> @i <span style="color: #0000FF;">smallint</span> <span style="color: #808080;">=</span> <span style="color: #000;">823</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @alert_name sysname<br />
<br />
<span style="color: #0000FF;">DECLARE</span> @operator_name sysname <span style="color: #808080;">=</span> <span style="color: #FF0000;">'monOperateur'</span><br />
<br />
<span style="color: #0000FF;">WHILE</span> @i <span style="color: #808080;">&amp;</span>lt;<span style="color: #808080;">=</span> <span style="color: #000;">825</span><br />
<span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; @alert_name <span style="color: #808080;">=</span> <span style="color: #808080;">&amp;</span>#039;Message <span style="color: #808080;">&amp;</span>#039; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span>@i <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">char</span><span style="color: #808080;">&#40;</span><span style="color: #000;">3</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> msdb.<span style="color: #202020;">dbo</span>.<span style="color: #AF0000;">sp_add_alert</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @name <span style="color: #808080;">=</span> @alert_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @message_id <span style="color: #808080;">=</span> @i<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @severity <span style="color: #808080;">=</span> <span style="color: #000;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @enabled <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @delay_between_responses <span style="color: #808080;">=</span> <span style="color: #000;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @include_event_description_in <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @job_id <span style="color: #808080;">=</span> N<span style="color: #808080;">&amp;</span>#039;00000000<span style="color: #808080;">-</span>0000<span style="color: #808080;">-</span>0000<span style="color: #808080;">-</span>0000<span style="color: #808080;">-</span>000000000000<span style="color: #808080;">&amp;</span>#039;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> msdb.<span style="color: #202020;">dbo</span>.<span style="color: #AF0000;">sp_add_notification</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @alert_name <span style="color: #808080;">=</span> @alert_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @operator_name <span style="color: #808080;">=</span> @operator_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @notification_method <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @i <span style="color: #808080;">=</span> @i <span style="color: #808080;">+</span> <span style="color: #000;">1</span><br />
<span style="color: #0000FF;">END</span></div></td></tr></tbody></table></div>
<p>L&rsquo;erreur qui nous intéresse est la 824, mais les erreurs 823 et 825 sont importantes aussi. Pour trouver leur signification, il suffit d&rsquo;interroger la vue système <em>sys.messages</em> :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">messages</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; message_id <span style="color: #808080;">BETWEEN</span> <span style="color: #000;">823</span> <span style="color: #808080;">AND</span> <span style="color: #000;">825</span><br />
<span style="color: #808080;">AND</span> &nbsp; &nbsp; language_id <span style="color: #808080;">=</span> <span style="color: #000;">1036</span> <span style="color: #008080;">-- Français</span></div></td></tr></tbody></table></div>
<p>On peut faire de même avec l&rsquo;erreur n° 3043, qui est celle que l&rsquo;on obtient lors de la sauvegarde.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Activer CHECKSUM pour toutes les sauvegardes</strong></p>
<p>Cela devrait aussi faire partie de la checklist d&rsquo;installation de SQL Server, d&rsquo;autant que c&rsquo;est d&rsquo;une simplicité enfantine : il suffit d&rsquo;activer le drapeau de trace n° 3023 :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">DBCC</span> TRACEON <span style="color: #808080;">&#40;</span><span style="color: #000;">3023</span>, <span style="color: #808080;">-</span><span style="color: #000;">1</span><span style="color: #808080;">&#41;</span></div></td></tr></tbody></table></div>
<p>Après avoir exécuté cette instruction, si nous ré-exécutons maintenant la commande suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM.bak'</span><br />
<span style="color: #0000FF;">WITH</span> COMPRESSION<br />
GO</div></td></tr></tbody></table></div>
<p>Nous obtenons l&rsquo;erreur que nous avions obtenue lorsque nous avions ajouté l&rsquo;option CHECKSUM :</p>
<blockquote><p>Msg 3043, Level 16, State 1, Line 1<br />
BACKUP &lsquo;TEST_CHECKSUM&rsquo; detected an error on page (1:228) in file &lsquo;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TEST_CHECKSUM.mdf&rsquo;.<br />
Msg 3013, Level 16, State 1, Line 1<br />
BACKUP DATABASE is terminating abnormally.</p></blockquote>
<p>Ceci est très pratique :</p>
<p>&#8211; Si l&rsquo;on prend les sauvegardes de base de données à l&rsquo;aide de <a href="http://blog.developpez.com/elsuket/p11161/agent-sql-server/supporter_plan_de_maintenance">plans de maintenance</a>, il est impossible de spécifier que l&rsquo;on souhaite avoir la somme de contrôle;<br />
&#8211; Si l&rsquo;on code une procédure stockée qui s&rsquo;en charge, cela évite d&rsquo;avoir à l&rsquo;ajouter dans le code.</p>
<p>D&rsquo;autre part si la <a href="http://blog.developpez.com/elsuket/p9040/moteur-de-base-de-donnees-sql-server/compresser_tous_les_backups_sans_modifie_2008">compression des sauvegardes est activée au niveau de l&rsquo;instance</a>, on n&rsquo;a plus qu&rsquo;a se soucier de la sauvegarde elle-même !</p>
<p>Bonnes sauvegardes et intégrité de pages à tous !</p>
<p>ElSüket.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rafraîchir les métadonnées des modules SQL</title>
		<link>https://blog.developpez.com/elsuket/p7084/snippets/rafraichir_les_metadonnees_des_modules_s</link>
		<comments>https://blog.developpez.com/elsuket/p7084/snippets/rafraichir_les_metadonnees_des_modules_s#comments</comments>
		<pubDate>Fri, 16 Jan 2009 20:27:08 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Après un certain temps de vie, ou après que la structure d&#8217;une base de données de développement ait été copiée depuis celle de production puis modifiée, il arrive que lorsqu&#8217;on recherche les dépendances d&#8217;un objet, dans les tables systèmes ou &#8230; <a href="https://blog.developpez.com/elsuket/p7084/snippets/rafraichir_les_metadonnees_des_modules_s">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Après un certain temps de vie, ou après que la structure d&rsquo;une base de données de développement ait été copiée depuis celle de production puis modifiée, il arrive que lorsqu&rsquo;on recherche les dépendances d&rsquo;un objet, dans les tables systèmes ou en choisissant l&rsquo;option <em>Dépendances</em> du menu contextuel proposé par le clic-droit sur un module SQL (une procédure stockée, une fonction, un trigger, ou une vue définis par l&rsquo;utilisateur), les données ou l&rsquo;affichage soient incorrects, bien que l&rsquo;on soit pourtant certain que l&rsquo;objet que l&rsquo;on vient de modifier dépend bien d&rsquo;un autre.<br />
Voici comment remédier à ce désagrément &#8230;<br />
<span id="more-37"></span></p>
<p>Il suffit pour cela de rafraîchir les métadonnées, avec la procédure stockée système sp_refreshsqlmodule, disponible sous SQL Server 2005 (<strong>SP2</strong>) et ultérieurs.<br />
On peut faire cela pour un module SQL bien particulier, mais a y être, autant le faire pour tous les modules de la base de données en cours :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 16/01/2009 - <br />
--------------------------------- <br />
DECLARE @nomModule SYSNAME <br />
&nbsp;<br />
-- Recherche du nom de toutes les procédures stockées, fonction scalaires, fonctions table en ligne, &nbsp;<br />
-- fonction table et vues définies dans le contexte de base de données en cours <br />
DECLARE curToRefresh CURSOR FOR <br />
&nbsp; SELECT name <br />
&nbsp; FROM sys.objects <br />
&nbsp; WHERE type IN ('P', 'FN', 'IF', 'TF', 'V') &nbsp;<br />
&nbsp; AND name NOT LIKE 'dt%' <br />
&nbsp; AND name NOT LIKE 'sp%' <br />
&nbsp; ORDER BY name <br />
FOR READ ONLY <br />
&nbsp;<br />
-- Recherche des dépendances pour chacun de ces objets <br />
OPEN curToRefresh <br />
FETCH NEXT FROM curToRefresh INTO @nomModule <br />
WHILE @@FETCH_STATUS = 0 <br />
BEGIN <br />
&nbsp; BEGIN TRY <br />
&nbsp; &nbsp; PRINT 'Procédure : ' + @nomModule <br />
&nbsp; &nbsp; BEGIN TRAN <br />
&nbsp; &nbsp; &nbsp; EXEC sys.sp_refreshsqlmodule @nomModule <br />
&nbsp; &nbsp; COMMIT TRAN <br />
&nbsp; END TRY <br />
&nbsp; BEGIN CATCH <br />
&nbsp; &nbsp; PRINT ' &nbsp;|---------------&gt; ERREUR : ' + ERROR_MESSAGE() <br />
&nbsp; &nbsp; ROLLBACK TRAN <br />
&nbsp; END CATCH <br />
&nbsp; FETCH NEXT FROM curToRefresh INTO @nomModule <br />
END <br />
&nbsp;<br />
DEALLOCATE curToRefresh</div></td></tr></tbody></table></div>
<p>Dès lors vous constaterez que les données contenues dans la vue système sys.sql_dependencies sous SQL Server 2005, ou dans sys.sysdepends dans SQL Server 2000, sont toutes fraîches !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Obtenir l&#8217;historique des sauvegardes de bases de données</title>
		<link>https://blog.developpez.com/elsuket/p10271/snippets/obtenir_historique_sauvegardes_bases_de_</link>
		<comments>https://blog.developpez.com/elsuket/p10271/snippets/obtenir_historique_sauvegardes_bases_de_#comments</comments>
		<pubDate>Thu, 08 Sep 2011 17:02:18 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici quelques requêtes simples qui montrent l&#8217;historique de toutes les sauvegardes de toutes les bases de données ou d&#8217;une base de données en particulier => Sous SQL Server 2000 12345678910111213141516171819202122232425262728293031323334353637SELECT &#160; &#160;D.name AS database_name &#160; &#160; , C.last_backup_date_time &#160; &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p10271/snippets/obtenir_historique_sauvegardes_bases_de_">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici quelques requêtes simples qui montrent l&rsquo;historique de toutes les sauvegardes de toutes les bases de données ou d&rsquo;une base de données en particulier<br />
<span id="more-66"></span></p>
<p>=> <strong>Sous SQL Server 2000</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT &nbsp; &nbsp;D.name AS database_name <br />
&nbsp; &nbsp; , C.last_backup_date_time <br />
&nbsp; &nbsp; , CAST(C.n / 1440 AS varchar(3)) + ' jours ' <br />
&nbsp; &nbsp; &nbsp; + CAST((C.n % 1440) / 60 AS varchar(2)) + ' heures ' <br />
&nbsp; &nbsp; &nbsp; + CAST(C.n % 60 AS varchar(2)) + ' minutes' AS backup_taken_ago <br />
&nbsp; &nbsp; , C.backup_type <br />
&nbsp; &nbsp; , C.backup_size <br />
&nbsp; &nbsp; , C.compressed_backup_size <br />
FROM &nbsp; &nbsp;sysdatabases AS D <br />
LEFT JOIN &nbsp;( <br />
&nbsp; &nbsp; &nbsp; SELECT &nbsp;database_name <br />
&nbsp; &nbsp; &nbsp; &nbsp; , last_backup_date_time <br />
&nbsp; &nbsp; &nbsp; &nbsp; , DATEDIFF(minute, last_backup_date_time, GETDATE()) AS n <br />
&nbsp; &nbsp; &nbsp; &nbsp; , backup_type <br />
&nbsp; &nbsp; &nbsp; &nbsp; , backup_size <br />
&nbsp; &nbsp; &nbsp; &nbsp; , compressed_backup_size <br />
&nbsp; &nbsp; &nbsp; FROM &nbsp;( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT &nbsp;database_name <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , MAX(backup_finish_date) AS last_backup_date_time <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , CASE type <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'D' THEN 'Full Database' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'I' THEN 'Differential database' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'L' THEN 'Transaction Log' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'F' THEN 'File or filegroup' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'G' THEN 'Differential file' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'P' THEN 'Partial' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'Q' THEN 'Differential partial' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END AS backup_type <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , backup_size &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , compressed_backup_size <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM &nbsp;msdb.dbo.backupset AS S <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GROUP &nbsp;BY database_name, type, backup_size, compressed_backup_size <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) AS BH <br />
&nbsp; &nbsp; &nbsp; ) AS C ON D.name = C.database_name <br />
WHERE &nbsp; &nbsp;1 = 1 <br />
AND &nbsp; &nbsp;D.name = 'maBaseDeDonnees' <br />
ORDER BY &nbsp;D.name</div></td></tr></tbody></table></div>
<p>=> <strong>Sous SQL Server 2005, 2008 et suivants :</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">;WITH <br />
&nbsp; CTE AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT &nbsp;database_name <br />
&nbsp; &nbsp; &nbsp; , last_backup_date_time <br />
&nbsp; &nbsp; &nbsp; , DATEDIFF(minute, last_backup_date_time, GETDATE()) AS n <br />
&nbsp; &nbsp; &nbsp; , backup_type <br />
&nbsp; &nbsp; &nbsp; , backup_size <br />
&nbsp; &nbsp; &nbsp; , compressed_backup_size <br />
&nbsp; &nbsp; FROM &nbsp;( <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT &nbsp;database_name <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , MAX(backup_finish_date) AS last_backup_date_time <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , CASE type <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'D' THEN 'Full Database' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'I' THEN 'Differential database' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'L' THEN 'Transaction Log' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'F' THEN 'File or filegroup' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'G' THEN 'Differential file' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'P' THEN 'Partial' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'Q' THEN 'Differential partial' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END AS backup_type <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , backup_size &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , compressed_backup_size <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM &nbsp;msdb.dbo.backupset AS S <br />
&nbsp; &nbsp; &nbsp; &nbsp; GROUP &nbsp;BY database_name, type, backup_size, compressed_backup_size <br />
&nbsp; &nbsp; &nbsp; ) AS BH <br />
&nbsp; ) <br />
SELECT &nbsp; &nbsp;D.name AS database_name <br />
&nbsp; &nbsp; , C.last_backup_date_time <br />
&nbsp; &nbsp; , CAST(C.n / 1440 AS varchar(3)) + ' jours ' <br />
&nbsp; &nbsp; &nbsp; + CAST((C.n % 1440) / 60 AS varchar(2)) + ' heures ' <br />
&nbsp; &nbsp; &nbsp; + CAST(C.n % 60 AS varchar(2)) + ' minutes' AS backup_taken_ago <br />
&nbsp; &nbsp; , C.backup_type <br />
&nbsp; &nbsp; , C.backup_size <br />
&nbsp; &nbsp; , C.compressed_backup_size <br />
FROM &nbsp; &nbsp;sys.databases AS D <br />
LEFT JOIN &nbsp;CTE AS C ON D.name = C.database_name <br />
WHERE &nbsp; &nbsp;1 = 1 <br />
AND &nbsp; &nbsp;D.name = 'maBaseDeDonnees' <br />
ORDER BY &nbsp;D.name</div></td></tr></tbody></table></div>
<p>Bonne gestion des sauvegardes !</p>
<p>@++ <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lister toutes les contraintes de clé étrangère d&#8217;une base de données</title>
		<link>https://blog.developpez.com/elsuket/p8298/snippets/lister_toutes_les_contraintes_de_cle_etr</link>
		<comments>https://blog.developpez.com/elsuket/p8298/snippets/lister_toutes_les_contraintes_de_cle_etr#comments</comments>
		<pubDate>Mon, 09 Nov 2009 17:40:49 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici un petit snippet permettant d&#8217;obtenir la liste de toutes les contraintes de clé étrangère d&#8217;une base de données avec : &#8211; le nom de la contrainte, &#8211; le nom de la table référençante, &#8211; le nom de la colonne &#8230; <a href="https://blog.developpez.com/elsuket/p8298/snippets/lister_toutes_les_contraintes_de_cle_etr">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici un petit snippet permettant d&rsquo;obtenir la liste de toutes les contraintes de clé étrangère d&rsquo;une base de données avec :<br />
&#8211; le nom de la contrainte,<br />
&#8211; le nom de la table référençante,<br />
&#8211; le nom de la colonne référençante dans la table référençante,<br />
&#8211; le nom de la table référencée,<br />
&#8211; le nom de la colonne référencée dans la table référencée.</p>
<p><span id="more-62"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 09/11/2009 <br />
------------------------------- <br />
SELECT &nbsp; &nbsp;PS.name + '.' + PT.name AS parent_table_name <br />
&nbsp; &nbsp; , PC.name AS parent_column_name <br />
&nbsp; &nbsp; , RS.name + '.' + RT.name AS referenced_table_name <br />
&nbsp; &nbsp; , RC.name AS referenced_column_name <br />
&nbsp; &nbsp; , FK.name AS foreign_key_name <br />
FROM &nbsp; &nbsp;sys.schemas AS PS <br />
INNER JOIN &nbsp;sys.foreign_keys AS FK <br />
&nbsp; &nbsp; &nbsp; ON PS.schema_id = FK.schema_id <br />
INNER JOIN &nbsp;sys.foreign_key_columns AS FKC <br />
&nbsp; &nbsp; &nbsp; ON FK.object_id = FKC.constraint_object_id <br />
INNER JOIN &nbsp;sys.tables AS PT <br />
&nbsp; &nbsp; &nbsp; ON FK.parent_object_id = PT.object_id <br />
INNER JOIN &nbsp;sys.columns AS PC <br />
&nbsp; &nbsp; &nbsp; ON FKC.parent_object_id = PC.object_id <br />
&nbsp; &nbsp; &nbsp; AND FKC.parent_column_id = PC.column_id <br />
INNER JOIN &nbsp;sys.tables AS RT <br />
&nbsp; &nbsp; &nbsp; ON FK.referenced_object_id = RT.object_id <br />
INNER JOIN &nbsp;sys.columns AS RC <br />
&nbsp; &nbsp; &nbsp; ON FKC.referenced_object_id = RC.object_id <br />
&nbsp; &nbsp; &nbsp; AND FKC.referenced_column_id = RC.column_id <br />
INNER JOIN &nbsp;sys.schemas AS RS <br />
&nbsp; &nbsp; &nbsp; ON RT.schema_id = RS.schema_id <br />
WHERE &nbsp; &nbsp;1 = 1 <br />
--AND &nbsp; &nbsp;RS.name = 'dbo' <br />
--AND &nbsp; &nbsp;PS.name = 'dbo' <br />
--AND &nbsp; &nbsp;PT.name = 'maTable' <br />
AND &nbsp; &nbsp;RT.name = 'maTable' <br />
--AND &nbsp; &nbsp;RC.name = 'maColonne' <br />
--AND &nbsp; &nbsp;FK.name = 'maContrainte' <br />
--ORDER BY &nbsp;parent_table_name <br />
ORDER BY &nbsp;foreign_key_name</div></td></tr></tbody></table></div>
<p>Bonne gestion de l&rsquo;intégrité référentielle !</p>
<p>ElSüket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Snippets] Générer le script de création d&#8217;une table existante</title>
		<link>https://blog.developpez.com/elsuket/p7134/snippets/generer_script_creation_table_existante</link>
		<comments>https://blog.developpez.com/elsuket/p7134/snippets/generer_script_creation_table_existante#comments</comments>
		<pubDate>Wed, 28 Jan 2009 21:02:18 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une petite procédure stockée qui permet d&#8217;imprimer le code permettant de créer une table existante. Il ne permet pas encore de récupérer les commandes de création des indexes attachées à la table &#8230; 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130--------------------------------- -- Nicolas SOUQUET - 28/01/2009 &#8230; <a href="https://blog.developpez.com/elsuket/p7134/snippets/generer_script_creation_table_existante">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une petite procédure stockée qui permet d&rsquo;imprimer le code permettant de créer une table existante.<br />
Il ne permet pas encore de récupérer les commandes de création des indexes attachées à la table &#8230;</p>
<p><span id="more-38"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 28/01/2009 - <br />
--------------------------------- <br />
CREATE PROCEDURE uspScripteTable <br />
&nbsp; @nomTable SYSNAME, <br />
&nbsp; @copie BIT = 0, <br />
&nbsp; @execute BIT = 0 <br />
AS <br />
BEGIN <br />
&nbsp; SET NOCOUNT ON <br />
&nbsp; <br />
&nbsp; DECLARE @script VARCHAR(MAX) <br />
&nbsp;<br />
&nbsp; SELECT &nbsp; &nbsp;@script = <br />
&nbsp; &nbsp; &nbsp; ISNULL(@script, '') + CHAR(9) + <br />
&nbsp; &nbsp; &nbsp; COLONNES.name + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN COMPCOL.object_id IS NOT NULL THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' ' + TYPES.name <br />
&nbsp; &nbsp; &nbsp; &nbsp; END + '' + <br />
&nbsp; &nbsp; &nbsp; CASE TYPES.name <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'float' THEN '(' + CAST(COLONNES.precision AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'decimal' THEN '(' + CAST(COLONNES.precision AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'numeric' THEN '(' + CAST(COLONNES.precision AS VARCHAR) + ', ' + CAST(COLONNES.scale AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'binary' THEN '(' + CAST(COLONNES.max_length AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'varbinary' THEN '(' + CASE COLONNES.max_length WHEN -1 THEN 'max' ELSE CAST(COLONNES.max_length AS VARCHAR) END + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'char' THEN '(' + CAST(COLONNES.max_length AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'varchar' THEN '(' + CASE COLONNES.max_length WHEN -1 THEN 'max' ELSE CAST(COLONNES.max_length AS VARCHAR) END + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'nchar' THEN '(' + CAST(COLONNES.max_length AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 'nvarchar' THEN '(' + &nbsp;CASE COLONNES.max_length WHEN -1 THEN 'max' ELSE CAST(COLONNES.max_length AS VARCHAR) END + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE COLONNES.is_identity <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 0 THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN ' IDENTITY(' + CAST(IDENT_SEED(TABLES.name) AS VARCHAR) + ', ' + CAST(IDENT_INCR(TABLES.name) AS VARCHAR) + ')' <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE COLONNES.is_nullable <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 0 THEN ' NOT NULL' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN ' NULL' <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN FK_COLONNES.constraint_object_id IS NULL THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' CONSTRAINT FK_' + TABLES.name + <br />
&nbsp; &nbsp; &nbsp; &nbsp; CASE @copie <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN '_COPIE' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; &nbsp; + '_' + COLONNES.name + ' FOREIGN KEY (' + COLONNES.name + ') REFERENCES ' + SCHEMA_FK.name + '.' + TAB_FK.name + '(' + COL_FK.name + ')' <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN DF.object_id IS NULL THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' CONSTRAINT DF_' + TABLES.name + <br />
&nbsp; &nbsp; &nbsp; &nbsp; CASE @copie <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN '_COPIE' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END + '_' + COLONNES.name + ' DEFAULT ' + REPLACE(REPLACE(DF.definition, '(', ''), ')', '') <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN CHK.object_id IS NULL THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' CONSTRAINT CHK_' + TABLES.name + <br />
&nbsp; &nbsp; &nbsp; &nbsp; CASE @copie <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN '_COPIE' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; END + '_' + COLONNES.name + ' CHECK (' + REPLACE(REPLACE(REPLACE(REPLACE(CHK.definition, '(', ''), ')', ''), '[', ''), ']', '') + ')' <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN COMPCOL.object_id IS NULL THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' AS (' + REPLACE(REPLACE(REPLACE(REPLACE(COMPCOL.definition, '(', ''), ')', ''), '[', ''), ']', '') + ')' <br />
&nbsp; &nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN ISNULL(INDEXES.is_primary_key, 0) = 0 THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' CONSTRAINT PK_' + TABLES.name + <br />
&nbsp; &nbsp; &nbsp; &nbsp; CASE @copie <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN '_COPIE' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; END + ' PRIMARY KEY' <br />
&nbsp; &nbsp; &nbsp; END + <br />
&nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN ISNULL(INDEXES.is_unique_constraint, 0) = 0 THEN '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE ' CONSTRAINT UQ_' + TABLES.name + '_' + COLONNES.name + ' UNIQUE' <br />
&nbsp; &nbsp; &nbsp; END + ',' + CHAR(10) <br />
&nbsp; FROM &nbsp; &nbsp;sys.tables AS TABLES -- Tables <br />
&nbsp; INNER JOIN &nbsp;sys.columns AS COLONNES <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON TABLES.object_id = COLONNES.object_id -- Colonnes <br />
&nbsp; INNER JOIN &nbsp;sys.types AS TYPES <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON COLONNES.user_type_id = TYPES.user_type_id -- types <br />
&nbsp; LEFT JOIN &nbsp;sys.index_columns COL_INDEX -- indexes <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON COL_INDEX.object_id = COLONNES.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND COL_INDEX.column_id = COLONNES.column_id <br />
&nbsp; LEFT JOIN &nbsp;sys.indexes AS INDEXES <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON INDEXES.object_id = COL_INDEX.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND INDEXES.index_id = COL_INDEX.index_id <br />
&nbsp; LEFT JOIN &nbsp;sys.default_constraints AS DF -- contraintes de valeur par défaut <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON DF.parent_object_id = TABLES.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND DF.parent_column_id = COLONNES.column_id <br />
&nbsp; LEFT JOIN &nbsp;sys.check_constraints AS CHK -- contraintes CHECK <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON CHK.parent_object_id = TABLES.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND CHK.parent_column_id = COLONNES.column_id <br />
&nbsp; LEFT JOIN &nbsp;sys.computed_columns AS COMPCOL -- colonnes calculées <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON COMPCOL.column_id = COLONNES.column_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND COMPCOL.object_id = TABLES.object_id <br />
&nbsp; LEFT JOIN &nbsp;sys.foreign_key_columns AS FK_COLONNES <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON FK_COLONNES.parent_object_id = TABLES.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND FK_COLONNES.parent_column_id = COLONNES.column_id <br />
&nbsp; LEFT JOIN &nbsp;sys.columns AS COL_FK <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON FK_COLONNES.referenced_object_id = COL_FK.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND FK_COLONNES.referenced_column_id = COL_FK.column_id <br />
&nbsp; LEFT JOIN &nbsp;sys.tables AS TAB_FK <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON COL_FK.object_id = TAB_FK.object_id <br />
&nbsp; LEFT JOIN &nbsp;sys.schemas AS SCHEMA_FK <br />
&nbsp; &nbsp; &nbsp; &nbsp; ON SCHEMA_FK.schema_id = TAB_FK.schema_id <br />
&nbsp; WHERE &nbsp; &nbsp;TABLES.name = @nomTable <br />
&nbsp;<br />
&nbsp; SELECT &nbsp;@script = 'CREATE TABLE ' + S.name + '.' + <br />
&nbsp; &nbsp; CASE @copie <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN T.name + '_COPIE' <br />
&nbsp; &nbsp; &nbsp; ELSE T.name <br />
&nbsp; &nbsp; END + CHAR(10) + <br />
&nbsp; &nbsp; '(' + CHAR(10) + SUBSTRING(@script, 1, LEN(@script) - 2) + CHAR(10) + ')' <br />
&nbsp; FROM &nbsp;sys.schemas AS S <br />
&nbsp; JOIN &nbsp;sys.tables AS T ON S.schema_id = T.schema_id <br />
&nbsp; WHERE &nbsp;T.name = @nomTable <br />
&nbsp;<br />
&nbsp; PRINT @script <br />
&nbsp; <br />
&nbsp; IF @execute = 1 <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; EXEC (@script) <br />
&nbsp; END <br />
END</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Lister les colonnes d&#8217;une ou des toutes les tables avec leurs types</title>
		<link>https://blog.developpez.com/elsuket/p9579/snippets/lister_les_colonnes_d_une_ou_des_toutes</link>
		<comments>https://blog.developpez.com/elsuket/p9579/snippets/lister_les_colonnes_d_une_ou_des_toutes#comments</comments>
		<pubDate>Mon, 13 Dec 2010 11:23:28 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une requête simple pour obtenir tout cela : 12345678910111213141516171819202122------------------------------- -- Nicolas SOUQUET - 13/12/2010 ------------------------------- SELECT &#160; &#160;S.name AS schema_name &#160; &#160; , T.name AS table_name &#160; &#160; , C.name AS column_name &#160; &#160; , C.column_id &#160; &#160; , &#8230; <a href="https://blog.developpez.com/elsuket/p9579/snippets/lister_les_colonnes_d_une_ou_des_toutes">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une requête simple pour obtenir tout cela :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 13/12/2010 <br />
------------------------------- <br />
SELECT &nbsp; &nbsp;S.name AS schema_name <br />
&nbsp; &nbsp; , T.name AS table_name <br />
&nbsp; &nbsp; , C.name AS column_name <br />
&nbsp; &nbsp; , C.column_id <br />
&nbsp; &nbsp; , TY.name AS data_type_name <br />
&nbsp; &nbsp; , CASE WHEN TY.name IN ('nchar', 'nvarchar') THEN C.max_length / 2 ELSE C.max_length END AS max_length <br />
FROM &nbsp; &nbsp;sys.schemas AS S <br />
INNER JOIN &nbsp;sys.tables AS T <br />
&nbsp; &nbsp; &nbsp; ON S.schema_id = T.schema_id <br />
INNER JOIN &nbsp;sys.columns AS C &nbsp;<br />
&nbsp; &nbsp; &nbsp; ON C.object_id = T.object_id <br />
INNER JOIN &nbsp;sys.types AS TY <br />
&nbsp; &nbsp; &nbsp; ON TY.system_type_id = C.system_type_id <br />
&nbsp; &nbsp; &nbsp; AND TY.system_type_id = TY.user_type_id <br />
WHERE &nbsp; &nbsp;1 = 1 <br />
--AND &nbsp; &nbsp;S.name = 'dbo' <br />
--AND &nbsp; &nbsp;T.name = 'maTable' <br />
--AND &nbsp; &nbsp;C.name = 'maColonne' <br />
ORDER BY &nbsp;T.name, C.column_id</div></td></tr></tbody></table></div>
<p>ElSüket <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Trouver le premier et le dernier jour de la semaine, du mois, du trimestre, et autre calculs</title>
		<link>https://blog.developpez.com/elsuket/p9840/snippets/trouver_le_premier_et_le_dernier_jour_de</link>
		<comments>https://blog.developpez.com/elsuket/p9840/snippets/trouver_le_premier_et_le_dernier_jour_de#comments</comments>
		<pubDate>Tue, 29 Mar 2011 15:04:38 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[Utilitaires]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Beaucoup de participants au forum SQL Server se compliquent la vie avec des calculs bizarres, à trouver le premier ou dernier jour d&#8217;un index temporel, comme celui d&#8217;une semaine, d&#8217;un mois, ou d&#8217;un trimestre. Ces calculs se font souvent à &#8230; <a href="https://blog.developpez.com/elsuket/p9840/snippets/trouver_le_premier_et_le_dernier_jour_de">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Beaucoup de participants au forum SQL Server se compliquent la vie avec des calculs bizarres, à trouver le premier ou dernier jour d&rsquo;un index temporel, comme celui d&rsquo;une semaine, d&rsquo;un mois, ou d&rsquo;un trimestre.</p>
<p>Ces calculs se font souvent à base d&rsquo;extractions de sous-chaînes après avoir converti une date en varchar(n), et on aboutit donc à des choses abominables.</p>
<p>Voici donc une série de calculs de valeurs, uniquement à base de fonctions de date &#8230;<br />
Oui, les dates se manipulent avec des <a href="http://msdn.microsoft.com/fr-fr/library/ms186724.aspx#DateandTimeFunctions">fonctions de date</a>, et non pas avec des <a href="http://msdn.microsoft.com/fr-fr/library/ms181984.aspx">fonctions de chaîne</a> !</p>
<p>J&rsquo;en profite au passage pour rappeler mon billet sur le <a href="http://blog.developpez.com/elsuket/p8233/sql-general/du-choix-des-types-de-donnees/">choix des types de données</a> &#8230;</p>
<p><span id="more-65"></span></p>
<p>La majorité des valeurs calculées ci-dessous repose sur la différence en semaines, mois, trimestres, &#8230;, entre la date courante et le 1er Janvier 1900.<br />
En effet, on peut introduire directement cette date par un zéro dans les fonctions de date, que SQL Server caste automatiquement, et qui donne cette date.</p>
<div class="codecolorer-container sql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">------------------------------- </span><br />
<span style="color: #808080; font-style: italic;">-- Nicolas Souquet - 29/03/2011 </span><br />
<span style="color: #808080; font-style: italic;">------------------------------- </span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp;<span style="color: #808080; font-style: italic;">--*** Semaine </span><br />
&nbsp; DATEADD<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_de_la_semaine_precedente <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_de_la_semaine_courante <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_de_la_semaine_prochaine <br />
&nbsp; <span style="color: #808080; font-style: italic;">--- </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_de_la_semaine_precedente <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_de_la_semaine_courante <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>week<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_de_la_semaine_prochaine <br />
&nbsp; <span style="color: #808080; font-style: italic;">--*** Mois </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_mois_precedent <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_mois_courant &nbsp;<br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_mois_prochain <br />
&nbsp; <span style="color: #808080; font-style: italic;">--- </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_mois_precedent <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_mois_courant &nbsp;<br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_mois_prochain <br />
&nbsp; <span style="color: #808080; font-style: italic;">--*** Trimestre </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_trimestre_precedent <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> permier_jour_du_trimestre_courant <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_trimestre_prochain <br />
&nbsp; <span style="color: #808080; font-style: italic;">--- </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_trimestre_precedent <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_trimestre_courant <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_trimestre_prochain <br />
&nbsp; <span style="color: #808080; font-style: italic;">--*** Semestre </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_semestre_precedent <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span>DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_semestre_courant <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_semestre_prochain <br />
&nbsp; <span style="color: #808080; font-style: italic;">--- </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span>DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_semestre_precedent <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_semestre_courant <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">MONTH</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>DATEDIFF<span style="color: #66cc66;">&#40;</span>quarter<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">12</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_semestre_prochain <br />
&nbsp; <span style="color: #808080; font-style: italic;">--*** Annee </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_annee_precedente <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_annee_courante <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_annee_suivante <br />
&nbsp; <span style="color: #808080; font-style: italic;">--- </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_annee_precedente <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_annee_courante <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_annee_suivante <br />
&nbsp; <span style="color: #808080; font-style: italic;">--*** Siècle </span><br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">&#40;</span>GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> % <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> premier_jour_du_siecle_courant <br />
&nbsp; <span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">&#40;</span>GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> % <span style="color: #cc66cc;">100</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">DAY</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> DATEADD<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span> <span style="color: #66cc66;">,</span> DATEDIFF<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">YEAR</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dernier_jour_du_siecle_courant</div></td></tr></tbody></table></div>
<p>J&rsquo;ai eu un peu la flemme sur le siècle, et j&rsquo;ai trouvé comme prétexte pour m&rsquo;arrêter que cela ne doit pas présenter grand intérêt <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>Bon calculs sur les dates !</p>
<p>ElSüket <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Lister les caractéristiques des indexes sous SQL Server 2005 et 2008</title>
		<link>https://blog.developpez.com/elsuket/p9762/moteur-de-base-de-donnees-sql-server/indexation/lister_les_caracteristiques_des_indexes__2008</link>
		<comments>https://blog.developpez.com/elsuket/p9762/moteur-de-base-de-donnees-sql-server/indexation/lister_les_caracteristiques_des_indexes__2008#comments</comments>
		<pubDate>Tue, 22 Feb 2011 09:28:29 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Indexation]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une requête qui nous permet de retrouver pour tout index : &#8211; la liste de ses colonnes clé &#8211; la liste de ses colonnes incluses &#8211; la définition de son filtre &#8211; le script de création de cet index &#8230; <a href="https://blog.developpez.com/elsuket/p9762/moteur-de-base-de-donnees-sql-server/indexation/lister_les_caracteristiques_des_indexes__2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une requête qui nous permet de retrouver pour tout index :</p>
<p>&#8211; la liste de ses colonnes clé<br />
&#8211; la liste de ses colonnes incluses<br />
&#8211; la définition de son filtre<br />
&#8211; le script de création de cet index</p>
<p><span id="more-29"></span></p>
<p>Voici une première requête qui retourne la définition de tous les index d&rsquo;une base de données.<br />
On peut bien sûr ajouter des filtres afin de voir la définition des index sur une table, ou la définition d&rsquo;un index en particulier.</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas Souquet - 22/02/2011 <br />
------------------------------- <br />
SELECT &nbsp; &nbsp;DISTINCT S.name AS schema_name <br />
&nbsp; &nbsp; , T.name AS table_name <br />
&nbsp; &nbsp; , I.name AS index_name <br />
&nbsp; &nbsp; , LEFT(KC.key_column_list, LEN(KC.key_column_list) - 1) AS key_column_list <br />
&nbsp; &nbsp; , LEFT(KCI.included_key_column_list, LEN(KCI.included_key_column_list) - 1) AS included_key_column_list <br />
&nbsp; &nbsp; , REPLACE(REPLACE(REPLACE(REPLACE(I.filter_definition, '[', ''), ']', ''), '(', ''), ')', '') AS filter_definition <br />
FROM &nbsp; &nbsp;sys.schemas AS S <br />
INNER JOIN &nbsp;sys.tables AS T <br />
&nbsp; &nbsp; &nbsp; ON S.schema_id = T.schema_id <br />
INNER JOIN &nbsp;sys.indexes AS I &nbsp;<br />
&nbsp; &nbsp; &nbsp; ON T.object_id = I.object_id <br />
INNER JOIN &nbsp;sys.index_columns AS IC <br />
&nbsp; &nbsp; &nbsp; ON IC.object_id = I.object_id <br />
&nbsp; &nbsp; &nbsp; AND IC.index_id = I.index_id <br />
INNER JOIN &nbsp;sys.columns AS C <br />
&nbsp; &nbsp; &nbsp; ON IC.object_id = C.object_id <br />
&nbsp; &nbsp; &nbsp; AND IC.column_id = C.column_id <br />
CROSS APPLY &nbsp;( <br />
&nbsp; &nbsp; &nbsp; SELECT &nbsp; &nbsp;CS.name + ',' <br />
&nbsp; &nbsp; &nbsp; FROM &nbsp; &nbsp;sys.columns AS CS <br />
&nbsp; &nbsp; &nbsp; INNER JOIN &nbsp;sys.index_columns AS ICS <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON CS.object_id = ICS.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND CS.column_id = ICS.column_id <br />
&nbsp; &nbsp; &nbsp; WHERE &nbsp; &nbsp;IC.object_id = ICS.object_id <br />
&nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;IC.index_id = ICS.index_id <br />
&nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;ICS.is_included_column = 0 <br />
&nbsp; &nbsp; &nbsp; ORDER BY &nbsp;ICS.index_column_id <br />
&nbsp; &nbsp; &nbsp; FOR XML PATH ('') <br />
&nbsp; &nbsp; ) AS KC (key_column_list) <br />
OUTER APPLY &nbsp;( <br />
&nbsp; &nbsp; &nbsp; SELECT &nbsp; &nbsp;CSI.name + ',' <br />
&nbsp; &nbsp; &nbsp; FROM &nbsp; &nbsp;sys.columns AS CSI <br />
&nbsp; &nbsp; &nbsp; INNER JOIN &nbsp;sys.index_columns AS ICSI <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON CSI.object_id = ICSI.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND CSI.column_id = ICSI.column_id <br />
&nbsp; &nbsp; &nbsp; WHERE &nbsp; &nbsp;IC.object_id = ICSI.object_id <br />
&nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;IC.index_id = ICSI.index_id <br />
&nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;ICSI.is_included_column = 1 <br />
&nbsp; &nbsp; &nbsp; ORDER BY &nbsp;ICSI.index_column_id <br />
&nbsp; &nbsp; &nbsp; FOR XML PATH ('') <br />
&nbsp; &nbsp; ) AS KCI (included_key_column_list) <br />
WHERE &nbsp; &nbsp;S.name = 'dbo' <br />
--AND &nbsp; &nbsp;T.name = 'maTable' <br />
--AND &nbsp; &nbsp;I.name = 'monIndex' <br />
ORDER BY &nbsp;T.name, I.name</div></td></tr></tbody></table></div>
<p><strong>Et une autre donnant le script de définition de l&rsquo;index :</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas Souquet - 22/02/2011 <br />
------------------------------- <br />
;WITH <br />
&nbsp; CTE AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT &nbsp; &nbsp;DISTINCT S.name AS schema_name <br />
&nbsp; &nbsp; &nbsp; &nbsp; , T.name AS table_name <br />
&nbsp; &nbsp; &nbsp; &nbsp; , I.name AS index_name <br />
&nbsp; &nbsp; &nbsp; &nbsp; , LEFT(KC.key_column_list, LEN(KC.key_column_list) - 1) AS key_column_list <br />
&nbsp; &nbsp; &nbsp; &nbsp; , LEFT(KCI.included_key_column_list, LEN(KCI.included_key_column_list) - 1) AS included_key_column_list <br />
&nbsp; &nbsp; &nbsp; &nbsp; , REPLACE(REPLACE(REPLACE(REPLACE(I.filter_definition, '[', ''), ']', ''), '(', ''), ')', '') AS filter_definition <br />
&nbsp; &nbsp; &nbsp; &nbsp; , ROW_NUMBER() OVER(ORDER BY T.name, I.name) AS n <br />
&nbsp; &nbsp; FROM &nbsp; &nbsp;sys.schemas AS S <br />
&nbsp; &nbsp; INNER JOIN &nbsp;sys.tables AS T <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON S.schema_id = T.schema_id <br />
&nbsp; &nbsp; INNER JOIN &nbsp;sys.indexes AS I &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON T.object_id = I.object_id <br />
&nbsp; &nbsp; INNER JOIN &nbsp;sys.index_columns AS IC <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON IC.object_id = I.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND IC.index_id = I.index_id <br />
&nbsp; &nbsp; INNER JOIN &nbsp;sys.columns AS C <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON IC.object_id = C.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND IC.column_id = C.column_id <br />
&nbsp; &nbsp; CROSS APPLY &nbsp;( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT &nbsp; &nbsp;CS.name + ',' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM &nbsp; &nbsp;sys.columns AS CS <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; INNER JOIN &nbsp;sys.index_columns AS ICS <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON CS.object_id = ICS.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND CS.column_id = ICS.column_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE &nbsp; &nbsp;IC.object_id = ICS.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;IC.index_id = ICS.index_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;ICS.is_included_column = 0 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER BY &nbsp;ICS.index_column_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FOR XML PATH ('') <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) AS KC (key_column_list) <br />
&nbsp; &nbsp; OUTER APPLY &nbsp;( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT &nbsp; &nbsp;CSI.name + ',' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM &nbsp; &nbsp;sys.columns AS CSI <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; INNER JOIN &nbsp;sys.index_columns AS ICSI <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ON CSI.object_id = ICSI.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND CSI.column_id = ICSI.column_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE &nbsp; &nbsp;IC.object_id = ICSI.object_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;IC.index_id = ICSI.index_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND &nbsp; &nbsp;ICSI.is_included_column = 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ORDER BY &nbsp;ICSI.index_column_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FOR XML PATH ('') <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) AS KCI (included_key_column_list) <br />
&nbsp; &nbsp; WHERE &nbsp; &nbsp;S.name = 'dbo' <br />
&nbsp; &nbsp; --AND &nbsp; &nbsp;T.name = 'maTable' <br />
&nbsp; &nbsp; --AND &nbsp; &nbsp;I.name = 'monIndex' <br />
&nbsp; ) <br />
SELECT &nbsp;'CREATE INDEX ' + index_name &nbsp;<br />
&nbsp; + ' ON ' + schema_name + '.' + table_name <br />
&nbsp; + '(' + key_column_list + ')' <br />
&nbsp; + CASE WHEN included_key_column_list IS NOT NULL THEN ' INCLUDE(' + included_key_column_list + ')' ELSE '' END <br />
&nbsp; + CASE WHEN filter_definition IS NOT NULL THEN ' WHERE ' + filter_definition ELSE '' END <br />
FROM &nbsp;CTE</div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Voir l&#8217;historique d&#8217;exécution des jobs par une requête</title>
		<link>https://blog.developpez.com/elsuket/p7895/snippets/voir_l_historique_d_execution_des_jobs_p</link>
		<comments>https://blog.developpez.com/elsuket/p7895/snippets/voir_l_historique_d_execution_des_jobs_p#comments</comments>
		<pubDate>Fri, 24 Jul 2009 06:00:00 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Agent SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Si la visionneuse du journal est pratique pour voir l&#8217;historique des exécutions d&#8217;un job, comment peut-on voir s&#8217;il existe des jobs dont l&#8217;exécution a échoué (ou réussi) pour pouvoir l&#8217;encapsuler dans une application ou un rapport SSRS par exemple ? &#8230; <a href="https://blog.developpez.com/elsuket/p7895/snippets/voir_l_historique_d_execution_des_jobs_p">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Si la visionneuse du journal est pratique pour voir l&rsquo;historique des exécutions d&rsquo;un job, comment peut-on voir s&rsquo;il existe des jobs dont l&rsquo;exécution a échoué (ou réussi) pour pouvoir l&rsquo;encapsuler dans une application ou un rapport SSRS par exemple ?</p>
<p><span id="more-14"></span></p>
<p>Les tables système de la base de données MSDB nous permettent de spécifier une requête nous permettant de retrouver tous les informations dont nous avons besoin à propos des jobs :</p>
<p>&#8211; msdb.dbo.sysjobs stocke la liste de tous les jobs présents sur l&rsquo;instance, qu&rsquo;ils soient activés ou non<br />
&#8211; msdb.dbo.sysjobhistory stocke la liste de toutes les exécutions des jobs et de leurs étapes<br />
&#8211; msdb.dbo.sysjobsteps stocke la description de toutes les étapes de tous les jobs de l&rsquo;instance</p>
<p>Voici donc, par exemple, comment retrouver tous les échecs pour le job nommé &lsquo;TEST&rsquo;, avec leur date :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 24/07/2009 - <br />
--------------------------------- <br />
SELECT nomJob, <br />
&nbsp; &nbsp; CAST(STUFF(STUFF(runDateTime, 12, 0, ':'), 15, 0, ':') AS DATETIME) AS DateEchecExecJob <br />
FROM <br />
( <br />
&nbsp; SELECT J.name AS nomJob, <br />
&nbsp; &nbsp; &nbsp; CAST(H.run_date AS CHAR(8)) + ' ' + <br />
&nbsp; &nbsp; &nbsp; CASE LEN(CAST(H.run_time AS VARCHAR(6))) <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 5 THEN '0' + CAST(H.run_time AS CHAR(5)) <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE CAST(H.run_time AS CHAR(6)) <br />
&nbsp; &nbsp; &nbsp; END AS runDateTime <br />
&nbsp; FROM msdb.dbo.sysjobs J <br />
&nbsp; JOIN msdb.dbo.sysjobhistory H <br />
&nbsp; &nbsp; ON J.job_id = H.job_id <br />
&nbsp; WHERE J.name = 'TEST' <br />
&nbsp; AND J.enabled = 1 -- Le job est activé <br />
&nbsp; AND H.run_status = 0 -- 0 : Echec | 1 : Réussite <br />
&nbsp; AND H.step_id = 0 -- quelle que soit l'étape du job <br />
) AS JOB_FAILED_EXEC (nomJob, runDateTime)</div></td></tr></tbody></table></div>
<p>Et si l&rsquo;on veut être relativement complet :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 24/07/2009 - <br />
--------------------------------- <br />
SELECT &nbsp;nomJob <br />
&nbsp; , nomEtapeJob <br />
&nbsp; , numeroEtapeJob <br />
&nbsp; , msgEtape <br />
&nbsp; , CAST(STUFF(STUFF(dateExecutionEtape, 12, 0, ':'), 15, 0, ':') AS DATETIME) AS dateExecutionEtape <br />
&nbsp; , dureeExecutionEtape <br />
&nbsp; , statutExecutionEtape <br />
FROM &nbsp;<br />
( &nbsp;<br />
&nbsp; SELECT &nbsp; &nbsp;J.name AS nomJob <br />
&nbsp; &nbsp; &nbsp; , S.step_name AS nomEtapeJob <br />
&nbsp; &nbsp; &nbsp; , S.step_id AS numeroEtapeJob <br />
&nbsp; &nbsp; &nbsp; , ISNULL('Erreur : ' + M.description, H.message) AS msgEtape <br />
&nbsp; &nbsp; &nbsp; , CAST(H.run_date AS CHAR(8)) + ' ' + &nbsp;<br />
&nbsp; &nbsp; &nbsp; CASE LEN(CAST(H.run_time AS VARCHAR(6))) <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN '00000' + CAST(H.run_time AS CHAR(1)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 2 THEN '0000' + CAST(H.run_time AS CHAR(2)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 3 THEN '000' + CAST(H.run_time AS CHAR(3)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 4 THEN '00' + CAST(H.run_time AS CHAR(4)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 5 THEN '0' + CAST(H.run_time AS CHAR(5)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE CAST(H.run_time AS CHAR(6)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; END AS dateExecutionEtape <br />
&nbsp; &nbsp; &nbsp; , CASE LEN(CAST(H.run_duration AS VARCHAR(10))) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN '00:00:0' + CAST(H.run_duration AS CHAR(1)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 2 THEN '00:00:' + CAST(H.run_duration AS CHAR(2)) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 3 THEN '00:0' + STUFF(CAST(H.run_duration AS CHAR(3)), 2, 0, ':') &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 4 THEN '00:' + STUFF(CAST(H.run_duration AS CHAR(4)), 3, 0, ':') &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 5 THEN '0' + STUFF(STUFF(CAST(H.run_duration AS CHAR(5)), 2, 0, ':'), 5, 0, ':') &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 6 THEN STUFF(STUFF(CAST(H.run_duration AS CHAR(6)), 3, 0, ':'), 6, 0, ':') &nbsp;<br />
&nbsp; &nbsp; &nbsp; END AS dureeExecutionEtape <br />
&nbsp; &nbsp; &nbsp; , CASE H.run_status &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 0 THEN 'FAILED' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 1 THEN 'SUCCESS' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 2 THEN 'RETRY' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 3 THEN 'CANCELED' <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN 4 THEN 'RUNNING' -- Pas fiable <br />
&nbsp; &nbsp; &nbsp; END AS statutExecutionEtape <br />
&nbsp; FROM &nbsp; &nbsp;msdb.dbo.sysjobs AS J &nbsp; <br />
&nbsp; INNER JOIN &nbsp;msdb.dbo.sysjobsteps AS S &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ON J.job_id = S.job_id &nbsp;<br />
&nbsp; INNER JOIN &nbsp;msdb.dbo.sysjobhistory AS H &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ON S.job_id = H.job_id &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; AND S.step_id = H.step_id &nbsp;<br />
&nbsp; LEFT JOIN &nbsp;sys.sysmessages AS M &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ON H.sql_message_id = M.error &nbsp;<br />
) AS JOB_CHARACTERISTICS (nomJob, nomEtapeJob, numeroEtapeJob, msgEtape, dateExecutionEtape, dureeExecutionEtape, statutExecutionEtape)</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Convertir des coordonnées sexagésimales en degrés et en radians</title>
		<link>https://blog.developpez.com/elsuket/p8247/snippets/convertir_des_coordonnees</link>
		<comments>https://blog.developpez.com/elsuket/p8247/snippets/convertir_des_coordonnees#comments</comments>
		<pubDate>Tue, 27 Oct 2009 17:14:11 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Systèmes d&#039;information géographiques]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Souvent, les coordonnées géographiques sont exprimées en degrés, minutes, secondes. Mais nos systèmes sont bien plus à l&#8217;aise avec des nombres décimaux, et il est donc nécessaire de convertir des coordonnées sexagésimales en degrés ou bien en radians. Voici une &#8230; <a href="https://blog.developpez.com/elsuket/p8247/snippets/convertir_des_coordonnees">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Souvent, les coordonnées géographiques sont exprimées en degrés, minutes, secondes.<br />
Mais nos systèmes sont bien plus à l&rsquo;aise avec des nombres décimaux, et il est donc nécessaire de convertir des coordonnées sexagésimales en degrés ou bien en radians.<br />
Voici une petite fonction pour le faire &#8230;</p>
<p><span id="more-159"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 28/10/2009 <br />
------------------------------- <br />
ALTER FUNCTION Fn_CoordonneesSexagesimalesToDegresRadians <br />
&nbsp; ( <br />
&nbsp; &nbsp; @degresLat TINYINT, <br />
&nbsp; &nbsp; @minutesLat TINYINT, <br />
&nbsp; &nbsp; @secondesLat TINYINT, <br />
&nbsp; &nbsp; -------------------- <br />
&nbsp; &nbsp; @degresLong TINYINT, <br />
&nbsp; &nbsp; @minutesLong TINYINT, <br />
&nbsp; &nbsp; @secondesLong TINYINT <br />
&nbsp; ) <br />
&nbsp; RETURNS TABLE <br />
AS <br />
RETURN <br />
( <br />
&nbsp; SELECT latitudeDeg, <br />
&nbsp; &nbsp; &nbsp; longitudeDeg, <br />
&nbsp; &nbsp; &nbsp; RADIANS(latitudeDeg) AS latitudeRad, <br />
&nbsp; &nbsp; &nbsp; RADIANS(longitudeDeg) AS longitudeRad <br />
&nbsp; FROM <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT @degresLat + @minutesLat / 60.0 + @secondesLat / 3600.0 AS latitudeDeg, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @degresLong + @minutesLong / 60.0 + @secondesLong / 3600.0 AS longitudeDeg <br />
&nbsp; ) AS TMP <br />
)</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vérifier l&#8217;unicité d&#8217;une position avec le type GEOGRAPHY sous SQL Server 2008</title>
		<link>https://blog.developpez.com/elsuket/p8257/moteur-de-base-de-donnees-sql-server/indexation/verifier_l_unicite_d_une_position_avec_l_2008</link>
		<comments>https://blog.developpez.com/elsuket/p8257/moteur-de-base-de-donnees-sql-server/indexation/verifier_l_unicite_d_une_position_avec_l_2008#comments</comments>
		<pubDate>Thu, 29 Oct 2009 22:33:34 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Indexation]]></category>
		<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Systèmes d&#039;information géographiques]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[SQL Server 2008 a introduit de nombreux nouveaux types de données, dont le type de données géographiques GEOGRAPHY. Ce n&#8217;est pas un type habituel, puisque c&#8217;est un type CLR.NET intégré à SQL Server. L&#8217;avantage présenté par l&#8217;intégration de ce type &#8230; <a href="https://blog.developpez.com/elsuket/p8257/moteur-de-base-de-donnees-sql-server/indexation/verifier_l_unicite_d_une_position_avec_l_2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>SQL Server 2008 a introduit de nombreux nouveaux types de données, dont le type de données géographiques GEOGRAPHY.<br />
Ce n&rsquo;est pas un type habituel, puisque c&rsquo;est un type CLR.NET intégré à SQL Server.</p>
<p>L&rsquo;avantage présenté par l&rsquo;intégration de ce type est l&rsquo;ensemble des méthodes standard &laquo;&nbsp;livrées&nbsp;&raquo; avec ce type, qui permettent d&rsquo;extraire très simplement une latitude (attribut Lat), une longitude (attribut Long), ou encore de connaître la distance entre deux points géographiques avec la méthode <a href="http://msdn.microsoft.com/fr-fr/library/bb933808.aspx">STDistance</a>.</p>
<p>Mais il devient alors plus complexe de garantir l&rsquo;unicité de positions dans une table où l&rsquo;on stocke la celle de plusieurs villes.<br />
En effet, si une colonne de ce type est spécifiée comme clé d&rsquo;une contrainte d&rsquo;unicité, le moteur de base de données SQL Server lève une exception.</p>
<p>Est-il possible de contourner ce problème ?</p>
<p><span id="more-160"></span></p>
<p>Si nous tentons de créer la table suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE dbo.TbCoordonneeVille <br />
( <br />
&nbsp; IDCoordonneeVille INT NOT NULL IDENTITY CONSTRAINT PK_TbCoordonneeVille PRIMARY KEY, <br />
&nbsp; nomVille VARCHAR(45) NOT NULL CONSTRAINT UQ_TbCoordonneeVille_nomVille UNIQUE, <br />
&nbsp; geoPositionVille GEOGRAPHY NOT NULL CONSTRAINT UQ_TbCoordonneeVille_geoPositionVille UNIQUE &nbsp;<br />
)</div></td></tr></tbody></table></div>
<p>Nous obtenons l&rsquo;erreur :</p>
<blockquote><p>Msg 1919, Niveau 16, État 1, Ligne 1<br />
La colonne &lsquo;geoPositionVille&rsquo; dans la table &lsquo;TbCoordonneeVille&rsquo; n&rsquo;est pas d&rsquo;un type valide lui permettant d&rsquo;être utilisée en tant que colonne clé dans un index.<br />
Msg 1750, Niveau 16, État 0, Ligne 1<br />
Impossible de créer la contrainte. Voir les erreurs précédentes.</p></blockquote>
<p>Nous sommes donc contraints de créer la table sans la contrainte d&rsquo;unicité sur la colonne geoPositionVille :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE dbo.TbCoordonneeVille <br />
( <br />
&nbsp; IDCoordonneeVille INT NOT NULL IDENTITY CONSTRAINT PK_TbCoordonneeVille PRIMARY KEY, <br />
&nbsp; nomVille VARCHAR(45) NOT NULL CONSTRAINT UQ_TbCoordonneeVille_nomVille UNIQUE, <br />
&nbsp; geoPositionVille GEOGRAPHY NOT NULL <br />
)</div></td></tr></tbody></table></div>
<p>Comment faire pour garantir l&rsquo;unicité des positions des villes sans perdre les avantages offerts par le type GEOGRAPHY ?<br />
Il est possible de créer une contrainte d&rsquo;unicité sur des colonnes calculées persistantes.</p>
<p>Ajoutons donc deux colonnes calculées, une pour la latitude, et une autre pour la longitude.<br />
Attention, la casse sur les méthodes CLR est importante.</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 29/10/2009 <br />
------------------------------- <br />
ALTER TABLE dbo.TbCoordonneeVille <br />
ADD latitudeVille AS (geoPositionVille.Lat) PERSISTED NOT NULL, <br />
&nbsp; longitudeVille AS (geoPositionVille.Long) PERSISTED NOT NULL</div></td></tr></tbody></table></div>
<p>Il nous suffit ensuite de créer une contrainte d&rsquo;unicité sur ces deux colonnes :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 29/10/2009 <br />
------------------------------- <br />
ALTER TABLE dbo.TbCoordonneeVille <br />
ADD CONSTRAINT UQ_TbCoordonneeVille_latitudeVille_longitudeVille <br />
&nbsp; UNIQUE (latitudeVille, longitudeVille)</div></td></tr></tbody></table></div>
<p>Essayons maintenant d&rsquo;insérer deux villes dont le nom est différent, mais dont les coordonnées sont identiques :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INSERT INTO dbo.TbCoordonneeVille (nomVille, geoPositionVille) <br />
VALUES ('Toulouse', GEOGRAPHY::STPointFromText('POINT(43.604503 1.444026)', 4326)) <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.TbCoordonneeVille (nomVille, geoPositionVille) <br />
VALUES ('Lyon', GEOGRAPHY::STPointFromText('POINT(43.604503 1.444026)', 4326)) <br />
GO</div></td></tr></tbody></table></div>
<p>La première instruction se passe sans problèmes.<br />
En revanche la seconde échoue, et nous obtenons l&rsquo;erreur suivante :</p>
<blockquote><p>Msg 2627, Niveau 14, État 1, Ligne 1<br />
Violation de la contrainte UNIQUE KEY &lsquo;UQ_TbCoordonneeVille_latitudeVille_longitudeVille&rsquo;. Impossible d&rsquo;insérer une clé en double dans l&rsquo;objet &lsquo;dbo.TbCoordonneeVille&rsquo;.<br />
L&rsquo;instruction a été arrêtée.</p></blockquote>
<p>Vérifions le contenu de la table :</p>
<p><img src="http://blog.developpez.com/media/geographyUnique1.PNG" width="1079" height="363" alt="" /></p>
<p>Une solution alternative est de créer une vue indexée, ce qui présentera un bon avantage si la table est souvent lue.<br />
Supprimons la table puis recréons-la :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DROP TABLE dbo.TbCoordonneeVille <br />
GO <br />
&nbsp;<br />
CREATE TABLE dbo.TbCoordonneeVille <br />
( <br />
&nbsp; IDCoordonneeVille INT NOT NULL IDENTITY CONSTRAINT PK_TbCoordonneeVille PRIMARY KEY, <br />
&nbsp; nomVille VARCHAR(45) NOT NULL CONSTRAINT UQ_TbCoordonneeVille_nomVille UNIQUE, <br />
&nbsp; geoPositionVille GEOGRAPHY NOT NULL <br />
)</div></td></tr></tbody></table></div>
<p>Créons ensuite la vue :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 29/10/2009 <br />
------------------------------- <br />
CREATE VIEW dbo.VwCoordonneeVille <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
SELECT nomVille, <br />
&nbsp; &nbsp; geoPositionVille.Lat AS latitudeVille, <br />
&nbsp; &nbsp; geoPositionVille.Long AS longitudeVille <br />
FROM dbo.TbCoordonneeVille</div></td></tr></tbody></table></div>
<p>Puis indexons-la :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 29/10/2009 <br />
------------------------------- <br />
CREATE UNIQUE CLUSTERED INDEX IXUQC_VwCoordonneeVille_latitudeVille_longitudeVille <br />
ON dbo.VwCoordonneeVille(latitudeVille, longitudeVille)</div></td></tr></tbody></table></div>
<p>Et tentons les mêmes insertions que celles que nous avons faites pour tester la contrainte d&rsquo;unicité sur les colonnes calculées persistantes :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INSERT INTO dbo.TbCoordonneeVille (nomVille, geoPositionVille) <br />
VALUES ('Toulouse', GEOGRAPHY::STPointFromText('POINT(43.604503 1.444026)', 4326)) <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.TbCoordonneeVille (nomVille, geoPositionVille) <br />
VALUES ('Lyon', GEOGRAPHY::STPointFromText('POINT(43.604503 1.444026)', 4326)) <br />
GO</div></td></tr></tbody></table></div>
<p>Là encore, la première instruction se passe sans problème, mais la seconde échoue, provoquant l&rsquo;erreur suivante :</p>
<blockquote><p>Msg 2601, Niveau 14, État 1, Ligne 1<br />
Impossible d&rsquo;insérer une ligne de clé en double dans l&rsquo;objet &lsquo;dbo.VwCoordonneeVille&rsquo; avec un index unique &lsquo;IXUQC_VwCoordonneeVille_latitudeVille_longitudeVille&rsquo;.<br />
L&rsquo;instruction a été arrêtée.</p></blockquote>
<p>Interrogeons néanmoins la vue :</p>
<p><img src="http://blog.developpez.com/media/geographyUnique2.PNG" width="770" height="348" alt="" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Obtenir une représentation sexagésimale d&#8217;une coordonnée géographique en degrés</title>
		<link>https://blog.developpez.com/elsuket/p8378/snippets/obtenir_une_representation_sexagesimale</link>
		<comments>https://blog.developpez.com/elsuket/p8378/snippets/obtenir_une_representation_sexagesimale#comments</comments>
		<pubDate>Thu, 19 Nov 2009 18:19:49 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Systèmes d&#039;information géographiques]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Faisant suite à ce billet, voici une petite fonction pour représenter sexagésimalement une coordonnée géographique exprimée en degrés : 12345678910111213141516171819202122232425262728------------------------------- -- Nicolas SOUQUET - 19/11/2009 ------------------------------- ALTER FUNCTION Fn_SIG_CoordonneesDegresToSexagesimales &#160; (@_degresDecimaux FLOAT) &#160; RETURNS VARCHAR(16) &#160; WITH SCHEMABINDING AS BEGIN &#8230; <a href="https://blog.developpez.com/elsuket/p8378/snippets/obtenir_une_representation_sexagesimale">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Faisant suite à <a href="http://blog.developpez.com/elsuket/p8247/t-sql/convertir-des-coordonnees/">ce billet</a>, voici une petite fonction pour représenter sexagésimalement une coordonnée géographique exprimée en degrés :<br />
<span id="more-161"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 19/11/2009 <br />
------------------------------- <br />
ALTER FUNCTION Fn_SIG_CoordonneesDegresToSexagesimales <br />
&nbsp; (@_degresDecimaux FLOAT) <br />
&nbsp; RETURNS VARCHAR(16) <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; -- Extraction des degrés <br />
&nbsp; DECLARE @nDegresSexagesimaux TINYINT <br />
&nbsp; SELECT @nDegresSexagesimaux = CAST(@_degresDecimaux AS TINYINT) <br />
&nbsp;<br />
&nbsp; -- Extraction des minutes <br />
&nbsp; DECLARE @fMinutesSexagesimaux FLOAT <br />
&nbsp; SELECT @fMinutesSexagesimaux = (@_degresDecimaux - @nDegresSexagesimaux) * 60 <br />
&nbsp; DECLARE @nMinutesSexagesimaux TINYINT <br />
&nbsp; SELECT @nMinutesSexagesimaux = CAST(@fMinutesSexagesimaux AS TINYINT) <br />
&nbsp;<br />
&nbsp; -- Extraction des secondes <br />
&nbsp; DECLARE @fSecondesSexagesimaux FLOAT <br />
&nbsp; SELECT @fSecondesSexagesimaux = (@fMinutesSexagesimaux - @nMinutesSexagesimaux) * 60 <br />
&nbsp;<br />
&nbsp; -- Resultat <br />
&nbsp; RETURN CAST(@nDegresSexagesimaux AS VARCHAR(2)) + '° ' + <br />
&nbsp; &nbsp; &nbsp; CAST(@nMinutesSexagesimaux AS VARCHAR(2)) + '&amp;#8242; ' + <br />
&nbsp; &nbsp; &nbsp; CAST(@fSecondesSexagesimaux AS VARCHAR(14)) + '&quot;' <br />
END</div></td></tr></tbody></table></div>
<p>Ainsi l&rsquo;exécution de :</p>
<p><code class="codecolorer text default"><span class="text">SELECT dbo.Fn_SIG_CoordonneesDegresToSexagesimales (47.51027)</span></code></p>
<p>Nous retourne 47° 30&prime; 36.972&Prime; <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Empêcher un utilisateur de consulter le code source d&#8217;un objet de base de données (procédure stockée, fonction, trigger, vue, &#8230;)</title>
		<link>https://blog.developpez.com/elsuket/p8437/snippets/empecher_un_utilisateur_de_consulter_le</link>
		<comments>https://blog.developpez.com/elsuket/p8437/snippets/empecher_un_utilisateur_de_consulter_le#comments</comments>
		<pubDate>Mon, 07 Dec 2009 20:58:33 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Sécurité]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[On demande parfois comment on peut crypter le code d&#8217;un objet de base de données (procédure stockée, trigger, fonction, vue, &#8230;) afin qu&#8217;un utilisateur ou qu&#8217;un groupe d&#8217;utilisateurs ne puisse pas en consulter le code. Or il faut bien se &#8230; <a href="https://blog.developpez.com/elsuket/p8437/snippets/empecher_un_utilisateur_de_consulter_le">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>On demande parfois comment on peut crypter le code d&rsquo;un objet de base de données (procédure stockée, trigger, fonction, vue, &#8230;) afin qu&rsquo;un utilisateur ou qu&rsquo;un groupe d&rsquo;utilisateurs ne puisse pas en consulter le code.</p>
<p>Or il faut bien se rappeler que le cryptage d&rsquo;un objet de base de données implique que celui-ci soit décrypté lors de chacune de ses exécutions, ce qui peut infliger au serveur de base de données une consommation de ressources élevée, peu souhaitable dans un environnement OLTP ou pour un serveur OLAP fortement sollicité.</p>
<p>Une alternative bien simple existe pourtant : le refus d&rsquo;autorisation.<br />
Voyons comment l&rsquo;utiliser &#8230;<br />
<span id="more-148"></span><br />
Nous allons créer une connexion et un utilisateur TOTO, et lui refuser le droit de voir la définition d&rsquo;une procédure stockée.<br />
Je me limite ici au cas d&rsquo;une procédure stockée, mais le squelette est le même pour tout autre objet de base de données.<br />
Si nous exécutons le script suivant, dans une session sous le login sa (connexion super-admnistrateur par défaut d&rsquo;une instance SQL Server ) :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-- Crée une connexion d'identifiant TOTO <br />
CREATE LOGIN TOTO <br />
WITH PASSWORD = '***' <br />
GO <br />
&nbsp;<br />
-- Change de contexte de base de données <br />
USE ELSUKET <br />
GO <br />
&nbsp;<br />
-- Crée un utilisateur de base de données <br />
CREATE USER TOTO <br />
FOR LOGIN TOTO <br />
GO <br />
&nbsp;<br />
-- Une petite procédure <br />
CREATE PROCEDURE PsTestDroits <br />
AS <br />
BEGIN <br />
&nbsp; SELECT 1 <br />
END <br />
GO <br />
&nbsp;<br />
-- Refuse l'autorisation du vue de la définition à l'utilisateur TOTO <br />
-- de la base de données ELSUKET <br />
DENY VIEW DEFINITION <br />
ON PsTestDroits TO TOTO</div></td></tr></tbody></table></div>
<p>Nous voyons, dans l&rsquo;explorateur d&rsquo;objet de <em>SQL Server Management Studio</em>:</p>
<p><img src="http://blog.developpez.com/media/denyViewDefinition1.png" width="304" height="811" alt="" /></p>
<p>Connectons nous maintenant comme le ferait l&rsquo;utilisateur TOTO :</p>
<p><img src="http://blog.developpez.com/media/denyViewDefinition2.png" width="218" height="232" alt="" /></p>
<p><img src="http://blog.developpez.com/media/denyViewDefinition3.png" width="416" height="315" alt="" /></p>
<p>La nouvelle connexion s&rsquo;ouvre dans l&rsquo;explorateur d&rsquo;objets avec le contexte de navigation dans la base de données de TOTO : on ne peut pas voir la procédure stockée PsTestDroits :</p>
<p><img src="http://blog.developpez.com/media/denyViewDefinition4.png" width="310" height="258" alt="" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Supprimer toutes les captures instantanées de base de données d&#8217;un coup</title>
		<link>https://blog.developpez.com/elsuket/p8302/snippets/supprimer_toutes_les_captures_instantane</link>
		<comments>https://blog.developpez.com/elsuket/p8302/snippets/supprimer_toutes_les_captures_instantane#comments</comments>
		<pubDate>Mon, 09 Nov 2009 21:42:31 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il est parfois nécessaire de supprimer toute les captures instantanées d&#8217;une base de données : par exemple pour la restaurer ou pour la supprimer. Voici donc un bout de code pour les supprimer toutes, d&#8217;un seul coup &#8230; 123456789101112------------------------------- -- &#8230; <a href="https://blog.developpez.com/elsuket/p8302/snippets/supprimer_toutes_les_captures_instantane">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il est parfois nécessaire de supprimer toute les <a href="http://blog.developpez.com/elsuket/p7454/moteur-de-base-de-donnees-sql-server/creer-des-captures-instantanees-de-bases/">captures instantanées</a> d&rsquo;une base de données : par exemple pour la restaurer ou pour la supprimer.<br />
Voici donc un bout de code pour les supprimer toutes, d&rsquo;un seul coup &#8230;<br />
<span id="more-63"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 09/11/2009 <br />
------------------------------- <br />
DECLARE @sql VARCHAR(MAX) = '' <br />
SELECT @sql = @sql + 'DROP DATABASE ' + name + ';' <br />
FROM sys.databases <br />
WHERE source_database_id IS NOT NULL <br />
AND name = 'maBaseDeDonneess' <br />
&nbsp;<br />
PRINT @sql <br />
&nbsp;<br />
--EXEC (@sql)</div></td></tr></tbody></table></div>
<p>Il suffit de décommenter EXEC (@sql) pour exécuter la suppression des captures instantanées, qui entraîne la suppression des fichiers de chacune d&rsquo;entre-elles.</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vérifier la validité d&#8217;une adresse e-mail</title>
		<link>https://blog.developpez.com/elsuket/p8303/snippets/verifier_la_validite_d_une_adresse_e_mai</link>
		<comments>https://blog.developpez.com/elsuket/p8303/snippets/verifier_la_validite_d_une_adresse_e_mai#comments</comments>
		<pubDate>Mon, 09 Nov 2009 22:13:45 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici un petit snippet pour vérifier la validité d&#8217;une adresse mail, histoire d&#8217;assurer un minimum d&#8217;intégrité à l&#8217;aide d&#8217;une contrainte de domaine vérifiée par cette fonction : 123456789101112131415161718192021222324------------------------------- -- Nicolas SOUQUET - 09/11/2009 ------------------------------- CREATE FUNCTION Fn_CheckMail &#160; (@_mail VARCHAR(320)) &#8230; <a href="https://blog.developpez.com/elsuket/p8303/snippets/verifier_la_validite_d_une_adresse_e_mai">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici un petit snippet pour vérifier la validité d&rsquo;une adresse mail, histoire d&rsquo;assurer un minimum d&rsquo;intégrité à l&rsquo;aide d&rsquo;une contrainte de domaine vérifiée par cette fonction :<br />
<span id="more-64"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 09/11/2009 <br />
------------------------------- <br />
CREATE FUNCTION Fn_CheckMail <br />
&nbsp; (@_mail VARCHAR(320)) <br />
&nbsp; RETURNS BIT <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; RETURN CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN CHARINDEX(' ', LTRIM(RTRIM(@_mail))) = 0 -- Pas d'espaces <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND LEFT(LTRIM(@_mail), 1) &nbsp;'@' &nbsp;-- '@' ne peut pas être le premier caractère de l'adresse <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND RIGHT(RTRIM(@_mail), 1) &nbsp;'.' -- '.' ne peut pas être le dernier caractère de l'adresse <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND LEN(LTRIM(RTRIM(@_mail))) - LEN(REPLACE(LTRIM(RTRIM(@_mail)), '@', '')) = 1 -- Un seul '@' <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND CHARINDEX('.', @_mail, CHARINDEX('@', @_mail)) - CHARINDEX('@', @_mail) &amp;gt; 1 -- Il doit y avoir un '.' après l'@ &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; AND CHARINDEX('.', REVERSE(LTRIM(RTRIM(@_mail)))) &amp;gt;= 3 -- le nom de domaine doit se terminer avec au moins 2 caractères <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND CHARINDEX('.@', @_mail) = 0 -- pas de '.@' <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND CHARINDEX('..', @_mail) = 0 -- pas de '..' <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND LEN(LEFT(@_mail, CHARINDEX('@', @_mail) - 1)) &amp;lt;= 64 -- la partie locale ne peut excéder 64 caractères <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND LEN(RIGHT(@_mail, LEN(@_mail) - CHARINDEX(&amp;#039;@&amp;#039;, @_mail))) &amp;lt;= 250 -- la partie nom de domaine ne peut excéder 250 caractères <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; THEN CAST(1 AS BIT) <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE CAST(0 AS BIT) <br />
&nbsp; &nbsp; &nbsp; END <br />
END</div></td></tr></tbody></table></div>
<p>Et voici comment ajouter la contrainte à la table-exemple suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE TbClient <br />
( <br />
&nbsp; IDClient INT NOT NULL CONSTRAINT PK_TbClient PRIMARY KEY, <br />
&nbsp; NumeroClient INT NOT NULL CONSTRAINT UQ_TbClient_NumeroClient UNIQUE, <br />
&nbsp; NomClient VARCHAR(32) NOT NULL, <br />
&nbsp; PrenomClient VARCHAR(32) NOT NULL, <br />
&nbsp; mailClient VARCHAR(320) NOT NULL <br />
) <br />
&nbsp;<br />
ALTER TABLE dbo.TbClient <br />
ADD CONSTRAINT CHK_TbClient_mailClient CHECK (dbo.Fn_CheckMail(mailClient) = 1)</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Lister tous les types de données utilisés pour les colonnes des tables d&#8217;une base de données sous SQL Server 2005 et 2008</title>
		<link>https://blog.developpez.com/elsuket/p8259/snippets/lister_tous_les_types_de_donnees_utilise_2008</link>
		<comments>https://blog.developpez.com/elsuket/p8259/snippets/lister_tous_les_types_de_donnees_utilise_2008#comments</comments>
		<pubDate>Fri, 30 Oct 2009 17:45:50 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une petite requête qui permet de lister tous les types de données utilisés pour les colonnes des tables d&#8217;une base de données &#8230; Si on ne souhaite connaître que les types de données : 12345678910------------------------------- -- Nicolas SOUQUET - &#8230; <a href="https://blog.developpez.com/elsuket/p8259/snippets/lister_tous_les_types_de_donnees_utilise_2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une petite requête qui permet de lister tous les types de données utilisés  pour les colonnes des tables d&rsquo;une base de données &#8230;<br />
<span id="more-61"></span></p>
<p>Si on ne souhaite connaître que les types de données :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 30/10/2009 <br />
------------------------------- <br />
SELECT DISTINCT TY.name AS nomType <br />
FROM sys.TABLES AS T <br />
JOIN sys.COLUMNS AS C <br />
&nbsp; ON T.object_id = C.object_id <br />
JOIN sys.types AS TY <br />
&nbsp; ON C.user_type_id = TY.user_type_id <br />
ORDER BY TY.name</div></td></tr></tbody></table></div>
<p>On peut aussi simplement connaître le nombre d&rsquo;utilisations de tous les types utilisés :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 30/10/2009 <br />
------------------------------- <br />
SELECT TY.name AS nomType, <br />
&nbsp; &nbsp; COUNT(*) AS nbUtilisationsType <br />
FROM sys.tables AS T <br />
JOIN sys.columns AS C <br />
&nbsp; ON T.object_id = C.object_id <br />
JOIN sys.types AS TY <br />
&nbsp; ON C.user_type_id = TY.user_type_id <br />
GROUP BY TY.name <br />
ORDER BY TY.name</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Récupérer les options de session</title>
		<link>https://blog.developpez.com/elsuket/p8111/snippets/recuperer_les_options_de_session</link>
		<comments>https://blog.developpez.com/elsuket/p8111/snippets/recuperer_les_options_de_session#comments</comments>
		<pubDate>Sun, 27 Sep 2009 21:26:35 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Comment connaître la liste des options de session (par exemple SET NOCOUNT ON) que nous utilisons dans la session en cours ou bien dans le contexte d&#8217;exécution ? Ce snippet est valable pour les options suivantes : &#8211; DISABLE_DEF_CNST_CHK &#8211; &#8230; <a href="https://blog.developpez.com/elsuket/p8111/snippets/recuperer_les_options_de_session">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Comment connaître la liste des options de session (par exemple SET NOCOUNT ON) que nous utilisons dans la session en cours ou bien dans le contexte d&rsquo;exécution ?<br />
Ce snippet est valable pour les options suivantes :</p>
<p>&#8211; DISABLE_DEF_CNST_CHK<br />
&#8211; IMPLICIT_TRANSACTIONS<br />
&#8211; CURSOR_CLOSE_ON_COMMIT<br />
&#8211; ANSI_WARNINGS<br />
&#8211; ANSI_PADDING<br />
&#8211; ANSI_NULLS<br />
&#8211; ARITHABORT<br />
&#8211; ARITHIGNORE<br />
&#8211; QUOTED_IDENTIFIER<br />
&#8211; NOCOUNT<br />
&#8211; ANSI_NULL_DFLT_ON<br />
&#8211; ANSI_NULL_DFLT_OFF<br />
&#8211; CONCAT_NULL_YIELDS_NULL<br />
&#8211; NUMERIC_ROUNDABORT<br />
&#8211; XACT_ABORT </p>
<p>Et pas pour les suivantes :</p>
<p>&#8211; TEXTSIZE<br />
&#8211; LANGUAGE<br />
&#8211; DATEFORMAT<br />
&#8211; DATEFIRST<br />
&#8211; LOCK_TIMEOUT<br />
&#8211; ISOLATION LEVEL</p>
<p><span id="more-88"></span></p>
<p>Il est assez simple de vérifier la liste des options de session comme SET NOCOUNT ON à l&rsquo;aide de l&rsquo;instruction DBCC USEROPTIONS :</p>
<p><img src="http://blog.developpez.com/media/dbccuseroptions.PNG" width="374" height="427" alt="" /></p>
<p>Mais si l&rsquo;on souhaite pouvoir manipuler le résultat, nous devons écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- 27/09/2009 - Nicolas SOUQUET - <br />
--------------------------------- <br />
SELECT [Set Option], [Value] <br />
FROM OPENROWSET <br />
( <br />
&nbsp; 'SQLNCLI', <br />
&nbsp; 'Server=monServeur\monInstanceSQLServer;Uid=login;Pwd=motDePasse;', <br />
&nbsp; 'SET FMTONLY OFF;EXEC(''DBCC USEROPTIONS'')' <br />
)</div></td></tr></tbody></table></div>
<p>Mais comme la commande EXEC s&rsquo;exécute dans un autre contexte, on n&rsquo;obtient pas les informations relatives à la session en cours.<br />
Néanmoins la fonction @@OPTIONS elle aussi une valeur qui est une somme de valeurs des puissances de 2, où chacune des options est une puissance de 2.<br />
Dès lors nous pouvons écrire la fonction suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- 27/09/2009 - Nicolas SOUQUET - <br />
--------------------------------- <br />
CREATE FUNCTION FnGetSessionOptions() <br />
&nbsp; RETURNS TABLE <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
&nbsp; RETURN <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT sessionOptions <br />
&nbsp; &nbsp; FROM <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 1 = 1 THEN 'DISABLE_DEF_CNST_CHK' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END AS sessionOptions <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 2 = 2 THEN 'IMPLICIT_TRANSACTIONS' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 4 = 4 THEN 'CURSOR_CLOSE_ON_COMMIT' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 8 = 8 THEN 'ANSI_WARNINGS' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 16 = 16 THEN 'ANSI_PADDING' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 32 = 32 THEN 'ANSI_NULLS' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 64 = 64 THEN 'ARITHABORT' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 128 = 128 THEN 'ARITHIGNORE' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 256 = 256 THEN 'QUOTED_IDENTIFIER' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 512 = 512 THEN 'NOCOUNT' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 1024 = 1024 THEN 'ANSI_NULL_DFLT_ON' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 2048 = 2048 THEN 'ANSI_NULL_DFLT_OFF' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 4096 = 4096 THEN 'CONCAT_NULL_YIELDS_NULL' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 8192 = 8192 THEN 'NUMERIC_ROUNDABORT' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; UNION <br />
&nbsp; &nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @@OPTIONS &amp; 16384 = 16384 THEN 'XACT_ABORT' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE '' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; ) AS TMP <br />
&nbsp; &nbsp; WHERE sessionOptions &gt; '' <br />
&nbsp; )</div></td></tr></tbody></table></div>
<p>Ce qui nous permet de manipuler le résultat de celle-ci très simplement :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT sessionOptions <br />
FROM dbo.FnGetSessionOptions()</div></td></tr></tbody></table></div>
<p>où, avec aucune option de session modifiée, nous obtenons :</p>
<p><img src="http://blog.developpez.com/media/fngetsessionoptions.PNG" width="247" height="312" alt="" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lister les triggers d&#8217;une base de données sous SQL Server 2005 et 2008</title>
		<link>https://blog.developpez.com/elsuket/p8087/snippets/lister_les_triggers_d_une_base_de_donnee_2008</link>
		<comments>https://blog.developpez.com/elsuket/p8087/snippets/lister_les_triggers_d_une_base_de_donnee_2008#comments</comments>
		<pubDate>Mon, 21 Sep 2009 17:58:32 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici un petit snippet pour trouver la liste de tous les triggers d&#8217;une base de données, ainsi que le type d&#8217;événement qui entraîne leur exécution &#8230; Si nous voulons lister les triggers DML (qui sont déclenchés suite à l&#8217;occurrence d&#8217;une &#8230; <a href="https://blog.developpez.com/elsuket/p8087/snippets/lister_les_triggers_d_une_base_de_donnee_2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici un petit snippet pour trouver la liste de tous les triggers d&rsquo;une base de données, ainsi que le type d&rsquo;événement qui entraîne leur exécution &#8230;</p>
<p><span id="more-60"></span></p>
<p>Si nous voulons lister les triggers DML (qui sont déclenchés suite à l&rsquo;occurrence d&rsquo;une instruction INSERT, UPDATE, ou DELETE) de la base de données en cours, nous pouvons exécuter :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 21/09/2009 - <br />
--------------------------------- <br />
SELECT TR.name AS nomTrigger, <br />
&nbsp; &nbsp; T.name AS nomTable, <br />
&nbsp; &nbsp; TR.is_disabled AS estActif, <br />
&nbsp; &nbsp; CASE TR.is_instead_of_trigger <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN 'INSTEAD OF' <br />
&nbsp; &nbsp; &nbsp; ELSE 'AFTER' <br />
&nbsp; &nbsp; END AS typeDeclenchement, <br />
&nbsp; &nbsp; TRE.type_desc AS DMLDeclencheur, <br />
&nbsp; &nbsp; TRE.is_first AS estPremier, <br />
&nbsp; &nbsp; TRE.is_last AS estDernier <br />
FROM sys.triggers AS TR <br />
JOIN sys.tables AS T <br />
&nbsp; ON TR.parent_id = T.object_id <br />
JOIN sys.trigger_events AS TRE <br />
&nbsp; ON TR.object_id = TRE.object_id <br />
--WHERE T.name = 'maTable' <br />
ORDER BY T.name, TR.name</div></td></tr></tbody></table></div>
<p>La seule jointure avec sys.tables suffit a éliminer les triggers de base de données ou de connexion.</p>
<p>Si nous souhaitons lister les triggers de base de données pour la base de données en cours, il suffit d&rsquo;écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 21/09/2009 - <br />
--------------------------------- <br />
SELECT TR.name, <br />
&nbsp; &nbsp; TR.is_disabled AS estActif, <br />
&nbsp; &nbsp; CASE TR.is_instead_of_trigger <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN 'INSTEAD OF' <br />
&nbsp; &nbsp; &nbsp; ELSE 'AFTER' <br />
&nbsp; &nbsp; END AS typeDeclenchement, <br />
&nbsp; &nbsp; TRE.type_desc AS DDLDeclencheur, <br />
&nbsp; &nbsp; TRE.is_first AS estPremier, <br />
&nbsp; &nbsp; TRE.is_last AS estDernier <br />
FROM sys.triggers AS TR <br />
JOIN sys.trigger_events AS TRE <br />
&nbsp; ON TR.object_id = TRE.object_id <br />
WHERE parent_id = 0</div></td></tr></tbody></table></div>
<p>Enfin, si l&rsquo;on souhaite lister les triggers de connexion :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 21/09/2009 - <br />
--------------------------------- <br />
SELECT ST.name AS nomTriggerConnexion, <br />
&nbsp; &nbsp; ST.is_disabled AS estActif, <br />
&nbsp; &nbsp; STE.type_desc AS typeDeclenchement, <br />
&nbsp; &nbsp; STE.event_group_type_desc AS groupeEvenement <br />
FROM sys.server_triggers AS ST <br />
JOIN sys.server_trigger_events AS STE <br />
&nbsp; ON ST.object_id = STE.object_id</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Les dangers de la vérification de l&#8217;intégrité des données : la commande DBCC CHECKDB</title>
		<link>https://blog.developpez.com/elsuket/p8075/snippets/les_dangers_de_la_verification_de_l_inte</link>
		<comments>https://blog.developpez.com/elsuket/p8075/snippets/les_dangers_de_la_verification_de_l_inte#comments</comments>
		<pubDate>Thu, 17 Sep 2009 21:16:20 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Non documenté]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[La plupart du temps, lorsqu&#8217;on pose la question à des personnes qui débutent sous SQL Server, la réponse à la question : &#171;&#160;comment faites-vous pour résoudre une erreur de page déchirée ou de somme de contrôle &#171;&#160;, la réponse est &#8230; <a href="https://blog.developpez.com/elsuket/p8075/snippets/les_dangers_de_la_verification_de_l_inte">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>La plupart du temps, lorsqu&rsquo;on pose la question à des personnes qui débutent sous SQL Server, la réponse à la question : &laquo;&nbsp;comment faites-vous pour résoudre une erreur de page déchirée ou de somme de contrôle &laquo;&nbsp;, la réponse est bien souvent : &laquo;&nbsp;j&rsquo;utilise la commande DBCC CHECKDB avec l&rsquo;option REPAIR_ALLOW_DATA_LOSS&nbsp;&raquo; &#8230;</p>
<p>Et là, c&rsquo;est le drame, car il existe avant cette options bien d&rsquo;autres solutions.</p>
<p>Comme vous allez le voir, l&rsquo;option REPAIR_ALLOW_DATA_LOSS est une option à utiliser en dernier recours, tellement les dégâts qu&rsquo;elle peut causer sont dangereux &#8230;<br />
<span id="more-86"></span></p>
<p>Comment, dès lors, utiliser la commande DBCC CHECKDB, dont l&rsquo;utilité n&rsquo;est ici pas remise en cause, bien au contraire !<br />
Si vous avez choisi la bonne stratégie de sauvegarde suivant le métier qui fait vivre la base de données, vous devez en plus effectuer, au pire par abus de conscience, un contrôle d&rsquo;intégrité, à une fréquence adaptée elle aussi au métier de l&rsquo;entreprise.<br />
Pour une base de données utilisée qui doit être hautement disponible, on peut préférer par exemple vérifier l&rsquo;intégrité de celle-ci tous les jours à l&rsquo;aide de l&rsquo;instruction suivante :</p>
<p><code class="codecolorer text default"><span class="text">DBCC CHECKDB ('maBD') WITH NO_INFOMSGS</span></code></p>
<p>L&rsquo;option <code class="codecolorer text default"><span class="text">WITH NO_INFOMSGS</span></code> ne montre pas tous les messages d&rsquo;information qui sont normalement retournées sans cette option (nombre de pages vérifiées par table, &#8230;).<br />
En revanche, on verra toujours les erreurs apparaître.<br />
Il sera donc pratique de faire exécuter cela par un job à une heure de faible activité sur la base de données, et d&rsquo;adjoindre au job un fichier de sortie pour pouvoir consulter <em>a posteriori</em> ce fichier.</p>
<p>Comme cette option peut consommer une quantité de ressources système élevée, on peut tout à fait se rabattre sur :</p>
<p><code class="codecolorer text default"><span class="text">DBCC CHECKDB ('maBD') WITH PHYSICAL_ONLY, NO_INFOMSGS</span></code></p>
<p>Cette instruction permet de ne vérifier les structures sur disque, sans scruter les structures logiques internes aux pages de la base de données.</p>
<p><strong>Revenons à nos moutons : nous avons détecté un problème d&rsquo;intégrité dans la base de données, et maintenant, que fait-on ?</strong></p>
<p>Si, comme nous l&rsquo;avons vu un peu plus haut, nous avons choisi la bonne stratégie de sauvegarde, alors nous sommes sauvés.<br />
Restaurer une base de données corrompue est de loin la meilleure solution à employer pour passer outre une corruption de données, mais il existe encore, avant de prendre cette décision qui peut être lourde de conséquences dans certains contextes, bien d&rsquo;autres possibilités.<br />
Voyons à quoi ressemble une erreur de corruption de page :</p>
<blockquote><p>Msg 8928, Level 16, State 1, Line 1<br />
Object ID 2078435228, index ID 0, partition ID 72342401522583797, alloc unit ID 72385201253561693 (type In-row data): Page (1:62418) could not be processed.  See other errors for details.<br />
Msg 8939, Level 16, State 98, Line 1<br />
Table error: Object ID 2078435228, index ID 0, partition ID 72342401522583797, alloc unit ID 72385201253561693 (type In-row data), page (1:62418). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed.<br />
CHECKDB found 0 allocation errors and 2 consistency errors in table &lsquo;elsuket&rsquo; (object ID 2078435228).<br />
CHECKDB found 0 allocation errors and 2 consistency errors in database &lsquo;elsuket&rsquo;.<br />
repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (ELSUKET).</p></blockquote>
<p>Comme on le voit, la page corrompue nous est précisée.<br />
Il serait avantageux de savoir à quel objet appartient cette page, car :</p>
<p>&#8211; si c&rsquo;est un index non-cluster, il suffit de reconstruire celui-ci (ce n&rsquo;est pas le cas avec un index cluster)<br />
&#8211; si c&rsquo;est un autre type d&rsquo;objet, nous pouvons utiliser l&rsquo;option PAGE de l&rsquo;instruction RESTORE DATABASE.</p>
<p>Notons que cette dernière possibilité n&rsquo;est possible que dans le mode de restauration FULL.<br />
Examinons maintenant la page qui est corrompue.<br />
Malheureusement cela nécessite de connaître des drapeaux de trace et instructions qui ne sont pas documentés :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DBCC TRACEON (3604, -1) <br />
GO <br />
DBCC PAGE('ELSUKET', 1, 62418, 3) <br />
GO</div></td></tr></tbody></table></div>
<p>Le drapeau de trace 3604 est utilisé ici pour remonter les traces d&rsquo;exécution de toute commande DBCC au client de la session de l&rsquo;utilisateur.</p>
<p>La commande DBCC PAGE est ici spécifiée comme suit :</p>
<p>&#8211; &lsquo;ELSUKET&rsquo; est le nom de la base de données,<br />
&#8211; 1 est le numéro de fichier (c&rsquo;est le même numéro que celui qui précède le numéro de page dans le résultat de la commande DBCC CHECKDB )<br />
&#8211; 62418 est le numéro de page<br />
&#8211; 3 est l&rsquo;option de suivi de scrutation des pages : on aura l&rsquo;en-tête de buffer, l&rsquo;en-tête de page, chaque ligne de données que stocke la page, la table des offsets de lignes.</p>
<p>Dans le listing, nous trouverons des repères nommés <em>MetaData</em>, et nous pourrons trouver, par exemple :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">MetaData: AllocUnitId = 72385201253561693 &nbsp;<br />
MetaData: PartitionId = 72342401522583797 <br />
MetaData: ObjectId = 2078435228 <br />
Metadata: IndexId = 1</div></td></tr></tbody></table></div>
<p>C&rsquo;est plus précisément <em>Metadata: IndexId</em> qui nous intéresse ici :</p>
<p>&#8211; S&rsquo;il est plus grand que 1, il s&rsquo;agit d&rsquo;une index non-cluster, donc il suffit de le supprimer et de la reconstruire<br />
&#8211; S&rsquo;il vaut 0 ou 1, nous devons résoudre le défaut d&rsquo;intégrité de façon plus complexe.</p>
<p>=> <strong>Restauration de pages à partir d&rsquo;une sauvegarde de la base de données</strong></p>
<p>On peut tout simplement restaurer la page concernée à partir de notre sauvegarde, en ayant au préalable sauvegardé la queue du fichier du journal des transactions, c&rsquo;est à dire le journal des transactions courant.<br />
Il faut alors restaurer la dernière sauvegarde complète, puis l&rsquo;éventuelle dernière sauvegarde différentielle, puis les journaux de transaction dans l&rsquo;ordre où ils ont été sauvegardés, pour enfin restaurer la queue de celui-ci, mais avec l&rsquo;option <code class="codecolorer text default"><span class="text">NORECOVERY</span></code> de l&rsquo;instruction <code class="codecolorer text default"><span class="text">RESTORE</span></code>.</p>
<p>Si peu de pages sont corrompues, on peut alors décider de les restaurer une à une à partir de la base de données fraîchement restaurée :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">RESTORE DATABASE ELSUKET PAGE = '1:62418' <br />
FROM DISK = 'C:\ELSUKET.bak' <br />
WITH NORECOVERY</div></td></tr></tbody></table></div>
<p>Rappelons que cela n&rsquo;est possible que dans le mode de restauration FULL.<br />
Si la base de données utilise le mode de restauration SIMPLE, alors on devra restaurer la base de données à partir de la dernière sauvegarde complète et des éventuelles sauvegardes différentielles, mais on perdra les données qui ont été ajoutées ou modifiées entre l&rsquo;heure de terminaison des sauvegardes et maintenant.</p>
<p>=> <strong>La réparation automatique, et ses dangers</strong></p>
<p>Il est important, avant de choisir parmi les options de réparation de corruption, l&rsquo;option qui convient :</p>
<p>&#8211; REPAIR_ALLOW_DATA_LOSS<br />
&#8211; REPAIR_REBUILD</p>
<p>Si nous revenons à la trace produite par l&rsquo;exécution de la commande DBCC CHECKDB, on trouve dans celle-ci le niveau de correction à adopter :</p>
<blockquote><p>repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (ELSUKET)</p></blockquote>
<p>Si l&rsquo;option proposée est REPAIR_REBUILD, vous l&rsquo;avez échappé belle : il n&rsquo;y aucun risque de perte de données : il s&rsquo;agira pour le moteur de base de données de réparer des clés manquantes dans les index non-cluster, ou bien de reconstruire un index.</p>
<p>Si en revanche vous avez, comme ici, l&rsquo;option REPAIR_ALLOW_DATA_LOSS, comme le dit si bien cette options, il est possible que vous perdiez des données (d&rsquo;où l&rsquo;importance des sauvegardes).<br />
En effet, cette commande peut par exemple supprimer la page et la ré-allouer pour faire &laquo;&nbsp;croire&nbsp;&raquo; que celle-ci n&rsquo;a en fait jamais existé&#8230;</p>
<p><strong>En conclusion : bichonnez vos sauvegardes !</strong></p>
<p>Pour aller plus loin, je vous propose cet article de Mikedavem : <a href="La vérification d'intégrité et les problématiques liées aux VLDB">La vérification d&rsquo;intégrité et les problématiques liées aux VLDB</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lister les statistiques de colonnes et quelques une de leurs caractéristiques sous SQL Server 2008</title>
		<link>https://blog.developpez.com/elsuket/p8067/snippets/lister_les_statistiques_de_colonnes_et_q_2008</link>
		<comments>https://blog.developpez.com/elsuket/p8067/snippets/lister_les_statistiques_de_colonnes_et_q_2008#comments</comments>
		<pubDate>Wed, 16 Sep 2009 18:26:18 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici un petit snippet pour vous permettre de voir quelles sont les statistiques qui sont attachées aux colonnes des tables : 123456789101112131415161718192021------------------------------- -- Nicolas SOUQUET - 16/09/2009 ------------------------------- SELECT T.name AS nomTable, &#160; &#160; S.name AS nomStatistique, &#160; &#160; C.name &#8230; <a href="https://blog.developpez.com/elsuket/p8067/snippets/lister_les_statistiques_de_colonnes_et_q_2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici un petit snippet pour vous permettre de voir quelles sont les statistiques qui sont attachées aux colonnes des tables :</p>
<p><span id="more-59"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 16/09/2009 <br />
------------------------------- <br />
SELECT T.name AS nomTable, <br />
&nbsp; &nbsp; S.name AS nomStatistique, <br />
&nbsp; &nbsp; C.name AS nomColonne, <br />
&nbsp; &nbsp; S.auto_created AS estCreeeAuto, <br />
&nbsp; &nbsp; S.user_created AS estMAJAuto, <br />
&nbsp; &nbsp; S.filter_definition AS filtre <br />
FROM sys.stats AS S <br />
JOIN sys.stats_columns AS SC <br />
&nbsp; ON S.object_id = SC.object_id <br />
&nbsp; AND S.stats_id = SC.stats_id <br />
JOIN sys.columns AS C <br />
&nbsp; ON C.object_id = SC.object_id <br />
&nbsp; AND C.column_id = SC.column_id <br />
JOIN sys.tables AS T <br />
&nbsp; ON C.object_id = T.object_id <br />
&nbsp; AND T.name NOT LIKE 'sys%' <br />
&nbsp; AND T.name NOT LIKE 'dt%' <br />
ORDER BY T.name, S.name, C.name</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trouver l&#8217;heure de dernier démarrage d&#8217;une instance SQL Server</title>
		<link>https://blog.developpez.com/elsuket/p8005/snippets/trouver_l_heure_de_dernier_demarrage_d_u</link>
		<comments>https://blog.developpez.com/elsuket/p8005/snippets/trouver_l_heure_de_dernier_demarrage_d_u#comments</comments>
		<pubDate>Mon, 31 Aug 2009 21:43:47 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il est bon de savoir la dernière fois que le service SQL Server a été démarré. Voici donc deux requêtes simples pour connaître celles-ci sous SQL Server 2005 et 2008 &#8230; 12345------------------------------------------------- -- Nicolas SOUQUET - 31/08/2009 - SQL Server &#8230; <a href="https://blog.developpez.com/elsuket/p8005/snippets/trouver_l_heure_de_dernier_demarrage_d_u">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il est bon de savoir la dernière fois que le service SQL Server a été démarré.<br />
Voici donc deux requêtes simples pour connaître celles-ci sous SQL Server 2005 et 2008 &#8230;</p>
<p><span id="more-58"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------- <br />
-- Nicolas SOUQUET - 31/08/2009 - SQL Server 2000 <br />
------------------------------------------------- <br />
SELECT MIN(login_time) <br />
FROM master.dbo.sysprocesses</div></td></tr></tbody></table></div>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------- <br />
-- Nicolas SOUQUET - 31/08/2009 - SQL Server 2005 <br />
------------------------------------------------- <br />
SELECT DATEADD(second, -ms_ticks / 1000, GETDATE()) <br />
FROM sys.dm_os_sys_info;</div></td></tr></tbody></table></div>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------- <br />
-- Nicolas SOUQUET - 31/08/2009 - SQL Server 2008 <br />
------------------------------------------------- <br />
SELECT sqlserver_start_time <br />
FROM sys.dm_os_sys_info</div></td></tr></tbody></table></div>
<p>Facile à mettre dans un rapport SSRS &#8230; <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Retrouver l&#8217;utilisation CPU d&#8217;une machine sous SQL Server 2005 et 2008</title>
		<link>https://blog.developpez.com/elsuket/p8007/snippets/retrouver_l_utilisation_cpu_d_une_machin_2008</link>
		<comments>https://blog.developpez.com/elsuket/p8007/snippets/retrouver_l_utilisation_cpu_d_une_machin_2008#comments</comments>
		<pubDate>Tue, 01 Sep 2009 20:45:37 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Avec SQL Server 2005, Microsoft a introduit les vues et fonctions de gestion dynamique qui facilitent grandement l&#8217;administration des serveurs. Voyons comment utiliser celles-ci pour suivre la consommation de CPU d&#8217;une machine Les requête suivantes fournissent la consommation de processeurs &#8230; <a href="https://blog.developpez.com/elsuket/p8007/snippets/retrouver_l_utilisation_cpu_d_une_machin_2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Avec SQL Server 2005, Microsoft a introduit les vues et fonctions de gestion dynamique qui facilitent grandement l&rsquo;administration des serveurs.<br />
Voyons comment utiliser celles-ci pour suivre la consommation de CPU d&rsquo;une machine</p>
<p><span id="more-32"></span></p>
<p>Les requête suivantes fournissent la consommation de processeurs d&rsquo;une machine en pourcentage, en séparant la consommation de CPU par le processus SQL Server de l&rsquo;instance de la consommation CPU d&rsquo;autre processus.</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------------------------------------------------ <br />
--Nicolas SOUQUET - 01/09/2009 - Consommation de CPU (valable jusqu'à SQL Server 2005 SP1) <br />
------------------------------------------------------------------------------------------ <br />
DECLARE @cpu_ticks BIGINT <br />
SELECT @cpu_ticks = cpu_ticks / CONVERT(FLOAT, cpu_ticks_in_ms) <br />
FROM sys.dm_os_sys_info; <br />
&nbsp;<br />
WITH <br />
&nbsp; CTE_HeureDeb_HeureFin As <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT MIN(DATEPART(hour, DATEADD(ms, -1 * (@cpu_ticks - timestamp), GETDATE()))) HDeb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; MAX(DATEPART(hour, DATEADD(ms, -1 * (@cpu_ticks - timestamp), GETDATE()))) HFin <br />
&nbsp; &nbsp; FROM sys.dm_os_ring_buffers &nbsp;<br />
&nbsp; &nbsp; WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' <br />
&nbsp; &nbsp; AND record LIKE '%&lt;SystemHealth&gt;%' <br />
&nbsp; ), <br />
&nbsp; CTE_Heures AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(hour, CTE_HeureDeb_HeureFin.HDeb, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) HeureDeb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DATEADD(minute, 15, DATEADD(hour, CTE_HeureDeb_HeureFin.HDeb, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME))) HeureFin <br />
&nbsp; &nbsp; &nbsp; FROM CTE_HeureDeb_HeureFin <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(minute, 15, HeureDeb), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DATEADD(minute, 15, HeureFin) <br />
&nbsp; &nbsp; &nbsp; FROM CTE_Heures, CTE_HeureDeb_HeureFin <br />
&nbsp; &nbsp; &nbsp; WHERE HeureDeb &lt; DATEADD(hour, CTE_HeureDeb_HeureFin.HFin, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) <br />
&nbsp; ) <br />
SELECT CTE_Heures.HeureFin, <br />
&nbsp; &nbsp; AVG(SQLProcessUtilization) SQL, <br />
&nbsp; &nbsp; AVG(OtherProcessUtilization) Other <br />
FROM ( <br />
&nbsp; &nbsp; SELECT DATEADD(ms, -1 * (@cpu_ticks - [timestamp]), GETDATE()) AS EventTime, &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SQLProcessUtilization, <br />
&nbsp; &nbsp; &nbsp; &nbsp; SystemIdle, <br />
&nbsp; &nbsp; &nbsp; &nbsp; 100 - SystemIdle - SQLProcessUtilization OtherProcessUtilization <br />
&nbsp; &nbsp; FROM ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT record.value('(./Record/SchedluerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') SystemIdle, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; record.value('(./Record/SchedluerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') SQLProcessUtilization, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timestamp <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT timestamp, CONVERT(xml, record) AS record &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM sys.dm_os_ring_buffers &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND record LIKE '%&lt;SystemHealth&gt;%' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) SCHEDULER <br />
&nbsp; &nbsp; &nbsp; ) DATA <br />
&nbsp; ) FINAL <br />
JOIN CTE_Heures <br />
&nbsp; ON FINAL.EventTime BETWEEN CTE_Heures.HeureDeb <br />
&nbsp; AND CTE_Heures.HeureFin <br />
GROUP BY CTE_Heures.HeureFin</div></td></tr></tbody></table></div>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-------------------------------------------------------------------------------------------- <br />
--Nicolas SOUQUET - 01/09/2009 - Consommation de CPU (valable pour SQL Server 2005 post-SP1) <br />
-------------------------------------------------------------------------------------------- <br />
DECLARE @cpu_ticks BIGINT <br />
SELECT @cpu_ticks = cpu_ticks / CONVERT(FLOAT, cpu_ticks_in_ms) <br />
FROM sys.dm_os_sys_info; <br />
&nbsp;<br />
WITH <br />
&nbsp; CTE_HeureDeb_HeureFin As <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT MIN(DATEPART(hour, DATEADD(ms, -1 * (@cpu_ticks - timestamp), GETDATE()))) HDeb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; MAX(DATEPART(hour, DATEADD(ms, -1 * (@cpu_ticks - timestamp), GETDATE()))) HFin <br />
&nbsp; &nbsp; FROM sys.dm_os_ring_buffers &nbsp;<br />
&nbsp; &nbsp; WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' <br />
&nbsp; &nbsp; AND record LIKE '%&lt;SystemHealth&gt;%' <br />
&nbsp; ), <br />
&nbsp; CTE_Heures AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(hour, CTE_HeureDeb_HeureFin.HDeb, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) HeureDeb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DATEADD(minute, 15, DATEADD(hour, CTE_HeureDeb_HeureFin.HDeb, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME))) HeureFin <br />
&nbsp; &nbsp; &nbsp; FROM CTE_HeureDeb_HeureFin <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(minute, 15, HeureDeb), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DATEADD(minute, 15, HeureFin) <br />
&nbsp; &nbsp; &nbsp; FROM CTE_Heures, CTE_HeureDeb_HeureFin <br />
&nbsp; &nbsp; &nbsp; WHERE HeureDeb &lt; DATEADD(hour, CTE_HeureDeb_HeureFin.HFin, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) <br />
&nbsp; ) <br />
SELECT CTE_Heures.HeureFin, <br />
&nbsp; &nbsp; AVG(SQLProcessUtilization) SQL, <br />
&nbsp; &nbsp; AVG(OtherProcessUtilization) Other <br />
FROM ( <br />
&nbsp; &nbsp; SELECT DATEADD(ms, -1 * (@cpu_ticks - [timestamp]), GETDATE()) AS EventTime, &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SQLProcessUtilization, <br />
&nbsp; &nbsp; &nbsp; &nbsp; SystemIdle, <br />
&nbsp; &nbsp; &nbsp; &nbsp; 100 - SystemIdle - SQLProcessUtilization OtherProcessUtilization <br />
&nbsp; &nbsp; FROM ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') SystemIdle, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') SQLProcessUtilization, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timestamp <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT timestamp, CONVERT(xml, record) AS record &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM sys.dm_os_ring_buffers &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND record LIKE '%&lt;SystemHealth&gt;%' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) SCHEDULER <br />
&nbsp; &nbsp; &nbsp; ) DATA <br />
&nbsp; ) FINAL <br />
JOIN CTE_Heures <br />
&nbsp; ON FINAL.EventTime BETWEEN CTE_Heures.HeureDeb <br />
&nbsp; AND CTE_Heures.HeureFin <br />
GROUP BY CTE_Heures.HeureFin</div></td></tr></tbody></table></div>
<p>Il y a en fait une petite erreur d&rsquo;orthographe qui a été corrigée avec le SP2 de SQL Server 2005, au niveau du XML que contient la colonne <em>record</em> : <em>SchedluerMonitorEvent</em> a été corrigé par <em>SchedulerMonitorEvent</em></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">----------------------------------------------------------------------------------- <br />
--Nicolas SOUQUET - 01/09/2009 - Consommation de CPU (valable pour SQL Server 2008) <br />
----------------------------------------------------------------------------------- <br />
DECLARE @cpu_ticks BIGINT <br />
&nbsp;<br />
SELECT @cpu_ticks = ms_ticks <br />
FROM sys.dm_os_sys_info; <br />
&nbsp;<br />
;WITH <br />
&nbsp; CTE_HeureDeb_HeureFin As <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT MIN(DATEPART(hour, DATEADD(ms, -1 * (@cpu_ticks - timestamp), GETDATE()))) HDeb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; MAX(DATEPART(hour, DATEADD(ms, -1 * (@cpu_ticks - timestamp), GETDATE()))) HFin <br />
&nbsp; &nbsp; FROM sys.dm_os_ring_buffers &nbsp;<br />
&nbsp; &nbsp; WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' <br />
&nbsp; &nbsp; AND record LIKE '%&lt;SystemHealth&gt;%' <br />
&nbsp; ), <br />
&nbsp; CTE_Heures AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(hour, CTE_HeureDeb_HeureFin.HDeb, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) HeureDeb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DATEADD(minute, 15, DATEADD(hour, CTE_HeureDeb_HeureFin.HDeb, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME))) HeureFin <br />
&nbsp; &nbsp; &nbsp; FROM CTE_HeureDeb_HeureFin <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(minute, 15, HeureDeb), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DATEADD(minute, 15, HeureFin) <br />
&nbsp; &nbsp; &nbsp; FROM CTE_Heures, CTE_HeureDeb_HeureFin <br />
&nbsp; &nbsp; &nbsp; WHERE HeureDeb &lt; DATEADD(hour, CTE_HeureDeb_HeureFin.HFin, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) <br />
&nbsp; ) <br />
SELECT CTE_Heures.HeureFin, <br />
&nbsp; &nbsp; AVG(SQLProcessUtilization) SQL, <br />
&nbsp; &nbsp; AVG(OtherProcessUtilization) Other <br />
FROM ( <br />
&nbsp; &nbsp; SELECT DATEADD(ms, -1 * (@cpu_ticks - [timestamp]), GETDATE()) AS EventTime, &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SQLProcessUtilization, <br />
&nbsp; &nbsp; &nbsp; &nbsp; SystemIdle, <br />
&nbsp; &nbsp; &nbsp; &nbsp; 100 - SystemIdle - SQLProcessUtilization OtherProcessUtilization <br />
&nbsp; &nbsp; FROM ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') SystemIdle, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') SQLProcessUtilization, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timestamp <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT timestamp, CONVERT(xml, record) AS record &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM sys.dm_os_ring_buffers &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND record LIKE '%&lt;SystemHealth&gt;%' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) SCHEDULER <br />
&nbsp; &nbsp; &nbsp; ) DATA <br />
&nbsp; ) FINAL <br />
JOIN CTE_Heures <br />
&nbsp; ON FINAL.EventTime BETWEEN CTE_Heures.HeureDeb <br />
&nbsp; AND CTE_Heures.HeureFin <br />
GROUP BY CTE_Heures.HeureFin</div></td></tr></tbody></table></div>
<p>Facile à mettre dans un rapport SSRS pour tracer un graphe <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Snippets] Manipuler un fichier texte d&#8217;une colonne comme une table d&#8217;une colonne</title>
		<link>https://blog.developpez.com/elsuket/p7218/snippets/snippets_manipuler_un_fichier_texte_d_un</link>
		<comments>https://blog.developpez.com/elsuket/p7218/snippets/snippets_manipuler_un_fichier_texte_d_un#comments</comments>
		<pubDate>Thu, 12 Feb 2009 18:56:20 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voyons comment on peut rendre abstraite la notion de fichier en T-SQL en combinant les commandes OPENROWSET et les vénérables CTE &#8230; 123456789101112131415161718192021222324--------------------------------- -- Nicolas SOUQUET - 12/02/2009 - --------------------------------- WITH &#160; CTE_IMPORT AS &#160; ( &#160; &#160; SELECT BulkColumn &#8230; <a href="https://blog.developpez.com/elsuket/p7218/snippets/snippets_manipuler_un_fichier_texte_d_un">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voyons comment on peut rendre abstraite la notion de fichier en T-SQL en combinant les commandes OPENROWSET et les vénérables CTE &#8230;</p>
<p><span id="more-39"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 12/02/2009 - <br />
--------------------------------- <br />
WITH <br />
&nbsp; CTE_IMPORT AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT BulkColumn <br />
&nbsp; &nbsp; FROM OPENROWSET(BULK 'C:\monFichier.txt', SINGLE_CLOB) TMP <br />
&nbsp; ), <br />
&nbsp; CTE_INDICES_LIGNES (Deb, Fin) AS &nbsp;<br />
&nbsp; ( &nbsp;<br />
&nbsp; &nbsp; &nbsp; SELECT 1 Deb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CHARINDEX(CHAR(10), CTE_IMPORT.BulkColumn + CHAR(10)) Fin <br />
&nbsp; &nbsp; &nbsp; FROM CTE_IMPORT <br />
&nbsp; &nbsp; UNION ALL &nbsp;<br />
&nbsp; &nbsp; &nbsp; SELECT CAST(CTE_INDICES_LIGNES.Fin + 1 AS INT), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CHARINDEX(CHAR(10), CTE_IMPORT.BulkColumn + CHAR(10), CTE_INDICES_LIGNES.Fin + 1) <br />
&nbsp; &nbsp; &nbsp; FROM CTE_IMPORT, CTE_INDICES_LIGNES <br />
&nbsp; &nbsp; &nbsp; WHERE CHARINDEX(CHAR(10), CTE_IMPORT.BulkColumn + CHAR(10), CTE_INDICES_LIGNES.Fin + 1 ) &gt; 0 &nbsp;<br />
&nbsp; ) <br />
SELECT SUBSTRING(BulkColumn, CTE_INDICES_LIGNES.Deb, CTE_INDICES_LIGNES.Fin - CTE_INDICES_LIGNES.Deb) AS Colonne <br />
FROM CTE_INDICES_LIGNES <br />
CROSS JOIN CTE_IMPORT <br />
WHERE CTE_INDICES_LIGNES.Deb &lt;&gt; CTE_INDICES_LIGNES.Fin</div></td></tr></tbody></table></div>
<p>Comme on peut s&rsquo;y attendre, c&rsquo;est particulièrement contre-performant :<br />
en activant SET STATISTICS IO puis SET STATISTICS TIME, on obtient successivement, pour un fichier contenant 50 lignes:</p>
<blockquote><p>Table &lsquo;Worktable&rsquo;. Nombre d&rsquo;analyses 3, lectures logiques 810<br />
Temps UC = 40 ms, temps écoulé = 101 ms.</p></blockquote>
<p>Ce snippet s&rsquo;avère donc utile pour faire un import d&rsquo;un faible de nombre de lignes sans passer par une table de base de données, mais il est à éviter pour faire des import massifs.<br />
L&rsquo;utilisation de la CTE permet de plus de réaliser des jointures &#8230;</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connaître l&#8217;état d&#8217;un service : xp_servicecontrol</title>
		<link>https://blog.developpez.com/elsuket/p7806/snippets/connaitre_l_etat_d_un_service_xp_service</link>
		<comments>https://blog.developpez.com/elsuket/p7806/snippets/connaitre_l_etat_d_un_service_xp_service#comments</comments>
		<pubDate>Sat, 27 Jun 2009 06:32:18 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Non documenté]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Comment connaître simplement l&#8217;état d&#8217;un service ? Est-il possible d&#8217;arrêter et de démarrer un service avec une requête ? La procédure stockée système étendue non documentée xp_servicecontrol permet de connaître l&#8217;état d&#8217;un service : EXEC master.dbo.xp_servicecontrol 'QUERYSTATE', 'MSSQLServer' Retourne bien &#8230; <a href="https://blog.developpez.com/elsuket/p7806/snippets/connaitre_l_etat_d_un_service_xp_service">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Comment connaître simplement l&rsquo;état d&rsquo;un service ?<br />
Est-il possible d&rsquo;arrêter et de démarrer un service avec une requête ?</p>
<p><span id="more-48"></span></p>
<p>La procédure stockée système étendue <strong>non documentée</strong> xp_servicecontrol permet de connaître l&rsquo;état d&rsquo;un service :</p>
<p><code class="codecolorer text default"><span class="text">EXEC master.dbo.xp_servicecontrol 'QUERYSTATE', 'MSSQLServer'</span></code></p>
<p>Retourne bien sûr :</p>
<p><img src="http://blog.developpez.com/media/serviceSQLServer.PNG" width="564" height="139" alt="" /></p>
<p>mais peut retourner les états suivants :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">- &quot;Stopped.&quot; <br />
- &quot;Running.&quot; <br />
- &quot;Stopping.&quot; <br />
- &quot;Starting.&quot; <br />
- &quot;Unknown.&quot; <br />
- &quot;ErrorRetrieving.&quot;</div></td></tr></tbody></table></div>
<p>On peut aussi démarrer un service :</p>
<p><code class="codecolorer text default"><span class="text">EXEC master.dbo.xp_servicecontrol 'START', 'MSSQLServer'</span></code></p>
<p>ou encore l&rsquo;arrêter : </p>
<p><code class="codecolorer text default"><span class="text">EXEC master.dbo.xp_servicecontrol 'STOP', 'MSSQLServer'</span></code></p>
<p>Il peut être pratique de connaître l&rsquo;état de services par ce biais, lorsque l&rsquo;on administre une instance de SQL Server avec l&rsquo;utilitaire en ligne de commande <a href="http://msdn.microsoft.com/fr-fr/library/ms162773(SQL.90).aspx">SQLCMD</a> (ancien OSQL) et une connexion <a href="http://msdn.microsoft.com/fr-fr/library/ms189595(SQL.90).aspx">DAC</a>, ou encore encapsuler ce résultat dans un rapport SSRS sur l&rsquo;état d&rsquo;un serveur et de ses applications &#8230;</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Suivre les sauvegardes de base de données avec MSDB</title>
		<link>https://blog.developpez.com/elsuket/p7807/snippets/suivre_les_sauvegardes_de_base_de_donnee</link>
		<comments>https://blog.developpez.com/elsuket/p7807/snippets/suivre_les_sauvegardes_de_base_de_donnee#comments</comments>
		<pubDate>Sat, 27 Jun 2009 07:17:56 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Comment suivre l&#8217;évolution des sauvegardes de base de données avec une requête sur la base de données système MSDB ? L&#8217;exécution de la requête suivante montre, pour chaque sauvegarde de base de données : &#8211; l&#8217;heure de début, &#8211; l&#8217;heure &#8230; <a href="https://blog.developpez.com/elsuket/p7807/snippets/suivre_les_sauvegardes_de_base_de_donnee">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Comment suivre l&rsquo;évolution des sauvegardes de base de données avec une requête sur la base de données système MSDB ?</p>
<p><span id="more-6"></span></p>
<p>L&rsquo;exécution de la requête suivante montre, pour chaque sauvegarde de base de données :</p>
<p>&#8211; l&rsquo;heure de début,<br />
&#8211; l&rsquo;heure de fin,<br />
&#8211; la durée,<br />
&#8211; la taille,<br />
&#8211; l&rsquo;emplacement du fichier de sauvegarde,<br />
&#8211; quelques autres caractéristiques de la sauvegarde &#8230;</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 27/06/2009 - <br />
--------------------------------- <br />
SELECT database_name, <br />
&nbsp; &nbsp; physical_drive, <br />
&nbsp; &nbsp; physical_name, <br />
&nbsp; &nbsp; physical_device_name, <br />
&nbsp; &nbsp; logical_name, <br />
&nbsp; &nbsp; CAST(SUM(file_size) / 1048576 AS NUMERIC (10, 2)) AS Taille, <br />
&nbsp; &nbsp; name, <br />
&nbsp; &nbsp; user_name, <br />
&nbsp; &nbsp; database_creation_date, <br />
&nbsp; &nbsp; backup_start_date, <br />
&nbsp; &nbsp; backup_finish_date, <br />
&nbsp; &nbsp; Duree, <br />
&nbsp; &nbsp; Type, <br />
&nbsp; &nbsp; server_name, <br />
&nbsp; &nbsp; machine_name, <br />
&nbsp; &nbsp; recovery_model, <br />
&nbsp; &nbsp; is_snapshot, <br />
&nbsp; &nbsp; is_damaged, <br />
&nbsp; &nbsp; has_incomplete_metadata <br />
FROM <br />
( <br />
&nbsp; SELECT F.physical_drive, <br />
&nbsp; &nbsp; F.physical_name, <br />
&nbsp; &nbsp; F.logical_name, <br />
&nbsp; &nbsp; F.file_size, <br />
&nbsp; &nbsp; S.name, <br />
&nbsp; &nbsp; S.user_name, <br />
&nbsp; &nbsp; S.database_creation_date, <br />
&nbsp; &nbsp; S.backup_start_date, <br />
&nbsp; &nbsp; S.backup_finish_date, <br />
&nbsp; &nbsp; CASE LEN(CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) / 3600 AS VARCHAR(4))) <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '0' + CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) / 3600 AS VARCHAR(4)) <br />
&nbsp; &nbsp; &nbsp; ELSE CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) / 3600 AS VARCHAR(4)) <br />
&nbsp; &nbsp; END + ':' + <br />
&nbsp; &nbsp; CASE LEN(CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) / 60 % 60 AS VARCHAR(2))) <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '0' + CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) / 60 % 60 AS VARCHAR(2)) <br />
&nbsp; &nbsp; &nbsp; ELSE CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) / 60 % 60 AS VARCHAR(2)) <br />
&nbsp; &nbsp; END + ':' + <br />
&nbsp; &nbsp; CASE LEN(CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) % 60 AS VARCHAR(2))) <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '0' + CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) % 60 AS VARCHAR(2)) <br />
&nbsp; &nbsp; &nbsp; ELSE CAST(DATEDIFF(second, S.backup_start_date, S.backup_finish_date) % 60 AS VARCHAR(2)) <br />
&nbsp; &nbsp; END Duree, <br />
&nbsp; &nbsp; CASE S.type <br />
&nbsp; &nbsp; &nbsp; WHEN 'D' THEN 'Base de données - Complet' <br />
&nbsp; &nbsp; &nbsp; WHEN 'I' THEN 'Base de données - Différentiel' <br />
&nbsp; &nbsp; &nbsp; WHEN 'L' THEN 'Journal de transactions' <br />
&nbsp; &nbsp; &nbsp; WHEN 'F' THEN 'Fichier ou groupe de fichiers' <br />
&nbsp; &nbsp; &nbsp; WHEN 'G' THEN 'Fichier - Différentiel' <br />
&nbsp; &nbsp; &nbsp; WHEN 'P' THEN 'Partiel' <br />
&nbsp; &nbsp; &nbsp; WHEN 'Q' THEN 'Partiel - Différentiel' <br />
&nbsp; &nbsp; END Type, <br />
&nbsp; &nbsp; S.database_name, <br />
&nbsp; &nbsp; S.server_name, <br />
&nbsp; &nbsp; S.machine_name, <br />
&nbsp; &nbsp; S.recovery_model, <br />
&nbsp; &nbsp; S.is_snapshot, <br />
&nbsp; &nbsp; S.is_damaged, <br />
&nbsp; &nbsp; S.has_incomplete_metadata, <br />
&nbsp; &nbsp; FAM.physical_device_name <br />
&nbsp; FROM msdb.dbo.backupfile AS F &nbsp;<br />
&nbsp; JOIN msdb.dbo.backupset AS S &nbsp;<br />
&nbsp; &nbsp; ON F.backup_set_id = S.backup_set_id <br />
&nbsp; JOIN msdb.dbo.backupmediafamily AS FAM <br />
&nbsp; &nbsp; ON FAM.media_set_id = S.media_set_id <br />
&nbsp; WHERE S.backup_start_date BETWEEN CAST(FLOOR(CAST(GETDATE()- 2 AS FLOAT)) AS DATETIME) AND GETDATE() <br />
) AS SUB <br />
GROUP BY physical_drive, <br />
&nbsp; &nbsp; physical_name, <br />
&nbsp; &nbsp; physical_device_name, <br />
&nbsp; &nbsp; logical_name, <br />
&nbsp; &nbsp; name, <br />
&nbsp; &nbsp; user_name, <br />
&nbsp; &nbsp; database_creation_date, <br />
&nbsp; &nbsp; backup_start_date, <br />
&nbsp; &nbsp; backup_finish_date, <br />
&nbsp; &nbsp; Duree, <br />
&nbsp; &nbsp; Type, <br />
&nbsp; &nbsp; database_name, <br />
&nbsp; &nbsp; server_name, &nbsp;<br />
&nbsp; &nbsp; machine_name, &nbsp;<br />
&nbsp; &nbsp; recovery_model, &nbsp;<br />
&nbsp; &nbsp; is_snapshot, &nbsp;<br />
&nbsp; &nbsp; is_damaged, &nbsp;<br />
&nbsp; &nbsp; has_incomplete_metadata <br />
ORDER BY database_name, backup_start_date</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Découper une chaîne en sous-chaînes de longueur fixe</title>
		<link>https://blog.developpez.com/elsuket/p7818/snippets/decouper_une_chaine_en_sous_chaines_de_l</link>
		<comments>https://blog.developpez.com/elsuket/p7818/snippets/decouper_une_chaine_en_sous_chaines_de_l#comments</comments>
		<pubDate>Wed, 01 Jul 2009 06:12:23 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Certains me désignent sur le forum SQL Server comme l&#8217;homme qui murmure à l&#8217;oreille des CTE. En voici donc une nouvelle ! 1234567891011121314151617181920--------------------------------- -- Nicolas SOUQUET - 01/07/2009 - --------------------------------- DECLARE @toto VARCHAR(50) = 'ABCDEFGHIJKLM' SELECT LEN(@toto) &#160; ;WITH &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p7818/snippets/decouper_une_chaine_en_sous_chaines_de_l">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Certains me désignent sur le forum SQL Server comme l&rsquo;homme qui murmure à l&rsquo;oreille des CTE.<br />
En voici donc une nouvelle !</p>
<p><span id="more-49"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 01/07/2009 - <br />
--------------------------------- <br />
DECLARE @toto VARCHAR(50) = 'ABCDEFGHIJKLM' <br />
SELECT LEN(@toto) <br />
&nbsp;<br />
;WITH <br />
&nbsp; CTE AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT SUBSTRING(@toto, 1, 4) AS sousChaine, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 AS nFinSousChaine <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; SELECT SUBSTRING(@toto, nFinSousChaine + 4, 4) AS sousChaine, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nFinSousChaine + 4 AS nFinSousChaine <br />
&nbsp; &nbsp; &nbsp; FROM CTE <br />
&nbsp; &nbsp; &nbsp; WHERE nFinSousChaine &lt;= LEN(@toto) <br />
&nbsp; ) <br />
SELECT sousChaine <br />
FROM CTE <br />
WHERE nFinSousChaine &lt;= LEN(@toto)</div></td></tr></tbody></table></div>
<p>Retourne :</p>
<blockquote><p>sousChaine<br />
&#8212;&#8212;&#8212;-<br />
ABCD<br />
EFGH<br />
IJKL<br />
M</p></blockquote>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Consulter l&#8217;historique des restaurations de bases de données</title>
		<link>https://blog.developpez.com/elsuket/p7914/snippets/consulter_l_historique_des_restaurations</link>
		<comments>https://blog.developpez.com/elsuket/p7914/snippets/consulter_l_historique_des_restaurations#comments</comments>
		<pubDate>Thu, 30 Jul 2009 17:09:21 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une petite requête qui permet de voir toutes les restaurations de bases de données d&#8217;une instance &#8230; 12345678910111213141516171819--------------------------------- -- Nicolas SOUQUET - 30/07/2009 - --------------------------------- SELECT H.restore_date, &#160; &#160; H.destination_database_name, &#160; &#160; H.user_name, &#160; &#160; CASE restore_type &#160; &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p7914/snippets/consulter_l_historique_des_restaurations">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une petite requête qui permet de voir toutes les restaurations de bases de données d&rsquo;une instance &#8230;</p>
<p><span id="more-54"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 30/07/2009 - <br />
--------------------------------- <br />
SELECT H.restore_date, <br />
&nbsp; &nbsp; H.destination_database_name, <br />
&nbsp; &nbsp; H.user_name, <br />
&nbsp; &nbsp; CASE restore_type <br />
&nbsp; &nbsp; &nbsp; WHEN 'D' THEN 'Base de données' <br />
&nbsp; &nbsp; &nbsp; WHEN 'F' THEN 'Fichier' <br />
&nbsp; &nbsp; &nbsp; WHEN 'G' THEN 'Groupe de fichiers' <br />
&nbsp; &nbsp; &nbsp; WHEN 'I' THEN 'Différentiel' <br />
&nbsp; &nbsp; &nbsp; WHEN 'L' THEN 'Fichier du journal des transactions' <br />
&nbsp; &nbsp; &nbsp; WHEN 'V' THEN 'Vérification' <br />
&nbsp; &nbsp; &nbsp; WHEN 'R' THEN 'Par capture instantanée' <br />
&nbsp; &nbsp; END AS restore_type, <br />
&nbsp; &nbsp; F.destination_phys_name <br />
FROM msdb.dbo.restorehistory AS H <br />
JOIN msdb.dbo.restorefile AS F <br />
&nbsp; ON H.restore_history_id &nbsp;= F.restore_history_id</div></td></tr></tbody></table></div>
<p>Facile à placer dans un rapport SSRS <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lister les contraintes CHECK qui utilisent une fonction définie par l&#8217;utilisateur</title>
		<link>https://blog.developpez.com/elsuket/p7969/snippets/lister_les_contraintes_check_qui_utilise</link>
		<comments>https://blog.developpez.com/elsuket/p7969/snippets/lister_les_contraintes_check_qui_utilise#comments</comments>
		<pubDate>Thu, 20 Aug 2009 17:32:19 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici un snippet qui vous permettra de trouver tous les contraintes de domaines qui font référence à une fonction que vous avez défini 123456789101112131415------------------------------- -- Nicolas SOUQUET - 20/08/2009 ------------------------------- SELECT T.name AS nomTable, &#160; &#160; C.name AS nomColonne, &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p7969/snippets/lister_les_contraintes_check_qui_utilise">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici un snippet qui vous permettra de trouver tous les contraintes de domaines qui font référence à une fonction que vous avez défini <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------- <br />
-- Nicolas SOUQUET - 20/08/2009 <br />
------------------------------- <br />
SELECT T.name AS nomTable, <br />
&nbsp; &nbsp; C.name AS nomColonne, <br />
&nbsp; &nbsp; CHK.name AS nomContrainte, <br />
&nbsp; &nbsp; CHK.definition AS DefinitionContrainte <br />
FROM sys.tables AS T -- Tables <br />
JOIN sys.columns AS C <br />
&nbsp; &nbsp; ON T.object_id = C.object_id -- Colonnes <br />
JOIN sys.check_constraints AS CHK -- contraintes CHECK &nbsp; <br />
&nbsp; &nbsp; ON CHK.parent_object_id = T.object_id &nbsp; <br />
&nbsp; &nbsp; AND CHK.parent_column_id = C.column_id <br />
WHERE CHK.definition LIKE '%maFonction%' <br />
ORDER BY T.name</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comment exécuter une procédure stockée dès le démarrage de SQL Server ?</title>
		<link>https://blog.developpez.com/elsuket/p7964/snippets/comment_executer_une_procedure_stockee_d</link>
		<comments>https://blog.developpez.com/elsuket/p7964/snippets/comment_executer_une_procedure_stockee_d#comments</comments>
		<pubDate>Tue, 18 Aug 2009 18:46:42 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Nous allons voir comment on peut exécuter n&#8217;importe quelle procédure stockée dès le démarrage de SQL Server, à l&#8217;aide de la procédure stockée sp_procoption Il peut être parfois intéressant de démarrer une application, ou d&#8217;exécuter une requête dès le démarrage &#8230; <a href="https://blog.developpez.com/elsuket/p7964/snippets/comment_executer_une_procedure_stockee_d">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Nous allons voir comment on peut exécuter n&rsquo;importe quelle procédure stockée dès le démarrage de SQL Server, à l&rsquo;aide de la procédure stockée sp_procoption</p>
<p><span id="more-56"></span></p>
<p>Il peut être parfois intéressant de démarrer une application, ou d&rsquo;exécuter une requête dès le démarrage du service SQL Server.</p>
<p>Cela requiert :</p>
<p>=> que la procédure soit stockée dans la base de données système master : en effet, la procédure stockée à créer sera exécutée dès la récupération de cette base de données, qui est la première à être récupérée.<br />
=> que la procédure n&rsquo;accepte aucun paramètre en entrée, ni aucun paramètre en sortie (propriété OUTPUT interdite)</p>
<p>Supposons que nous souhaitons par exemple savoir à quelle heure le serveur a redémarré, en cas de crash.<br />
Cela n&rsquo;est pas vraiment utile puisque nous pouvons le savoir à l&rsquo;aide des journaux SQL Server :</p>
<p><img src="http://blog.developpez.com/media/sp_proctoption1.PNG" width="399" height="363" alt="" /></p>
<p>Mais nous nous en servirons simplement pour l&rsquo;exemple.</p>
<p>Nous pouvons tout aussi bien démarrer un service Windows à l&rsquo;aide de la procédure stockée système <a href="http://blog.developpez.com/elsuket/p7806/snippets/connaitre-l-etat-d-un-service-xp-service/">xp_servicecontrol</a>, ou encore exécuter une application à l&rsquo;aide d&rsquo;une autre procédure stockée étendue système <a href="http://msdn.microsoft.com/fr-fr/library/ms175046.aspx">xp_cmdshell</a></p>
<p>Créons la table suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">USE MASTER <br />
GO <br />
&nbsp;<br />
CREATE TABLE TbDatesRedemarrageSQLServer <br />
( <br />
&nbsp; dateRedemarrageSQLServer DATETIME <br />
) <br />
GO</div></td></tr></tbody></table></div>
<p>Créons maintenant notre procédure stockée :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE PROCEDURE PsGetHeureRedemarrageSQLServer <br />
AS <br />
BEGIN <br />
&nbsp; INSERT INTO dbo.TbDatesRedemarrageSQLServer <br />
&nbsp; ( <br />
&nbsp; &nbsp; dateRedemarrageSQLServer <br />
&nbsp; ) <br />
&nbsp; SELECT GETDATE() -- retourne la date courante <br />
END</div></td></tr></tbody></table></div>
<p>Marquons cette procédure stockée comme devant être exécutée au démarrage de l&rsquo;instance SQL Server.</p>
<p>Nous pouvons exécuter :<br />
<code class="codecolorer text default"><span class="text">EXEC master.dbo.sp_procoption 'PsGetHeureRedemarrageSQLServer', 'startup', 'on'</span></code></p>
<p>mais aussi :</p>
<p><code class="codecolorer text default"><span class="text">EXEC master.dbo.sp_procoption 'PsGetHeureRedemarrageSQLServer', 'startup', 'true'</span></code></p>
<p>Comme vous le voyez :</p>
<p>&#8211; le premier paramètre est le nom de la procédure a exécuter. Ce ne peut pas être un autre type de module SQL (fonction, &#8230;)<br />
&#8211; le second paramètre est obligatoirement &lsquo;startup&rsquo;, la procédure n&rsquo;acceptant pas d&rsquo;autre valeurs<br />
&#8211; le troisième paramètre peut prendre les valeurs suivantes :  &lsquo;on&rsquo;, &lsquo;off&rsquo;, &lsquo;true&rsquo;, &lsquo;false&rsquo;.</p>
<p>Les valeurs &lsquo;on&rsquo; est &lsquo;true&rsquo; ont le même effet : celui d&rsquo;activer la procédure pour l&rsquo;exécution dès le redémarrage de SQL Server<br />
Les valeurs &lsquo;off&rsquo; est &lsquo;false&rsquo; ont l&rsquo;effet inverse</p>
<p>Arrêtons maintenant le service SQL Server :</p>
<p><img src="http://blog.developpez.com/media/sp_proctoption2.gif" width="395" height="378" alt="" /></p>
<p>Redémarrons-le : </p>
<p><img src="http://blog.developpez.com/media/sp_proctoption3.gif" width="391" height="386" alt="" /></p>
<p><img src="http://blog.developpez.com/media/sp_proctoption4.gif" width="611" height="135" alt="" /></p>
<p><img src="http://blog.developpez.com/media/sp_proctoption5.gif" width="579" height="146" alt="" /></p>
<p>Exécutons la requête suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT dateRedemarrageSQLServer <br />
FROM master.dbo.TbDatesRedemarrageSQLServer</div></td></tr></tbody></table></div>
<p><img src="http://blog.developpez.com/media/sp_proctoption6.gif" width="830" height="367" alt="" /></p>
<p>ElSüket </p>
<p>Merci à <a href="http://blog.developpez.com/mikedavem/">MikeDavem</a> <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caractériser une adresse IP</title>
		<link>https://blog.developpez.com/elsuket/p7935/snippets/caracteriser_une_adresse_ip</link>
		<comments>https://blog.developpez.com/elsuket/p7935/snippets/caracteriser_une_adresse_ip#comments</comments>
		<pubDate>Sun, 09 Aug 2009 09:54:36 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une procédure stockée pour : &#8211; vérifier une adresse IP &#8211; chercher si celle-ci est privée &#8211; chercher la classe de cette adresse IP 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163------------------------------------------------------------ -- Nicolas SOUQUET - 08/08/2009 - Vérifie une adresse IP -- &#160; &#160; &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p7935/snippets/caracteriser_une_adresse_ip">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une procédure stockée pour :</p>
<p>&#8211; vérifier une adresse IP<br />
&#8211; chercher si celle-ci est privée<br />
&#8211; chercher la classe de cette adresse IP</p>
<p><span id="more-55"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br />134<br />135<br />136<br />137<br />138<br />139<br />140<br />141<br />142<br />143<br />144<br />145<br />146<br />147<br />148<br />149<br />150<br />151<br />152<br />153<br />154<br />155<br />156<br />157<br />158<br />159<br />160<br />161<br />162<br />163<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------------------ <br />
-- Nicolas SOUQUET - 08/08/2009 - Vérifie une adresse IP <br />
-- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- Extrait sa classe <br />
-- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- Vérifie si elle est privée <br />
/* <br />
DECLARE @IP VARCHAR(15), <br />
&nbsp; &nbsp; @OK BIT, <br />
&nbsp; &nbsp; @classe CHAR(1), <br />
&nbsp; &nbsp; @privee BIT <br />
&nbsp;<br />
SET @IP = '172.220.10.1' <br />
&nbsp;<br />
EXEC dbo.PsCheck_AdresseIP <br />
&nbsp; @IP, <br />
&nbsp; @OK OUTPUT, <br />
&nbsp; @classe OUTPUT, <br />
&nbsp; @privee OUTPUT <br />
&nbsp;<br />
SELECT @OK AS OK, <br />
&nbsp; &nbsp; @classe AS classe, <br />
&nbsp; &nbsp; @privee AS privee <br />
*/ <br />
------------------------------------------------------------ <br />
ALTER PROCEDURE PsCheck_AdresseIP <br />
&nbsp; @adresseIP VARCHAR(15), <br />
&nbsp; @estAdresseIPCorrecte BIT = NULL OUTPUT, <br />
&nbsp; @classeAdresseIP CHAR(1) = NULL OUTPUT, <br />
&nbsp; @estPrivee BIT = NULL OUTPUT <br />
AS <br />
BEGIN <br />
&nbsp; SET NOCOUNT ON <br />
&nbsp;<br />
&nbsp; SELECT @estAdresseIPCorrecte = 1, <br />
&nbsp; &nbsp; &nbsp; @estPrivee = 0 <br />
&nbsp;<br />
&nbsp; IF <br />
&nbsp; ( <br />
&nbsp; &nbsp; @adresseIP IS NULL <br />
&nbsp; &nbsp; OR @adresseIP NOT LIKE '%.%.%.%' <br />
&nbsp; ) <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; SET @estAdresseIPCorrecte = 0 <br />
&nbsp; END <br />
&nbsp; ELSE <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; ----------------------------------------- <br />
&nbsp; &nbsp; -- Recherche de la valeur de chaque octet <br />
&nbsp; &nbsp; ----------------------------------------- <br />
&nbsp; &nbsp; DECLARE @octet1 TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @octet2 TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @octet3 TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @octet4 TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; --- <br />
&nbsp; &nbsp; &nbsp; &nbsp; @indiceFinPremierOctet TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @indiceFinDeuxiemeOctet TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @indiceFinTroisiemeOctet TINYINT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @indiceFinQuatriemeOctect TINYINT <br />
&nbsp;<br />
&nbsp; &nbsp; SELECT @indiceFinPremierOctet = CHARINDEX('.', @adresseIP), <br />
&nbsp; &nbsp; &nbsp; &nbsp; @indiceFinDeuxiemeOctet = CHARINDEX('.', @adresseIP, @indiceFinPremierOctet + 1), <br />
&nbsp; &nbsp; &nbsp; &nbsp; @indiceFinTroisiemeOctet = CHARINDEX('.', @adresseIP, @indiceFinDeuxiemeOctet + 1) <br />
&nbsp;<br />
&nbsp; &nbsp; BEGIN TRY <br />
&nbsp; &nbsp; &nbsp; SELECT @octet1 = CAST(SUBSTRING(@adresseIP, 1, @indiceFinPremierOctet - 1) AS TINYINT), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet2 = CAST(SUBSTRING(@adresseIP, @indiceFinPremierOctet + 1, @indiceFinDeuxiemeOctet - @indiceFinPremierOctet - 1) AS TINYINT), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet3 = CAST(SUBSTRING(@adresseIP, @indiceFinDeuxiemeOctet + 1, @indiceFinTroisiemeOctet - @indiceFinDeuxiemeOctet - 1) AS TINYINT), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet4 = CAST(RIGHT(@adresseIP, LEN(@adresseIP) - @indiceFinTroisiemeOctet) AS TINYINT) <br />
&nbsp; &nbsp; END TRY <br />
&nbsp; &nbsp; BEGIN CATCH <br />
&nbsp; &nbsp; &nbsp; RAISERROR('Une des octets de l''adresse IP est incorrect', 16, 1) <br />
&nbsp; &nbsp; END CATCH <br />
&nbsp;<br />
&nbsp; &nbsp; -------------------------------------- <br />
&nbsp; &nbsp; -- Recherche de la classe de l'adresse <br />
&nbsp; &nbsp; -------------------------------------- <br />
&nbsp; &nbsp; -- Classe A <br />
&nbsp; &nbsp; IF @octet1 BETWEEN 1 AND 126 <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SET @classeAdresseIP = 'A' <br />
&nbsp; &nbsp; END <br />
&nbsp;<br />
&nbsp; &nbsp; -- Classe B <br />
&nbsp; &nbsp; IF <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; @octet1 BETWEEN 128 AND 190 <br />
&nbsp; &nbsp; &nbsp; OR <br />
&nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 191 <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND @octet3 = 0 <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND @octet4 = 0 <br />
&nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; ) <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SET @classeAdresseIP = 'B' <br />
&nbsp; &nbsp; END <br />
&nbsp;<br />
&nbsp; &nbsp; -- Classe C <br />
&nbsp; &nbsp; IF <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; @octet1 BETWEEN 191 AND 222 <br />
&nbsp; &nbsp; &nbsp; OR <br />
&nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 223 <br />
&nbsp; &nbsp; &nbsp; &nbsp; AND @octet4 = 0 <br />
&nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; ) <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SET @classeAdresseIP = 'C' <br />
&nbsp; &nbsp; END <br />
&nbsp;<br />
&nbsp; &nbsp; IF @classeAdresseIP IS NULL <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SET @estAdresseIPCorrecte = 0 <br />
&nbsp; &nbsp; END <br />
&nbsp;<br />
&nbsp; &nbsp; ------------------------------------ <br />
&nbsp; &nbsp; -- Recherche si l'adresse est privée <br />
&nbsp; &nbsp; ------------------------------------ <br />
&nbsp; &nbsp; IF <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; ( &nbsp;-- Classe A <br />
&nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 10 <br />
&nbsp; &nbsp; &nbsp; &nbsp; OR <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 10 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet2 = 255 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet3 = 255 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet4 = 254 <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; OR -- Classe B <br />
&nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 172 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet2 BETWEEN 16 AND 31 <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; &nbsp; OR <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 172 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet2 = 31 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet3 = 255 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet4 = 254 <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; OR -- Classe C <br />
&nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 192 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet2 = 168 <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; &nbsp; OR <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @octet1 = 192 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet1 = 168 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet3 = 255 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND @octet4 = 254 <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; &nbsp; ) <br />
&nbsp; &nbsp; ) <br />
&nbsp; &nbsp; SET @estPrivee = 1 <br />
&nbsp; END <br />
END</div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Créer une table de dates</title>
		<link>https://blog.developpez.com/elsuket/p7872/snippets/creer_une_table_de_dates</link>
		<comments>https://blog.developpez.com/elsuket/p7872/snippets/creer_une_table_de_dates#comments</comments>
		<pubDate>Fri, 10 Jul 2009 18:23:08 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pourquoi ne pas créer une table de dates pour se faciliter les recherches dans des tables suivant la colonne de type date qu&#8217;elles contiennent ? On peut vous demander par exemple de rechercher la quantité d&#8217;eau consommée par un parc &#8230; <a href="https://blog.developpez.com/elsuket/p7872/snippets/creer_une_table_de_dates">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Pourquoi ne pas créer une table de dates pour se faciliter les recherches dans des tables suivant la colonne de type date qu&rsquo;elles contiennent ?<br />
On peut vous demander par exemple de rechercher la quantité d&rsquo;eau consommée par un parc de machines pour la deuxième semaine de chaque mois d&rsquo;une année.<br />
Imaginez un peu la complexité de la requête à écrire &#8230;<br />
Voyons comment on peut résoudre cette demande très facilement en créant une table de dates &#8230;</p>
<p><span id="more-52"></span></p>
<p>Voici donc notre table :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - <br />
--------------------------------- <br />
CREATE TABLE TbDates <br />
( <br />
&nbsp; date DATETIME NOT NULL CONSTRAINT PK_TbDates_date PRIMARY KEY, <br />
&nbsp; annee AS (YEAR(date)) PERSISTED NOT NULL, <br />
&nbsp; mois AS(MONTH(date)) PERSISTED NOT NULL, <br />
&nbsp; semaineDansAnnee AS(DATEPART(week, date)) PERSISTED NOT NULL, <br />
&nbsp; semaineDansMois AS(DATEPART(week, date) - DATEPART(week, DATEADD(day, -DATEPART(day, date) + 1, date)) + 1) &nbsp;PERSISTED NOT NULL, <br />
&nbsp; jourDansAnnee AS (DATEPART(dayofyear, date)) PERSISTED NOT NULL, <br />
&nbsp; jourDansMois AS(DAY(date)) PERSISTED NOT NULL, <br />
&nbsp; jourDansSemaine TINYINT NULL CONSTRAINT CHK_TbDates_jourDansSemaine CHECK(jourDansSemaine BETWEEN 0 AND 7), <br />
) <br />
GO</div></td></tr></tbody></table></div>
<p>Comme toutes les colonnes sont calculées à l&rsquo;exception de <em>jourDansSemaine </em> (parce que la fonction <em>DATEPART(weekday, date)</em> n&rsquo;est pas déterministe, elle ne peut pas être utilisée comme spécification d&rsquo;une colonne calculée), nous n&rsquo;aurons donc qu&rsquo;à insérer les dates dans la colonne <em>date</em>.</p>
<p>Comment allons-nous valuer la colonne <em>jourDansSemaine </em> ? Avec le trigger suivant :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - Déclencheur qui calcule le jour de la semaine - <br />
-- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pour la table dbo.TbDates &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - <br />
--------------------------------------------------------------------------------- <br />
CREATE TRIGGER TR_A_I_TbDates <br />
&nbsp; ON dbo.TbDates <br />
&nbsp; AFTER INSERT <br />
AS <br />
BEGIN <br />
&nbsp; SET NOCOUNT ON <br />
&nbsp;<br />
&nbsp; UPDATE dbo.TbDates <br />
&nbsp; SET jourDansSemaine = DATEPART(weekday, D.date) <br />
&nbsp; FROM dbo.TbDates AS D <br />
&nbsp; JOIN INSERTED AS I <br />
&nbsp; &nbsp; ON D.date = I.date <br />
END <br />
GO</div></td></tr></tbody></table></div>
<p>Et pour stocker les dates, il suffira d&rsquo;exécuter la procédure stockée suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">----------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - Procédure de génération de tous les jours d'une année - <br />
----------------------------------------------------------------------------------------- <br />
ALTER PROCEDURE Ps_GenereDatesAnnee <br />
&nbsp; @annee SMALLINT <br />
AS <br />
BEGIN <br />
&nbsp; SET NOCOUNT ON <br />
&nbsp;<br />
&nbsp; DECLARE @dateDeb DATETIME, <br />
&nbsp; &nbsp; &nbsp; @dateFin DATETIME <br />
&nbsp;<br />
&nbsp; SELECT @dateDeb = CAST(CAST(@annee AS VARCHAR) + '0101' AS DATETIME), <br />
&nbsp; &nbsp; &nbsp; @dateFin = CAST(CAST(@annee AS VARCHAR) + '1231' AS DATETIME) <br />
&nbsp; <br />
&nbsp; ;WITH <br />
&nbsp; &nbsp; CTE_DATES AS <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT @dateDeb AS Date <br />
&nbsp; &nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT Date + 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM CTE_DATES <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHERE Date &lt;= @dateFin <br />
&nbsp; &nbsp; ) <br />
&nbsp; SELECT Date <br />
&nbsp; FROM CTE_DATES <br />
&nbsp; WHERE Date &lt;= @dateFin <br />
&nbsp; OPTION (MAXRECURSION 366) <br />
END</div></td></tr></tbody></table></div>
<p>Ainsi pour stocker tous les jours de l&rsquo;année 2009, il suffira d&rsquo;exécuter :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - &nbsp;<br />
--------------------------------- <br />
ALTER TABLE dbo.TbDates <br />
ALTER COLUMN jourDansSemaine TINYINT NULL <br />
GO <br />
INSERT INTO dbo.TbDates (date) &nbsp;<br />
EXEC dbo.Ps_GenereDatesAnnee 2009 <br />
GO <br />
ALTER TABLE dbo.TbDates <br />
ALTER COLUMN jourDansSemaine TINYINT NOT NULL <br />
GO</div></td></tr></tbody></table></div>
<p>Pour voir ce que contient la table après cette insertion :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - &nbsp;<br />
--------------------------------- <br />
SELECT date, annee, mois, semaineDansAnnee, semaineDansMois, jourDansAnnee, jourDansMois, jourDansSemaine <br />
FROM dbo.TbDates</div></td></tr></tbody></table></div>
<p>Finalement, pour rechercher la quantité d&rsquo;eau consommée par un parc de machines pour la deuxième semaine de chaque mois de l&rsquo;année 2009, nous devrons écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - &nbsp;<br />
--------------------------------- <br />
SELECT SUM(T.conso) AS consoDeuxiemeSemaine2009 <br />
FROM dbo.maTable AS T <br />
JOIN dbo.TbDates AS D <br />
&nbsp; ON T.colonneDate = D.date <br />
WHERE D.semaineDansLeMois = 2 <br />
AND D.annee = 2009</div></td></tr></tbody></table></div>
<p>Une autre exemple : rechercher la consommation moyenne d&rsquo;eau par semaine dans le mois, pour toute l&rsquo;année 2009 :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 10/07/2009 - &nbsp;<br />
--------------------------------- <br />
SELECT semaineDansLeMois, AVG(consoSemaine) <br />
FROM <br />
( <br />
&nbsp; SELECT D.semaineDansLeMois, SUM(T.conso) AS consoSemaine <br />
&nbsp; FROM dbo.maTable AS T &nbsp;<br />
&nbsp; JOIN dbo.TbDates AS D &nbsp;<br />
&nbsp; &nbsp; ON T.colonneDate = D.date &nbsp;<br />
&nbsp; WHERE D.annee = 2009 <br />
&nbsp; GROUP BY D.semaineDansLeMois <br />
) AS SUB (semaineDansLeMois, consoSemaine) <br />
GROUP BY semaineDansLeMois</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Détecter un caractère unicode dans une chaîne de caractères</title>
		<link>https://blog.developpez.com/elsuket/p7886/snippets/detecter_un_caractere_unicode_dans_une_c</link>
		<comments>https://blog.developpez.com/elsuket/p7886/snippets/detecter_un_caractere_unicode_dans_une_c#comments</comments>
		<pubDate>Fri, 17 Jul 2009 16:30:46 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une petite fonction qui permet de vérifier la présence d&#8217;un caractère qui n&#8217;est pas supporté par la norme ASCII dans une chaîne de caractères &#8230; 12345678910111213141516171819202122232425262728293031--------------------------------- -- Nicolas SOUQUET - 17/07/2009 - --------------------------------- CREATE FUNCTION Fn_CheckUnicode (@chaine NVARCHAR(MAX)) &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p7886/snippets/detecter_un_caractere_unicode_dans_une_c">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une petite fonction qui permet de vérifier la présence d&rsquo;un caractère qui n&rsquo;est pas supporté par la norme ASCII dans une chaîne de caractères &#8230;</p>
<p><span id="more-53"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 17/07/2009 - <br />
--------------------------------- <br />
CREATE FUNCTION Fn_CheckUnicode (@chaine NVARCHAR(MAX)) <br />
&nbsp; RETURNS BIT <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; DECLARE @i INT, <br />
&nbsp; &nbsp; &nbsp; @lgr INT, <br />
&nbsp; &nbsp; &nbsp; @caractere NCHAR(1), <br />
&nbsp; &nbsp; &nbsp; @contientCaractereUnicode BIT <br />
&nbsp;<br />
&nbsp; SELECT @i = 1, <br />
&nbsp; &nbsp; &nbsp; @lgr = LEN(@chaine), <br />
&nbsp; &nbsp; &nbsp; @contientCaractereUnicode = 0 <br />
&nbsp;<br />
&nbsp; WHILE @i &lt;= @lgr AND @contientCaractereUnicode = 0 <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; SELECT @caractere = SUBSTRING(@chaine, @i, 1) <br />
&nbsp;<br />
&nbsp; &nbsp; IF ASCII(@caractere) &lt;&gt; UNICODE(@caractere) <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SET @contientCaractereUnicode = 1 <br />
&nbsp; &nbsp; END <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; SET @i = @i + 1 <br />
&nbsp; END <br />
&nbsp;<br />
&nbsp; RETURN @contientCaractereUnicode <br />
END</div></td></tr></tbody></table></div>
<p>Et un exemple d&rsquo;utilisation :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 17/07/2009 - <br />
--------------------------------- <br />
SELECT dbo.Fn_CheckUnicode(N'toto')</div></td></tr></tbody></table></div>
<p>retourne 0</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 17/07/2009 - <br />
--------------------------------- <br />
SELECT dbo.Fn_CheckUnicode(N'&amp;#3626;t&amp;#3623;&amp;#3633;o&amp;#3626;t&amp;#3604;&amp;#3637;o')</div></td></tr></tbody></table></div>
<p>retourne 1.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ajouter des contraintes à des tables déjà existantes</title>
		<link>https://blog.developpez.com/elsuket/p7900/moteur-de-base-de-donnees-sql-server/indexation/ajouter_des_contraintes_a_des_tables_dej</link>
		<comments>https://blog.developpez.com/elsuket/p7900/moteur-de-base-de-donnees-sql-server/indexation/ajouter_des_contraintes_a_des_tables_dej#comments</comments>
		<pubDate>Sat, 25 Jul 2009 14:07:42 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Indexation]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Comment peut-on ajouter des contraintes de tous types à une table qui existe déjà, mais dont on a modifié la structure ou tout simplement oublié d&#8217;ajouter la contrainte en même temps que la colonne ? Considérons le DDL des tables &#8230; <a href="https://blog.developpez.com/elsuket/p7900/moteur-de-base-de-donnees-sql-server/indexation/ajouter_des_contraintes_a_des_tables_dej">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Comment peut-on ajouter des contraintes de tous types à une table qui existe déjà, mais dont on a modifié la structure ou tout simplement oublié d&rsquo;ajouter la contrainte en même temps que la colonne ?</p>
<p><span id="more-7"></span></p>
<p>Considérons le DDL des tables suivantes :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
CREATE TABLE TbPays <br />
( <br />
&nbsp; IDPays INT IDENTITY, <br />
&nbsp; nomPays VARCHAR(30), <br />
&nbsp; prefixeTelephonique VARCHAR(4), <br />
&nbsp; longueurNumeroTelephone TINYINT <br />
) <br />
&nbsp;<br />
CREATE TABLE TbClient <br />
( <br />
&nbsp; IDClient INT IDENTITY, <br />
&nbsp; nomClient VARCHAR(20), <br />
&nbsp; IDPays INT, <br />
&nbsp; numeroTelephoneClient VARCHAR(36) <br />
) <br />
&nbsp;<br />
CREATE TABLE TbAbonnement &nbsp;<br />
( <br />
&nbsp; IDAbonnement INT IDENTITY, <br />
&nbsp; referenceAbonnement CHAR(10), <br />
&nbsp; nomAbonnement VARCHAR(30), <br />
&nbsp; descriptionAbonnemement VARCHAR(255) <br />
) <br />
&nbsp;<br />
CREATE TABLE TbAbonnementClient <br />
( <br />
&nbsp; IDAbonnementClient INT IDENTITY, <br />
&nbsp; IDClient INT, <br />
&nbsp; IDAbonnement INT, <br />
&nbsp; dateAbonnementClient DATETIME <br />
)</div></td></tr></tbody></table></div>
<p>Manifestement il manque toutes les contraintes  :</p>
<p>&#8211; de valuation obligatoire (NOT NULL),<br />
&#8211; de clé primaire,<br />
&#8211; de clé étrangère,<br />
&#8211; d&rsquo;unicité,<br />
&#8211; de valeur par défaut<br />
&#8211; de domaine (CHECK)</p>
<p><strong>Le squelette d&rsquo;ajout de contraintes est le suivant :</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
---------------------------------</div></td></tr></tbody></table></div>
<p>=> contraintes de valuation obligatoire</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER TABLE maTable <br />
ALTER COLUMN maColonne memeType NOT NULL</div></td></tr></tbody></table></div>
<p>=> contraintes de clé primaire</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER TABLE maTable <br />
ADD CONSTRAINT PK_maTable <br />
&nbsp; PRIMARY KEY (colonnesConstituantLaCléPrimaire)</div></td></tr></tbody></table></div>
<p>=> contraintes de clé étrangère</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER TABLE maTable <br />
ADD CONSTRAINT FK_maTable_colonneDeCleEtrangere <br />
&nbsp; FOREIGN KEY(colonneDeCleEtrangere) <br />
&nbsp; REFERENCES tableContenantLaClePrimaireAReferencer(colonneDeClePrimaire)</div></td></tr></tbody></table></div>
<p>=> contraintes d&rsquo;unicité</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER TABLE maTable <br />
ADD CONSTRAINT UQ_maTable_colonnesConstituantLeTupleQuiDoitEtreUnique <br />
&nbsp; UNIQUE (colonnesConstituantLeTupleQuiDoitEtreUnique)</div></td></tr></tbody></table></div>
<p>=> contraintes de valeur par défaut :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER TABLE maTable <br />
ADD CONSTRAINT DF_maTable_maColonne <br />
&nbsp; DEFAULT (uneValeur) FOR (maColonne)</div></td></tr></tbody></table></div>
<p>=> contraintes de domaine (CHECK)<br />
ALTER TABLE maTable<br />
ADD CONSTRAINT CHK_maTable_maColonne<br />
	CHECK(maColonne [formuleDeVerification]</p>
<p><strong>Définissons les dans cet ordre :</strong></p>
<p>=> <strong>Contraintes de valuation obligatoire</strong> </p>
<p>Une clé primaire ne pouvant logiquement pas être NULL, nous devons définir toute les colonnes qui vont servir de clé primaire aux tables comme ne pouvant pas être NULL.<br />
Nous devons également obliger la valuation des colonnes qui sont des clés naturelles, et celles qui seront clé étrangère :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
-- TbPays <br />
ALTER TABLE dbo.TbPays <br />
ALTER COLUMN IDPays INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbPays <br />
ALTER COLUMN nomPays VARCHAR(30) NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbPays <br />
ALTER COLUMN prefixeTelephonique VARCHAR(4) NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbPays <br />
ALTER COLUMN longueurNumeroTelephone TINYINT NOT NULL <br />
&nbsp;<br />
-- TbClient <br />
ALTER TABLE dbo.TbClient <br />
ALTER COLUMN IDClient INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbClient <br />
ALTER COLUMN nomClient VARCHAR(20) NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbClient <br />
ALTER COLUMN IDPays INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbClient <br />
ALTER COLUMN numeroTelephoneClient VARCHAR(36) NOT NULL <br />
&nbsp;<br />
-- TbAbonnement <br />
ALTER TABLE dbo.TbAbonnement <br />
ALTER COLUMN IDAbonnement INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbAbonnement <br />
ALTER COLUMN referenceAbonnement NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbAbonnement <br />
ALTER COLUMN nomAbonnement VARCHAR(30) NOT NULL <br />
&nbsp;<br />
-- TbAbonnementClient <br />
ALTER TABLE dbo.TbAbonnementClient <br />
ALTER COLUMN IDAbonnementClient INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbAbonnementClient <br />
ALTER COLUMN IDClient INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbAbonnementClient <br />
ALTER COLUMN IDAbonnement INT NOT NULL <br />
&nbsp;<br />
ALTER TABLE dbo.TbAbonnementClient <br />
ALTER COLUMN dateAbonnementClient DATETIME NOT NULL</div></td></tr></tbody></table></div>
<p>=> <strong>Contraintes de clé primaire</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
-- TbPays <br />
ALTER TABLE dbo.TbPays <br />
ADD CONSTRAINT PK_TbPays_IDPays PRIMARY KEY (IDPays) <br />
&nbsp;<br />
-- TbClient <br />
ALTER TABLE dbo.TbClient <br />
ADD CONSTRAINT PK_TbClient_IDClient PRIMARY KEY(IDClient) <br />
&nbsp;<br />
-- TbAbonnement <br />
ALTER TABLE dbo.TbAbonnement <br />
ADD CONSTRAINT PK_TbAbonnement_IDAbonnement PRIMARY KEY (IDAbonnement) <br />
&nbsp;<br />
-- TbAbonnementClient <br />
ALTER TABLE dbo.TbAbonnementClient <br />
ADD CONSTRAINT PK_TbAbonnementClient_IDAbonnementClient PRIMARY KEY (IDAbonnementClient)</div></td></tr></tbody></table></div>
<p>=> <strong>Contraintes de clé étrangère</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
-- TbClient <br />
ALTER TABLE dbo.TbClient <br />
ADD CONSTRAINT FK_TbClient_IDPays <br />
&nbsp; FOREIGN KEY (IDPays) REFERENCES dbo.TbPays(IDPays) <br />
&nbsp;<br />
-- TbAbonnementClient <br />
ALTER TABLE dbo.TbAbonnementClient <br />
ADD CONSTRAINT FK_TbAbonnementClient_IDClient <br />
&nbsp; FOREIGN KEY (IDClient) REFERENCES dbo.TbClient(IDClient), <br />
&nbsp; ---- <br />
&nbsp; CONSTRAINT FK_TbAbonnementClient_IDAbonnement <br />
&nbsp; FOREIGN KEY (IDAbonnement) REFERENCES dbo.TbAbonnement(IDAbonnement)</div></td></tr></tbody></table></div>
<p>=> <strong>Contraintes d&rsquo;unicité</strong></p>
<p>Elles permettent de s&rsquo;assurer qu&rsquo;aucune valeur ne sera pas insérée en double dans des colonnes qui ne constituent pas la clé primaire.<br />
Bien qu&rsquo;une clé primaire permette également d&rsquo;assurer l&rsquo;unicité, on ne peut bien sûr en définir qu&rsquo;une seule par table, pour qu&rsquo;il soit possible de la référencer par des clés étrangères dans d&rsquo;autres tables.<br />
Au contraire, on peut définir plusieurs contraintes d&rsquo;unicité par table.</p>
<p>Similairement, des indexes sont créés implicitement lors de la création d&rsquo;une clé primaire ou d&rsquo;une contrainte d&rsquo;unicité.<br />
Mais seul l&rsquo;index de clé primaire est toujours cluster : l&rsquo;index sous-jacent à une contrainte d&rsquo;unicité est cluster si la table n&rsquo;a pas de clé primaire définie, et non-cluster à l&rsquo;inverse.<br />
Comme pour une clé primaire, il est nécessaire de mettre la colonne qui a la sélectivité la plus élevée en premier dans la définition de la contrainte d&rsquo;unicité, car cet ordre sert dans la définition de l&rsquo;index.<br />
Comme les recherches à travers les indexes se font suivant la valeur de la première clé, l&rsquo;index sera d&rsquo;autant plus efficace que la valeur de sa première clé sera sélective.</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
-- TbClient <br />
ALTER TABLE dbo.TbClient <br />
ADD CONSTRAINT UQ_TbClient_nomClient UNIQUE (nomClient), <br />
&nbsp; CONSTRAINT UQ_TbClient_numeroTelephoneClient UNIQUE (numeroTelephoneClient) <br />
&nbsp;<br />
-- TbAbonnement <br />
ALTER TABLE dbo.TbAbonnement <br />
ADD CONSTRAINT UQ_TbAbonnement_nomAbonnement UNIQUE (nomAbonnement) <br />
&nbsp;<br />
ALTER TABLE dbo.TbAbonnement <br />
ADD CONSTRAINT UQ_TbAbonnement_referenceAbonnement UNIQUE (referenceAbonnement) <br />
&nbsp;<br />
-- TbAbonnementClient <br />
ALTER TABLE dbo.TbAbonnementClient <br />
ADD CONSTRAINT UQ_TbAbonnementClient_IDClient_IDAbonnement UNIQUE(IDClient, IDAbonnement)</div></td></tr></tbody></table></div>
<p>=> <strong>Contraintes de valeur par défaut :</strong></p>
<p>Il peut être intéressant de définir une valeur par défaut pour l&rsquo;insertion (mais pas à l&rsquo;UPDATE) d&rsquo;une nouvelle ligne à une table si la colonne est omise dans la spécification de l&rsquo;instruction INSERT :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
ALTER TABLE dbo.TbAbonnementClient <br />
ADD CONSTRAINT DF_TbAbonnementClient_dateAbonnementClient <br />
&nbsp; DEFAULT (GETDATE()) FOR dateAbonnementClient</div></td></tr></tbody></table></div>
<p>Ainsi si nous écrivons :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
INSERT INTO dbo.TbAbonnementClient <br />
( <br />
&nbsp; IDClient, <br />
&nbsp; IDAbonnement <br />
) <br />
VALUES <br />
( <br />
&nbsp; @IDClient, <br />
&nbsp; @IDAbonnement <br />
)</div></td></tr></tbody></table></div>
<p>la colonne <em>dateAbonnementClient</em> sera valuée à la date actuelle du système.</p>
<p>=> <strong>Contraintes de domaine</strong></p>
<p>Elles permettent de limiter ou de vérifier les valeurs que peuvent contenir une colonne.<br />
Elles nécessitent une formule de vérification, qui peut être spécifiée directement lors de la définition de la contrainte, ou bien à travers une fonction définie par l&rsquo;utilisateur.<br />
L&rsquo;utilisation d&rsquo;une fonction pour la définition d&rsquo;une contrainte de domaine permet bien souvent de ne pas avoir recours à un déclencheur pour vérifier la validité des données.</p>
<p>Ici, nous souhaitons vérifier que les numéros de téléphone que nous stockons dans la base de données contiennent le préfixe du pays du client, et que la longueur des numéros de téléphone est correcte.<br />
Pour cela nous créons la fonction suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
CREATE FUNCTION Fn_IsNumTelClient_Correct <br />
&nbsp; ( <br />
&nbsp; &nbsp; @IDPays INT, <br />
&nbsp; &nbsp; @numeroTelephoneClient VARCHAR(36) <br />
&nbsp; ) <br />
RETURNS BIT <br />
WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; RETURN <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN @numeroTelephoneClient LIKE prefixeTelephonique + '%' <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AND LEN(@numeroTelephoneClient) = longueurNumeroTelephone <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;THEN CAST(1 AS BIT) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE CAST(0 AS BIT) <br />
&nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; FROM dbo.TbPays <br />
&nbsp; &nbsp; WHERE IDPays = @IDPays <br />
&nbsp; ) <br />
END</div></td></tr></tbody></table></div>
<p>La contrainte de domaine sera alors définie comme suit :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
ALTER TABLE dbo.TbAbonnementClient <br />
ADD CONSTRAINT CHK_TbAbonnementClient_numeroTelephoneClient <br />
&nbsp; CHECK(dbo.Fn_IsNumTelClient_Correct(IDPays, numeroTelephoneClient) = 1)</div></td></tr></tbody></table></div>
<p>Nous souhaitons également vérifier que les valeurs de la colonne <em>referenceAbonnement</em> de la table <em>TbAbonnement</em> aient le format XXX-nnn-nn.<br />
Là nous pouvons définir celui-ci directement  dans la spécification de la contrainte :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 25/07/2009 - <br />
--------------------------------- <br />
ALTER TABLE dbo.TbAbonnement <br />
ADD CONSTRAINT CHK_TbAbonnement_referenceAbonnement <br />
&nbsp; CHECK(referenceAbonnement LIKE '[A-Z][A-Z][A-Z]-[0-9][0-9][0-9]-[0-9][0-9]')</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Une fonction d&#8217;extraction des nombres contenus dans une chaîne de caractères : les fonctions ISNUMERIC() et ASCII()</title>
		<link>https://blog.developpez.com/elsuket/p7726/snippets/une_fonction_d_extraction_des_nombres_co</link>
		<comments>https://blog.developpez.com/elsuket/p7726/snippets/une_fonction_d_extraction_des_nombres_co#comments</comments>
		<pubDate>Tue, 09 Jun 2009 22:16:05 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une petite fonction qui vous permettra d&#8217;extraire les nombres contenus dans une chaîne de caractères, et de les retourner comme un entier&#8230; 1234567891011121314151617181920212223242526272829303132333435363738--------------------------------- -- Nicolas SOUQUET - 09/06/2009 - --------------------------------- CREATE FUNCTION dbo.FnTrouveChiffres(@string VARCHAR(1024)) &#160; RETURNS INT &#160; WITH &#8230; <a href="https://blog.developpez.com/elsuket/p7726/snippets/une_fonction_d_extraction_des_nombres_co">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une petite fonction qui vous permettra d&rsquo;extraire les nombres contenus dans une chaîne de caractères, et de les retourner comme un entier&#8230;</p>
<p><span id="more-45"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 09/06/2009 - <br />
--------------------------------- <br />
CREATE FUNCTION dbo.FnTrouveChiffres(@string VARCHAR(1024)) <br />
&nbsp; RETURNS INT <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; DECLARE @result VARCHAR(1024) <br />
&nbsp;<br />
&nbsp; IF ISNUMERIC(@string) = 1 <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; SET @result = @string <br />
&nbsp; END <br />
&nbsp; ELSE <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; DECLARE @i INT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @Lgr INT, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @char CHAR(1) <br />
&nbsp;<br />
&nbsp; &nbsp; SELECT @i = 1, <br />
&nbsp; &nbsp; &nbsp; &nbsp; @Lgr = LEN(@string), <br />
&nbsp; &nbsp; &nbsp; &nbsp; @result = '' <br />
&nbsp;<br />
&nbsp; &nbsp; WHILE @i &lt;= @Lgr <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SELECT @char = SUBSTRING(@string, @i, 1) <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; IF ISNUMERIC(@char) = 1 <br />
&nbsp; &nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; &nbsp; SET @result = @result + @char <br />
&nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; SET @i = @i + 1 <br />
&nbsp; &nbsp; END <br />
&nbsp; END <br />
&nbsp; RETURN CAST(@result AS INT) <br />
END</div></td></tr></tbody></table></div>
<p>Vous pouvez utiliser cette fonction si vous êtes certain que votre chaîne ne contiendra jamais les symboles arithmétiques &laquo;&nbsp;+&nbsp;&raquo; et &laquo;&nbsp;-&laquo;&nbsp;.<br />
En effet, la fonction ISNUMERIC() retourne 1 (vrai) pour ces deux symboles.</p>
<p>Il existe une autre solution avec la fonction ASCII() :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 09/06/2009 - <br />
--------------------------------- <br />
ALTER FUNCTION [dbo].[FnTrouveChiffres](@string VARCHAR(1024)) <br />
&nbsp; RETURNS INT <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; DECLARE @result VARCHAR(1024) <br />
&nbsp;<br />
&nbsp; DECLARE @i INT, <br />
&nbsp; &nbsp; &nbsp; @Lgr INT, <br />
&nbsp; &nbsp; &nbsp; @char CHAR(1) <br />
&nbsp;<br />
&nbsp; SELECT @i = 1, <br />
&nbsp; &nbsp; &nbsp; @Lgr = LEN(@string), <br />
&nbsp; &nbsp; &nbsp; @result = '' <br />
&nbsp;<br />
&nbsp; WHILE @i &lt;= @Lgr <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; SELECT @char = SUBSTRING(@string, @i, 1) <br />
&nbsp;<br />
&nbsp; &nbsp; IF ASCII(@char) BETWEEN 48 AND 57 <br />
&nbsp; &nbsp; BEGIN <br />
&nbsp; &nbsp; &nbsp; SET @result = @result + @char <br />
&nbsp; &nbsp; END <br />
&nbsp; <br />
&nbsp; &nbsp; SET @i = @i + 1 <br />
&nbsp; END <br />
&nbsp;<br />
&nbsp; RETURN CAST(@result AS INT) <br />
END</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trouver la version, le service pack et l&#8217;édition d&#8217;une instance SQL Server</title>
		<link>https://blog.developpez.com/elsuket/p7749/snippets/trouver_la_version_le_service_pack_et_l</link>
		<comments>https://blog.developpez.com/elsuket/p7749/snippets/trouver_la_version_le_service_pack_et_l#comments</comments>
		<pubDate>Mon, 15 Jun 2009 06:18:57 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une requête simple pour trouver la version, le service pack et l&#8217;édition d&#8217;une instance SQL Server, valable au moins sur les version 2000 et ultérieures &#8230; 123456--------------------------------- -- Nicolas SOUQUET - 15/06/2009 - --------------------------------- SELECT SERVERPROPERTY('productversion') AS ProductVersion, &#160; &#8230; <a href="https://blog.developpez.com/elsuket/p7749/snippets/trouver_la_version_le_service_pack_et_l">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une requête simple pour trouver la version, le service pack et l&rsquo;édition d&rsquo;une instance SQL Server, valable au moins sur les version 2000 et ultérieures &#8230;</p>
<p><span id="more-81"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 15/06/2009 - <br />
--------------------------------- <br />
SELECT SERVERPROPERTY('productversion') AS ProductVersion, <br />
&nbsp; &nbsp; SERVERPROPERTY ('productlevel') AS ProductLevel, <br />
&nbsp; &nbsp; SERVERPROPERTY ('edition') AS Edition</div></td></tr></tbody></table></div>
<p>Ou si vous préférez :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 15/06/2009 - <br />
--------------------------------- <br />
SELECT 'ProductVersion' AS Propriete, SERVERPROPERTY('ProductVersion') AS Valeur <br />
UNION SELECT 'ProductLevel', SERVERPROPERTY ('ProductLevel') <br />
UNION SELECT 'Edition', SERVERPROPERTY ('Edition')</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Changer le mot de passe de la connexion sa sous SQL Server 2000</title>
		<link>https://blog.developpez.com/elsuket/p7760/snippets/changer_le_mot_de_passe_de_la_connexion_2000</link>
		<comments>https://blog.developpez.com/elsuket/p7760/snippets/changer_le_mot_de_passe_de_la_connexion_2000#comments</comments>
		<pubDate>Wed, 17 Jun 2009 17:38:45 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Chassez le naturel, il revient au galop &#8230; La commande ALTER LOGIN permet de modifier le mot de passe suprême, mais fonctionne seulement dès SQL Server 2005. Comment faire sous SQL Server 2000? C&#8217;est un temps que les moins de &#8230; <a href="https://blog.developpez.com/elsuket/p7760/snippets/changer_le_mot_de_passe_de_la_connexion_2000">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Chassez le naturel, il revient au galop &#8230;<br />
La commande ALTER LOGIN permet de modifier le mot de passe suprême, mais fonctionne seulement dès SQL Server 2005. Comment faire sous SQL Server 2000?</p>
<p><span id="more-82"></span></p>
<p>C&rsquo;est un temps que les moins de 20 ans ne peuvent pas connaître, mais sous SQL Server 2000, l&rsquo;absence de la commande ALTER LOGIN pour changer le mot de passe sa n&rsquo;existait pas.<br />
On s&rsquo;habitue très vite à cette commande qui paraît naturelle dès SQL Server 2005, et les installations allant bon train, on en oublie l&rsquo;ancienne méthode !</p>
<p>On le modifie donc avec la procédure stockée <em>sp_password</em>, dont le prototype est le suivant :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">EXEC sp_password <br />
&nbsp; @old = 'myOldPassword', <br />
&nbsp; @new = 'myNewPassword', <br />
&nbsp; @loginame = 'myLogin'</div></td></tr></tbody></table></div>
<p><strong>Pièges :</strong></p>
<p>=> ne mettez qu&rsquo;un seul &lsquo;n&rsquo; au paramètre @loginame<br />
=> si l&rsquo;ancien mot de passe n&rsquo;était pas valué (à ne pas confondre avec chaîne vide), vous devez écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 17/06/2009 - <br />
--------------------------------- <br />
EXEC sp_password <br />
&nbsp; @old = null, <br />
&nbsp; @new = 'myNewPassword', <br />
&nbsp; @loginame = 'myLogin'</div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stocker simplement tout types de fichiers dans une table en utilisant le type de données VARBINARY et les BLOBs</title>
		<link>https://blog.developpez.com/elsuket/p7799/snippets/stocker_simplement_tout_types_de_fichier</link>
		<comments>https://blog.developpez.com/elsuket/p7799/snippets/stocker_simplement_tout_types_de_fichier#comments</comments>
		<pubDate>Thu, 25 Jun 2009 23:26:28 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici comment copier le contenu d&#8217;un fichier contenu sur un disque dur pour le stocker dans une table, à l&#8217;aide de la commande OPENROWSET et de son option BULK &#8230; Supposons que nous avons la table suivante, dans laquelle nous &#8230; <a href="https://blog.developpez.com/elsuket/p7799/snippets/stocker_simplement_tout_types_de_fichier">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici comment copier le contenu d&rsquo;un fichier contenu sur un disque dur pour le stocker dans une table, à l&rsquo;aide de la commande OPENROWSET et de son option BULK &#8230;</p>
<p><span id="more-47"></span></p>
<p>Supposons que nous avons la table suivante, dans laquelle nous stockons des icônes :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 26/06/2009 - <br />
--------------------------------- <br />
CREATE TABLE dbo.TbIcone <br />
( <br />
&nbsp; IDIcone INT IDENTITY CONSTRAINT PK_TbIcone PRIMARY KEY, <br />
&nbsp; nomIcone VARCHAR(255) NOT NULL, <br />
&nbsp; icone VARBINARY(MAX) <br />
)</div></td></tr></tbody></table></div>
<p>Et voici la procédure stockée qui va permettre de stocker des icônes stockées sur un des disques dur, simplement en passant son UNC en paramètre :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 26/06/2009 - <br />
--------------------------------- <br />
CREATE PROCEDURE PsStockeIcone <br />
&nbsp; @cheminDuFichier VARCHAR(255) <br />
AS <br />
BEGIN <br />
&nbsp; SET NOCOUNT ON <br />
&nbsp;<br />
&nbsp; DECLARE @SQL NVARCHAR(256), <br />
&nbsp; &nbsp; &nbsp; @ParamDefinition NVARCHAR(64), <br />
&nbsp; &nbsp; &nbsp; @nomDeFichier VARCHAR(64) <br />
&nbsp;<br />
&nbsp; SELECT @SQL = N'SELECT @fluxOUT = BulkColumn FROM OPENROWSET(BULK N''' + @cheminDuFichier + ''', SINGLE_BLOB) AS TMP', <br />
&nbsp; &nbsp; &nbsp; @ParamDefinition = N'@fluxOUT VARBINARY(MAX) OUTPUT', <br />
&nbsp; &nbsp; &nbsp; @nomDeFichier = RIGHT(@cheminDuFichier, CHARINDEX('\', REVERSE(@cheminDuFichier)) - 1) <br />
&nbsp;<br />
&nbsp; -- Récupère le fichier sous la forme d'une valeur binaire <br />
&nbsp; DECLARE @fluxFichier VARBINARY(MAX) <br />
&nbsp;<br />
&nbsp; EXEC sp_executesql <br />
&nbsp; &nbsp; &nbsp; @SQL, <br />
&nbsp; &nbsp; &nbsp; @ParamDefinition, <br />
&nbsp; &nbsp; &nbsp; @fluxFichier OUTPUT <br />
&nbsp;<br />
&nbsp; -- Stocke le flux dans la table <br />
&nbsp; INSERT INTO dbo.TbIcone <br />
&nbsp; ( <br />
&nbsp; &nbsp; nomIcone, <br />
&nbsp; &nbsp; icone <br />
&nbsp; ) <br />
&nbsp; VALUES <br />
&nbsp; ( <br />
&nbsp; &nbsp; @nomDeFichier, <br />
&nbsp; &nbsp; @fluxFichier <br />
&nbsp; ) <br />
END</div></td></tr></tbody></table></div>
<p>Je souhaite stocker l&rsquo;image suivante (C:\SQLServer2008Dark.jpg) :</p>
<p><img src="http://blog.developpez.com/media/SQLServer2008Dark_01.jpg" width="185" height="48" alt="" /></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 26/06/2009 - <br />
--------------------------------- <br />
EXEC dbo.PsStockeIcone 'C:\SQLServer2008Dark.jpg' <br />
GO <br />
&nbsp;<br />
SELECT IDIcone, nomIcone, icone <br />
FROM dbo.TbIcone</div></td></tr></tbody></table></div>
<p><img src="http://blog.developpez.com/media/icone_01.PNG" width="536" height="204" alt="" /></p>
<p>Notons que cette procédure fonctionne dès SQL Server 2005.</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exporter le code de vues, procédures stockées, triggers, fonctions SQL vers un fichier</title>
		<link>https://blog.developpez.com/elsuket/p7798/snippets/exporter_le_code_de_vues_procedures_stoc</link>
		<comments>https://blog.developpez.com/elsuket/p7798/snippets/exporter_le_code_de_vues_procedures_stoc#comments</comments>
		<pubDate>Thu, 25 Jun 2009 21:59:43 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[Utilitaires]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour effectuer une revue de code ou pour gérer des versions de code en phase de développement, il peut être intéressant d&#8217;exporter les codes des modules SQL vers un fichier. Voyons comment réaliser cela, à l&#8217;aide de l&#8217;utilitaire en ligne &#8230; <a href="https://blog.developpez.com/elsuket/p7798/snippets/exporter_le_code_de_vues_procedures_stoc">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Pour effectuer une revue de code ou pour gérer des versions de code en phase de développement, il peut être intéressant d&rsquo;exporter les codes des modules SQL vers un fichier.<br />
Voyons comment réaliser cela, à l&rsquo;aide de l&rsquo;utilitaire en ligne de commande BCP &#8230;</p>
<p><span id="more-46"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 25/06/2009 - Exporter le code de modules dans un fichier unique - <br />
-------------------------------------------------------------------------------------- <br />
SELECT SQL.definition + CHAR(10) + CHAR(13) + 'GO' AS CodeModule <br />
INTO ##MODULES <br />
FROM sys.objects AS OBJETS <br />
JOIN sys.sql_modules AS SQL ON SQL.object_id = OBJETS.object_id <br />
WHERE OBJETS.type IN ('P', 'V', 'TR', 'FN', 'IF', 'TF') <br />
AND OBJETS.name NOT LIKE 'dt%' AND OBJETS.name NOT LIKE 'sp%' <br />
ORDER BY OBJETS.object_id <br />
&nbsp;<br />
DECLARE @szBCP VARCHAR(256); <br />
SET @szBCP = 'bcp &quot;SELECT CodeModule FROM ##MODULES&quot; queryout C:\ModulesSQL.sql -T -c'; <br />
EXEC master.dbo.xp_cmdshell @szBCP; <br />
&nbsp;<br />
DROP TABLE ##MODULES; <br />
&nbsp;<br />
---------------------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 25/06/2009 - Exporter le code de plusieurs modules avec un fichier par module - <br />
---------------------------------------------------------------------------------------------------- <br />
--&gt;&gt;&gt;&gt; A EXECUTER DANS LE CONTEXTE DE LA BD DEPUIS LAQUELLE ON SOUHAITE RÉALISER L'EXPORT <br />
SET NOCOUNT ON <br />
&nbsp;<br />
DECLARE CUR_MODULES CURSOR FOR <br />
&nbsp; SELECT name <br />
&nbsp; FROM sys.objects <br />
&nbsp; WHERE type IN ('P', 'V', 'TR', 'FN', 'IF', 'TF') <br />
&nbsp; -- AND name LIKE '%blablabla%' <br />
FOR READ ONLY <br />
&nbsp;<br />
DECLARE @szNomModule SYSNAME <br />
OPEN CUR_MODULES <br />
FETCH NEXT FROM CUR_MODULES INTO @szNomModule <br />
WHILE @@FETCH_STATUS = 0 <br />
BEGIN <br />
&nbsp; SELECT definition <br />
&nbsp; INTO ##MODULE_TEXT <br />
&nbsp; FROM sys.sql_modules <br />
&nbsp; WHERE OBJECT_NAME(object_id) = @szNomModule <br />
&nbsp;<br />
&nbsp; DECLARE @szBCP VARCHAR(512); <br />
&nbsp; SET @szBCP = 'bcp &quot;SELECT definition FROM ##PROC_TEXT&quot; queryout C:\' + @szNomModule + '.sql -T -c'; <br />
&nbsp; EXEC master.dbo.xp_cmdshell @szBCP, NO_OUTPUT <br />
&nbsp;<br />
&nbsp; DROP TABLE ##MODULE_TEXT; <br />
&nbsp; FETCH NEXT FROM CUR_MODULES INTO @szNomModule <br />
END <br />
DEALLOCATE CUR_MODULES</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calculer le Buffer Cache Hit Ratio</title>
		<link>https://blog.developpez.com/elsuket/p7827/snippets/calculer_le_buffer_cache_hit_ratio</link>
		<comments>https://blog.developpez.com/elsuket/p7827/snippets/calculer_le_buffer_cache_hit_ratio#comments</comments>
		<pubDate>Thu, 02 Jul 2009 17:40:12 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[S&#8217;il est une valeur intéressante à suivre pour le performances d&#8217;un serveur, c&#8217;est bien le Buffer Cache Hit Ratio, ou Taux d&#8217;accès au cache des tampons, car celui-ci est un rapport du nombre de pages lues en RAM par rapport &#8230; <a href="https://blog.developpez.com/elsuket/p7827/snippets/calculer_le_buffer_cache_hit_ratio">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>S&rsquo;il est une valeur intéressante à suivre pour le performances d&rsquo;un serveur, c&rsquo;est bien le Buffer Cache Hit Ratio, ou Taux d&rsquo;accès au cache des tampons, car celui-ci est un rapport du nombre de pages lues en RAM par rapport au nombre de pages lues à partir des disques.</p>
<p>Voici une petite requête pour trouver sa valeur :</p>
<p><span id="more-50"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 02/07/2009 - <br />
--------------------------------- <br />
SELECT CAST( <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT CAST (cntr_value AS BIGINT) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM sys.dm_os_performance_counters &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE counter_name = 'Buffer cache hit ratio' <br />
&nbsp; &nbsp; &nbsp; &nbsp; )* 100.00 <br />
&nbsp; &nbsp; &nbsp; &nbsp; / <br />
&nbsp; &nbsp; &nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT CAST (cntr_value AS BIGINT) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM sys.dm_os_performance_counters &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE counter_name = 'Buffer cache hit ratio base' <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) AS NUMERIC(6,3) <br />
&nbsp; &nbsp; &nbsp; )</div></td></tr></tbody></table></div>
<p>Évidemment plus la valeur de ce pourcentage est élevée, meilleures sont les performances :</p>
<p>&#8211; en dessous de 90%, les performances sont médiocres<br />
&#8211; entre 90 et 95%, c&rsquo;est acceptable<br />
&#8211; au-delà de 95% c&rsquo;est correct.</p>
<p>On peut aussi suivre sa valeur avec le moniteur de performances &#8230;</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Une procédure pour connaître l&#8217;état d&#8217;un job</title>
		<link>https://blog.developpez.com/elsuket/p7611/snippets/une_procedure_pour_connaitre_l_etat_d_un</link>
		<comments>https://blog.developpez.com/elsuket/p7611/snippets/une_procedure_pour_connaitre_l_etat_d_un#comments</comments>
		<pubDate>Sun, 17 May 2009 23:09:10 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici une petite procédure stockée utilitaire qui retourne 1 si le job est en cours d&#8217;exécution, et 0 à l&#8217;inverse &#8230; 12345678910111213141516171819202122232425262728293031323334353637383940--------------------------------- -- Nicolas SOUQUET - 18/05/2009 - --------------------------------- CREATE PROCEDURE [dbo].[PsIsJobRunning] &#160; @nomJob SYSNAME AS BEGIN &#160; -- Récupère &#8230; <a href="https://blog.developpez.com/elsuket/p7611/snippets/une_procedure_pour_connaitre_l_etat_d_un">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici une petite procédure stockée utilitaire qui retourne 1 si le job est en cours d&rsquo;exécution, et 0 à l&rsquo;inverse &#8230;</p>
<p><span id="more-42"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 18/05/2009 - <br />
--------------------------------- <br />
CREATE PROCEDURE [dbo].[PsIsJobRunning] <br />
&nbsp; @nomJob SYSNAME <br />
AS <br />
BEGIN <br />
&nbsp; -- Récupère l'identifiant du job <br />
&nbsp; DECLARE @job_id UNIQUEIDENTIFIER, <br />
&nbsp; &nbsp; &nbsp; @isRunning BIT = 0 <br />
&nbsp;<br />
&nbsp; SELECT @job_id = job_id <br />
&nbsp; FROM msdb.dbo.sysjobs <br />
&nbsp; WHERE name = @_szNomJob <br />
&nbsp;<br />
&nbsp; DECLARE @Enum_Jobs TABLE <br />
&nbsp; ( <br />
&nbsp; &nbsp; JobID UNIQUEIDENTIFIER, <br />
&nbsp; &nbsp; LastRunDate INT, <br />
&nbsp; &nbsp; LatRunTime INT, <br />
&nbsp; &nbsp; NextRunDate INT, <br />
&nbsp; &nbsp; NextRunTime INT, <br />
&nbsp; &nbsp; NextRunScheduleID INT, <br />
&nbsp; &nbsp; RequestedToRun INT, <br />
&nbsp; &nbsp; RequesteSource INT, <br />
&nbsp; &nbsp; RequesteSourceID NVARCHAR(100), <br />
&nbsp; &nbsp; Running INT, <br />
&nbsp; &nbsp; CurrentStep INT, <br />
&nbsp; &nbsp; CurrentRetryAttempt INT, <br />
&nbsp; &nbsp; State INT <br />
&nbsp; ) <br />
&nbsp;<br />
&nbsp; INSERT INTO @Enum_Jobs <br />
&nbsp; EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, 'sa', @job_id <br />
&nbsp;<br />
&nbsp; SELECT @isRunning = ISNULL(CAST(Running AS BIT), 0) <br />
&nbsp; FROM @Enum_Jobs <br />
&nbsp;<br />
&nbsp; RETURN @isRunning <br />
END</div></td></tr></tbody></table></div>
<p>Notons que la colonne &laquo;&nbsp;Running&nbsp;&raquo; retournée par la procédure stockée étendue (et <strong>non-documentée</strong>) xp_sqlagent_enum_job peut prendre les valeurs suivantes :</p>
<p>0 = arrêté ou suspendu,<br />
1 = en cours d&rsquo;exécution,<br />
2 = en attente d&rsquo;un thread,<br />
3 = réessai,<br />
4 = arrêté,<br />
5 = suspendu,<br />
6 = en attente de terminaison d&rsquo;étape,<br />
7 = exécutions des actions d&rsquo;achèvement</p>
<p>Vous remarquerez que j&rsquo;aurai du vous proposer un code prenant en compte le statut d&rsquo;identifiant 4, mais lorsqu&rsquo;on requête pour un job arrêté, c&rsquo;est bien le statut d&rsquo;identiant 1 qui est retourné &#8230;</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rechercher une chaîne de caractère dans le code des modules SQL sous SQL Server 2005 et 2008</title>
		<link>https://blog.developpez.com/elsuket/p7612/snippets/rechercher_une_chaine_de_caractere_dans_2005</link>
		<comments>https://blog.developpez.com/elsuket/p7612/snippets/rechercher_une_chaine_de_caractere_dans_2005#comments</comments>
		<pubDate>Mon, 18 May 2009 17:11:35 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il arrive parfois de vouloir chercher un bout de code dans toutes les procédures stockées d&#8217;une base de données, comme par exemple le nom d&#8217;une colonne. Voyons comment réaliser cela avec une simple requête &#8230; 1234567891011121314151617181920212223242526--------------------------------- -- Nicolas SOUQUET - &#8230; <a href="https://blog.developpez.com/elsuket/p7612/snippets/rechercher_une_chaine_de_caractere_dans_2005">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il arrive parfois de vouloir chercher un bout de code dans toutes les procédures stockées d&rsquo;une base de données, comme par exemple le nom d&rsquo;une colonne.</p>
<p>Voyons comment réaliser cela avec une simple requête &#8230;</p>
<p><span id="more-43"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 18/05/2009 - <br />
--------------------------------- <br />
/* <br />
Valable pour les objets dont le type est : <br />
- Procédure stockée SQL (P) <br />
- Procédure de filtre de réplication (RF) <br />
- Vues (V) <br />
- Déclencheur DML SQL (TR) <br />
- Fonction scalaire (FN) <br />
- Fonction table incluse SQL (IF) <br />
- Fonction table SQL (TF) <br />
- Règle (R) <br />
*/ <br />
SELECT O.type_desc, <br />
&nbsp; &nbsp; O.name, <br />
&nbsp; &nbsp; O.create_date, <br />
&nbsp; &nbsp; O.modify_date, <br />
&nbsp; &nbsp; M.Definition <br />
FROM sys.objects O <br />
JOIN sys.sql_modules M ON M.object_id = O.object_id <br />
WHERE O.name NOT LIKE 'dt%' <br />
AND O.name NOT LIKE 'sys%' <br />
--AND O.type = 'P' -- Filtre sur le type d'objet <br />
AND M.Definition LIKE '%codeARechercher%' <br />
ORDER BY O.Name</div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exemples d&#8217;affectations de variables en ligne sous SQL Server 2008</title>
		<link>https://blog.developpez.com/elsuket/p7714/snippets/exemples_d_affectations_de_variables_en_2008</link>
		<comments>https://blog.developpez.com/elsuket/p7714/snippets/exemples_d_affectations_de_variables_en_2008#comments</comments>
		<pubDate>Sat, 06 Jun 2009 23:15:28 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici quelques exemples simples de code qui montrent que sous SQL Server 2008, on peut non seulement se passer des sempiternelles deux lignes de code nécessaires jusqu&#8217;en version 2005 pour déclarer et affecter d&#8217;un valeur une variable, mais on peut &#8230; <a href="https://blog.developpez.com/elsuket/p7714/snippets/exemples_d_affectations_de_variables_en_2008">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici quelques exemples simples de code qui montrent que sous SQL Server 2008, on peut non seulement se passer des sempiternelles deux lignes de code nécessaires jusqu&rsquo;en version 2005 pour déclarer et affecter d&rsquo;un valeur une variable, mais on peut aller encore plus loin &#8230;</p>
<p><span id="more-41"></span></p>
<p><strong>Voici un exemple de déclaration et d&rsquo;affection en ligne :</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 07/06/2009 - <br />
----------------------------------- <br />
Déclaration et affectation en ligne <br />
DECLARE @deux TINYINT = 2; <br />
-- Affichage <br />
SELECT @deux AS AffectationEnLigne</div></td></tr></tbody></table></div>
<p>Alors que jusque sous SQL Server 2005, nous devons écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 07/06/2009 - <br />
--------------------------------- <br />
-- Déclaration <br />
DECLARE @deux TINYINT; <br />
&nbsp;<br />
-- Affectation <br />
SET @deux = 2; <br />
&nbsp;<br />
-- Affichage <br />
SELECT @deux AS AffectationEnLigne;</div></td></tr></tbody></table></div>
<p><strong>Mais on peut aller encore plus loin</strong> avec ce qui peut vous rappeler la surcharge d&rsquo;opérateurs dans la programmation par objets, ou certains langages de programmation modernes :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 07/06/2009 - <br />
--------------------------------- <br />
-- Déclaration et affectation en ligne <br />
DECLARE @deux TINYINT = 2; SELECT @deux AS AffectationEnLigne <br />
&nbsp;<br />
-- Addition en ligne =&gt; 4 <br />
SELECT @deux += 2; SELECT @deux AS AdditionEnLigne <br />
&nbsp;<br />
-- Soustraction en ligne =&gt; 2 <br />
SELECT @deux -= 2; SELECT @deux AS SoustractionEnLigne <br />
&nbsp;<br />
-- Multiplication en ligne =&gt; 4 <br />
SELECT @deux *= 2; SELECT @deux AS MultiplicationEnLigne <br />
&nbsp;<br />
-- Division en ligne =&gt; 2 <br />
SELECT @deux /= 2 ; SELECT @deux AS DivisionEnLigne</div></td></tr></tbody></table></div>
<p>L&rsquo;exécution du code suivant affiche sous SQL Server Management Studio 2008:</p>
<p><img src="http://blog.developpez.com/media/affectationEnLigne.JPG" width="157" height="241" alt="" /></p>
<p><strong>Voyons maintenant la combinaison de déclarations avec des requêtes :</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 07/06/2009 - <br />
--------------------------------- <br />
-- Selection et affection en ligne <br />
CREATE TABLE TEST <br />
( <br />
&nbsp; Valeur TINYINT <br />
) <br />
GO <br />
&nbsp;<br />
SET NOCOUNT ON; <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.TEST (Valeur) VALUES (1); <br />
INSERT INTO dbo.TEST (Valeur) VALUES (2); <br />
INSERT INTO dbo.TEST (Valeur) VALUES (3); <br />
GO <br />
&nbsp;<br />
DECLARE @max TINYINT = (SELECT MAX(Valeur) FROM dbo.TEST), <br />
&nbsp; &nbsp; @min TINYINT = (SELECT MIN(Valeur) FROM dbo.TEST), <br />
&nbsp; &nbsp; @sum TINYINT = (SELECT SUM(Valeur) FROM dbo.TEST), <br />
&nbsp; &nbsp; @val TINYINT = (SELECT TOP 1 Valeur FROM dbo.TEST); <br />
&nbsp; &nbsp; <br />
SELECT @max AS MaxEnLigne, <br />
&nbsp; &nbsp; @min AS MinEnLigne, <br />
&nbsp; &nbsp; @sum AS SommeEnLigne, <br />
&nbsp; &nbsp; @val AS PremiereValeur <br />
GO</div></td></tr></tbody></table></div>
<p>L&rsquo;exécution du code suivant affiche sous SQL Server Management Studio 2008:</p>
<p><img src="http://blog.developpez.com/media/affectationEnLigne2.JPG" width="482" height="516" alt="" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Une seule instruction DROP pour supprimer plusieurs objets de base de données de même type</title>
		<link>https://blog.developpez.com/elsuket/p7721/snippets/une_seule_instruction_drop_pour_supprime</link>
		<comments>https://blog.developpez.com/elsuket/p7721/snippets/une_seule_instruction_drop_pour_supprime#comments</comments>
		<pubDate>Mon, 08 Jun 2009 22:05:00 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici comment, dans la même instruction, supprimer plusieurs procédures stockées ou tables &#8230; Supposons que nous voulons supprimer quatre tables dont les noms sont : &#8211; Client &#8211; Client_Commande &#8211; Client_Livraison &#8211; Livraison On peut écrire : 1234567891011--------------------------------- -- Nicolas &#8230; <a href="https://blog.developpez.com/elsuket/p7721/snippets/une_seule_instruction_drop_pour_supprime">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici comment, dans la même instruction, supprimer plusieurs procédures stockées ou tables &#8230;</p>
<p><span id="more-4"></span></p>
<p>Supposons que nous voulons supprimer quatre tables dont les noms sont :</p>
<p>&#8211; Client<br />
&#8211; Client_Commande<br />
&#8211; Client_Livraison<br />
&#8211; Livraison</p>
<p>On peut écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 08/06/2009 - <br />
--------------------------------- <br />
DROP TABLE dbo.Client <br />
GO <br />
DROP TABLE dbo.Client_Commande <br />
GO <br />
DROP TABLE dbo.Client_Livraison <br />
GO <br />
DROP TABLE dbo.Livraison <br />
GO</div></td></tr></tbody></table></div>
<p>Et dès lors si l&rsquo;on veut supprimer un jeu de procédures stockées correspondant à certains critères, on se voir obligé d&rsquo;écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 08/06/2009 - <br />
--------------------------------- <br />
DECLARE curProcedures CURSOR FOR <br />
&nbsp; SELECT name <br />
&nbsp; FROM sys.procedures <br />
&nbsp; WHERE name LIKE '%client%' <br />
&nbsp; OR name LIKE '%livraison%' <br />
FOR READ ONLY <br />
&nbsp;<br />
DECLARE @nomProc SYSNAME, <br />
&nbsp; &nbsp; @SQL VARCHAR(128) <br />
&nbsp;<br />
OPEN curProcedures <br />
FETCH NEXT FROM curProcedures INTO @nomProc <br />
WHILE @@FETCH_STATUS = 0 <br />
BEGIN <br />
&nbsp; SET @SQL = 'DROP PROCEDURE dbo.' + @nomProc <br />
&nbsp; <br />
&nbsp; PRINT @nomProc &nbsp;<br />
&nbsp; EXEC (@SQL) <br />
&nbsp;<br />
&nbsp; FETCH NEXT FROM curProcedures INTO @nomProc <br />
END <br />
&nbsp;<br />
DEALLOCATE curProcedures</div></td></tr></tbody></table></div>
<p>Mais la syntaxe suivante est aussi valable :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 08/06/2009 - <br />
--------------------------------- <br />
DROP TABLE dbo.Client, dbo.Client_Commande, dbo.Client_Livraison, dbo.Livraison</div></td></tr></tbody></table></div>
<p>Et on peut alors écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 08/06/2009 - <br />
--------------------------------- <br />
DECLARE @SQL NVARCHAR(2048), <br />
&nbsp; &nbsp; @separateur NCHAR(6) <br />
&nbsp;<br />
SET @separateur = N', dbo.' <br />
&nbsp;<br />
SELECT @SQL = ISNULL(@SQL, '') + name + @separateur <br />
FROM sys.procedures <br />
WHERE name LIKE '%client%' <br />
OR name LIKE '%livraison%' <br />
&nbsp;<br />
SELECT @SQL = 'DROP PROCEDURE ' + LEFT(@SQL, LEN(@SQL) - LEN(@separateur)) <br />
&nbsp;<br />
PRINT @SQL <br />
EXEC (@SQL)</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trouver le numéro d&#8217;une instance nommée de SQL Server</title>
		<link>https://blog.developpez.com/elsuket/p7725/snippets/trouver_le_numero_d_une_instance_nommee</link>
		<comments>https://blog.developpez.com/elsuket/p7725/snippets/trouver_le_numero_d_une_instance_nommee#comments</comments>
		<pubDate>Tue, 09 Jun 2009 20:53:50 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Vous aurez remarqué que pour une installation par défaut d&#8217;une instance nommée de SQL Server, celui-ci crée les fichiers de base de données dans le répertoire : C:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\Data où n est un entier. Dès lors, comment retrouver &#8230; <a href="https://blog.developpez.com/elsuket/p7725/snippets/trouver_le_numero_d_une_instance_nommee">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Vous aurez remarqué que pour une installation par défaut d&rsquo;une instance nommée de SQL Server, celui-ci crée les fichiers de base de données dans le répertoire :</p>
<blockquote><p>C:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\Data</p></blockquote>
<p>où n est un entier.</p>
<p>Dès lors, comment retrouver ce numéro ?</p>
<p><span id="more-44"></span></p>
<p>Le numéro de l&rsquo;instance et son nom logique sont en fait stockés dans la base de registre, sous la clé suivante :</p>
<blockquote><p>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL</p></blockquote>
<p>On peut donc y accéder:</p>
<p>=> <strong>Soit avec l&rsquo;utilitaire <em>RegEdit</em></strong></p>
<p><img src="http://blog.developpez.com/media/numInstanceRegedit.PNG" width="954" height="211" alt="" /></p>
<p>=> S<strong>oit avec la procédure stockée étendue système non documentée <em>xp_regread</em> :</strong></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 09/06/2009 - <br />
--------------------------------- <br />
EXEC master.sys.xp_regread <br />
&nbsp; @rootkey = 'HKEY_LOCAL_MACHINE', <br />
&nbsp; @key = 'SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL', <br />
&nbsp; @value_name = 'nomDeMonInstanceSQLServer'</div></td></tr></tbody></table></div>
<p>qui retourne :</p>
<p><img src="http://blog.developpez.com/media/numInstanceXpRegRead1.PNG" width="648" height="178" alt="" /></p>
<p>ou encore :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 11/05/2009 - <br />
--------------------------------- <br />
DECLARE @value VARCHAR(1024) <br />
&nbsp;<br />
EXEC master.sys.xp_regread <br />
&nbsp; @rootkey = 'HKEY_LOCAL_MACHINE', <br />
&nbsp; @key = 'SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL', <br />
&nbsp; @value_name = 'nomDeMonInstanceSQLServer', <br />
&nbsp; @value = @value OUTPUT <br />
&nbsp; <br />
SELECT @value AS numInstance</div></td></tr></tbody></table></div>
<p>qui retourne :</p>
<p><img src="http://blog.developpez.com/media/numInstanceXpRegRead2.PNG" width="649" height="257" alt="" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Concaténer les valeurs d&#8217;une colonne dans une variable</title>
		<link>https://blog.developpez.com/elsuket/p7460/snippets/concatener_les_valeurs_d_une_colonne_dan</link>
		<comments>https://blog.developpez.com/elsuket/p7460/snippets/concatener_les_valeurs_d_une_colonne_dan#comments</comments>
		<pubDate>Tue, 07 Apr 2009 21:11:22 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il est souvent demandé s&#8217;il est possible de concaténer les valeurs d&#8217;une colonne dans une variable, éventuellement en les séparant avec un symbole de ponctuation. Voici comment faire, sans curseur ni expression de table commune &#8230; Supposons la table suivante &#8230; <a href="https://blog.developpez.com/elsuket/p7460/snippets/concatener_les_valeurs_d_une_colonne_dan">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il est souvent demandé s&rsquo;il est possible de concaténer les valeurs d&rsquo;une colonne dans une variable, éventuellement en les séparant avec un symbole de ponctuation.<br />
Voici comment faire, sans curseur ni expression de table commune &#8230;<br />
<span id="more-40"></span><br />
Supposons la table suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE TABLE_TEST <br />
( <br />
&nbsp; Lettre CHAR(1) <br />
) <br />
GO</div></td></tr></tbody></table></div>
<p>Et le jeu de données suivant :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INSERT INTO dbo.TABLE_TEST (Lettre) VALUES ('A') <br />
INSERT INTO dbo.TABLE_TEST (Lettre) VALUES ('B') <br />
INSERT INTO dbo.TABLE_TEST (Lettre) VALUES ('C') <br />
INSERT INTO dbo.TABLE_TEST (Lettre) VALUES ('D') <br />
GO</div></td></tr></tbody></table></div>
<p>Si l&rsquo;on souhaite concaténer les valeurs de la colonne <em>Lettre</em> dans une variable de type chaîne de caractère, avec par exemple une virgule comme séparateur, il suffit d&rsquo;écrire :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 07/04/2009 - <br />
--------------------------------- <br />
DECLARE @concat VARCHAR(128) <br />
SELECT @concat = ISNULL(@concat, '') + Lettre + ',' <br />
FROM dbo.TABLE_TEST</div></td></tr></tbody></table></div>
<p>Et l&rsquo;on obtient ainsi :</p>
<blockquote><p>A, B, C, D,</p></blockquote>
<p>Pour aller plus <a href="http://blog.developpez.com/elsuket/p7311/t-sql/aggreger-des-donnees-non-numeriques-d-un/">loin</a>, mais cette fois avec une <a href="http://blog.developpez.com/elsuket/p6541/snippets/snippets-utilite-des-cte-recursives/">expression de table commune</a></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aggréger des données non numériques d&#8217;une entité par une liste de valeurs</title>
		<link>https://blog.developpez.com/elsuket/p7311/snippets/aggreger_des_donnees_non_numeriques_d_un</link>
		<comments>https://blog.developpez.com/elsuket/p7311/snippets/aggreger_des_donnees_non_numeriques_d_un#comments</comments>
		<pubDate>Wed, 04 Mar 2009 22:26:03 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il est souvent demandé sur le forum comment on peut créer une liste de valeurs stockées dans une colonne en une liste. Cela est en effet souvent demandé par le client pour des rapports, mais il n&#8217;est pas évident de &#8230; <a href="https://blog.developpez.com/elsuket/p7311/snippets/aggreger_des_donnees_non_numeriques_d_un">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il est souvent demandé sur le <a href="http://www.developpez.net/forums/f49/bases-donnees/ms-sql-server/">forum</a> comment on peut créer une liste de valeurs stockées dans une colonne en une liste.<br />
Cela est en effet souvent demandé par le client pour des rapports, mais il n&rsquo;est pas évident de prime abord de fournir un tel résultat, puisqu&rsquo;il est anti-relationnel !</p>
<p>Prenons pour exemple des adhérents à plusieurs clubs :</p>
<pre>
NomContact	NomClub
--------------- ------------
BipBip		SQLServer
BipBip		Oracle
BipBip		PostGreSQL
Coyotte		MySQL
Coyotte		FireBird
Titi		Sybase
Sylvestre	DB2
Sylvestre	SQLite
Bugs Bunny	SQLServer
Bugs Bunny	PostGreSQL
Daffy Duck	FireBird
Daffy Duck	DB2
Sam Le Pirate	SQLite
</pre>
<p>Le résultat recherché se présente sous la forme :</p>
<pre>
NomContact	ListeClub
--------------- -----------------------------
Titi		Sybase
Sam Le Pirate	SQLite
Daffy Duck	FireBird, DB2
Bugs Bunny	SQLServer, PostGreSQL
Sylvestre	DB2, SQLite
Coyotte		MySQL, FireBird
BipBip		SQLServer, Oracle, PostGreSQL
</pre>
<p><span id="more-3"></span></p>
<p>Représentons physiquement nos clubs et leurs adhérents :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 04/03/2009 - &nbsp;<br />
--------------------------------- <br />
CREATE TABLE Contact <br />
( <br />
&nbsp; IDContact INT IDENTITY CONSTRAINT PK_Contact PRIMARY KEY, <br />
&nbsp; NomContact VARCHAR(20) NOT NULL <br />
) <br />
GO <br />
&nbsp;<br />
CREATE TABLE Club <br />
( <br />
&nbsp; IDClub INT IDENTITY CONSTRAINT PK_Club PRIMARY KEY, <br />
&nbsp; NomClub VARCHAR(20) NOT NULL <br />
) <br />
GO <br />
&nbsp;<br />
CREATE TABLE Membre <br />
( <br />
&nbsp; IDMembre INT IDENTITY CONSTRAINT PK_Membre PRIMARY KEY, <br />
&nbsp; IDContact INT NOT NULL CONSTRAINT FK_Membre_IDContact FOREIGN KEY(IDContact) REFERENCES Contact(IDContact), <br />
&nbsp; IDClub INT NOT NULL CONSTRAINT FK_Membre_IDClub FOREIGN KEY(IDClub) REFERENCES Club(IDClub), <br />
&nbsp; CONSTRAINT UQ_Membre_IDContact_IDClub UNIQUE (IDContact, IDClub) <br />
) <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.Contact (NomContact) VALUES('BipBip') <br />
INSERT INTO dbo.Contact (NomContact) VALUES('Coyotte') <br />
INSERT INTO dbo.Contact (NomContact) VALUES('Titi') <br />
INSERT INTO dbo.Contact (NomContact) VALUES('Sylvestre') <br />
INSERT INTO dbo.Contact (NomContact) VALUES('Bugs Bunny') <br />
INSERT INTO dbo.Contact (NomContact) VALUES('Daffy Duck') <br />
INSERT INTO dbo.Contact (NomContact) VALUES('Sam Le Pirate') <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.Club (NomClub) VALUES ('SQLServer') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('Oracle') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('PostGreSQL') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('MySQL') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('FireBird') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('Sybase') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('DB2') <br />
INSERT INTO dbo.Club (NomClub) VALUES ('SQLite') <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (1, 1) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (1, 2) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (1, 3) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (2, 4) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (2, 5) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (3, 6) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (4, 7) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (4, 8) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (5, 1) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (5, 3) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (6, 5) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (6, 7) <br />
INSERT INTO dbo.Membre (IDContact, IDClub) VALUES (7, 8) <br />
GO</div></td></tr></tbody></table></div>
<p>La requête qui permet d&rsquo;obtenir tous les clubs auxquels participent tous nos contacts est alors simple :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT CONTACT.NomContact, <br />
&nbsp; &nbsp; CLUB.NomClub <br />
FROM dbo.Contact CONTACT <br />
JOIN dbo.Membre MEMBRE ON MBR.IDContact = CONTACT.IDContact <br />
JOIN dbo.Club CLUB ON CLUB.IDClub = MEMBRE.IDClub</div></td></tr></tbody></table></div>
<p>En revanche il est plus complexe d&rsquo;agréger toutes ces valeurs pour en fournir une liste par contact &#8230;<br />
Voyons comment on peut faire pour un seul membre :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DECLARE @nomContact VARCHAR(20), @listeClubs VARCHAR(1024) <br />
&nbsp;<br />
SELECT @nomContact = 'BipBip' <br />
&nbsp;<br />
SELECT @listeClubs = ISNULL(@listeClubs, '') + CLUB.NomClub + ', ' <br />
FROM dbo.Contact CONTACT <br />
JOIN dbo.Membre MEMBRE ON MEMBRE.IDContact = CONTACT.IDContact <br />
JOIN dbo.Club CLUB ON CLUB.IDClub = MEMBRE.IDClub <br />
WHERE CONTACT.NomContact = @nomContact <br />
&nbsp;<br />
SELECT @nomContact AS Contact, <br />
&nbsp; &nbsp; LEFT(@listeClubs, LEN(@listeClubs) - 1) AS ListeClubs</div></td></tr></tbody></table></div>
<p>Nous permet d&rsquo;obtenir :</p>
<pre>
Contact	ListeClubs
------- -----------------------------
BipBip	SQLServer, Oracle, PostGreSQL
</pre>
<p>Dès lors pour exécuter cette même requête pour tous les contacts, nous allons avoir (encore une fois diront certains) à la puissance des expressions de table commune récursives, introduites avec SQL Server 2005 :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 04/03/2009 - &nbsp;<br />
--------------------------------- <br />
WITH <br />
&nbsp; -- Extrait les informations pour chaque contact suivant la requête &quot;normale&quot; <br />
&nbsp; -- en attribuant à chaque tuple un indice arbitraire <br />
&nbsp; CTE_LISTE_BRUTE(IDContact, NomContact, NomClub, Indice) AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT CONTACT.IDContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; CONTACT.NomContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; CLUB.NomClub, <br />
&nbsp; &nbsp; &nbsp; &nbsp; ROW_NUMBER() OVER(PARTITION BY CONTACT.IDContact ORDER BY CONTACT.IDContact) AS Indice <br />
&nbsp; &nbsp; FROM dbo.Contact CONTACT <br />
&nbsp; &nbsp; JOIN dbo.Membre MEMBRE ON MEMBRE.IDContact = CONTACT.IDContact <br />
&nbsp; &nbsp; JOIN dbo.Club CLUB ON CLUB.IDClub = MEMBRE.IDClub <br />
&nbsp; ), <br />
&nbsp; -- Aggrège les informations pour chaque membre d'un club <br />
&nbsp; CTE_LISTE_CLUB(IDContact, NomContact, ListeClub, Compteur) AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; -- Recherche tous les contacts qui sont membres d'au moins un club <br />
&nbsp; &nbsp; &nbsp; SELECT IDContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NomContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CAST(NomClub AS VARCHAR(1024)) AS ListeClub, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 AS Compteur <br />
&nbsp; &nbsp; &nbsp; FROM CTE_LISTE_BRUTE <br />
&nbsp; &nbsp; &nbsp; WHERE Indice = 1 <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; -- Recherche les autres clubs adhérés par le même membre, pour chaque membre <br />
&nbsp; &nbsp; &nbsp; SELECT CTE_LISTE_CLUB.IDContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CTE_LISTE_CLUB.NomContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CAST(CTE_LISTE_CLUB.ListeClub + ', ' + CTE_LISTE_BRUTE.NomClub AS VARCHAR(1024)) AS ListeClub, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CTE_LISTE_CLUB.Compteur + 1 <br />
&nbsp; &nbsp; &nbsp; FROM CTE_LISTE_CLUB <br />
&nbsp; &nbsp; &nbsp; JOIN CTE_LISTE_BRUTE ON CTE_LISTE_CLUB.IDContact = CTE_LISTE_BRUTE.IDContact <br />
&nbsp; &nbsp; &nbsp; WHERE Indice = Compteur + 1 <br />
&nbsp; ), <br />
&nbsp; -- Recherche le nombre total d'adhésions pour chaque membre <br />
&nbsp; CTE_MAX(IDContact, maxCompteur) AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT IDContact, <br />
&nbsp; &nbsp; &nbsp; &nbsp; MAX(Compteur) AS maxCompteur <br />
&nbsp; &nbsp; FROM CTE_LISTE_CLUB <br />
&nbsp; &nbsp; GROUP BY IDContact <br />
&nbsp; ) <br />
SELECT CTE_LISTE_CLUB.NomContact, <br />
&nbsp; &nbsp; CTE_LISTE_CLUB.ListeClub <br />
FROM CTE_LISTE_CLUB <br />
JOIN CTE_MAX <br />
&nbsp; ON CTE_LISTE_CLUB.Compteur = CTE_MAX.maxCompteur <br />
&nbsp; AND CTE_LISTE_CLUB.IDContact = CTE_MAX.IDContact</div></td></tr></tbody></table></div>
<p>Nous obtenons ainsi :</p>
<pre>
NomContact	ListeClub
--------------- -----------------------------
Titi		Sybase
Sam Le Pirate	SQLite
Daffy Duck	FireBird, DB2
Bugs Bunny	SQLServer, PostGreSQL
Sylvestre	DB2, SQLite
Coyotte		MySQL, FireBird
BipBip		SQLServer, Oracle, PostGreSQL
</pre>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[Snippets] Calculer le PGCD de plusieurs nombres</title>
		<link>https://blog.developpez.com/elsuket/p6982/snippets/snippets_calculer_le_pgcd_de_plusieurs_n</link>
		<comments>https://blog.developpez.com/elsuket/p6982/snippets/snippets_calculer_le_pgcd_de_plusieurs_n#comments</comments>
		<pubDate>Fri, 19 Dec 2008 21:42:35 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Une internaute a récemment demandé comment on pouvait calculer le PGCD de plusieurs nombres en utilisant T-SQL. Amateur d&#8217;arithmétique, je me réjouissais de ce problème à résoudre. Voici donc une implémentation de l&#8217;arithmétique nécessaire au calcul du PGCD de plusieurs &#8230; <a href="https://blog.developpez.com/elsuket/p6982/snippets/snippets_calculer_le_pgcd_de_plusieurs_n">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Une internaute a récemment demandé comment on pouvait calculer le PGCD de plusieurs nombres en utilisant T-SQL.<br />
Amateur d&rsquo;arithmétique, je me réjouissais de ce problème à résoudre.<br />
Voici donc une implémentation de l&rsquo;arithmétique nécessaire au calcul du PGCD de plusieurs nombres &#8230;<br />
<span id="more-36"></span></p>
<p>Il faut d&rsquo;abord se rappeler comment on calcule le PGCD de deux nombres : c&rsquo;est le dernier reste entier de la division euclidienne du plus grand par le plus petit des deux nombres, c&rsquo;est à dire le modulo (a % b en SQL)</p>
<p>Mais aussi : (*)</p>
<blockquote><p>- PGCD(a, b, &#8230;, n) = PGCD(PGCD(PGCD(a, b), &#8230;), n)<br />
&#8211; PGCD(n, 0) = n</p></blockquote>
<p>Dès lors implémentons une première fonction scalaire pour calculer le PGCD de deux nombres :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 19/12/2008 - Calcule le PGCD de deux nombres - <br />
------------------------------------------------------------------- <br />
CREATE FUNCTION [dbo].[udf_Calcule_PGCD](@a INT, @b INT) <br />
&nbsp; RETURNS INT <br />
AS <br />
BEGIN <br />
&nbsp; DECLARE @pgcd INT <br />
&nbsp;<br />
&nbsp; IF @b = 0 <br />
&nbsp; &nbsp; SET @pgcd = @a <br />
&nbsp; ELSE <br />
&nbsp; BEGIN <br />
&nbsp; &nbsp; DECLARE @r INT <br />
&nbsp; &nbsp; SET @r = @a % @b <br />
&nbsp; &nbsp; SELECT @pgcd = dbo.udf_Calcule_PGCD(@b, @r) <br />
&nbsp; END <br />
&nbsp;<br />
&nbsp; RETURN @pgcd <br />
END <br />
GO</div></td></tr></tbody></table></div>
<p>Vérifions :</p>
<p><code class="codecolorer text default"><span class="text">SELECT dbo.udf_Calcule_PGCD (1820, 1176) AS PGCD</span></code></p>
<p>Retourne :</p>
<blockquote><p>PGCD<br />
&#8212;&#8212;&#8212;&#8211;<br />
28</p></blockquote>
<p>Comment faire maintenant pour calculer le PGCD de plusieurs nombres ?<br />
Nous allons combiner la récursivité proposée par les expressions de table commuunes, introduites par la norme SQL:2003 dans SQL Server 2005, et les propriétés de calcul du PGCD que j&rsquo;ai marquées plus haut d&rsquo;un astérisque.</p>
<p>Supposons la table suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE Tb_Test_PGCD <br />
( <br />
&nbsp; Nombre INT <br />
) <br />
GO</div></td></tr></tbody></table></div>
<p>Voici une procédure stockée permettant de calculer le PGCD de nombres qui seront stockés dans cette table :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 19/12/2008 - Calcule le PGCD des nombres stockés dans dbo.Tb_Test_PGCD - <br />
--------------------------------------------------------------------------------------------- <br />
CREATE PROCEDURE usp_Calcule_PGCD <br />
AS <br />
BEGIN <br />
&nbsp; WITH <br />
&nbsp; &nbsp; -- Calcule un indice pour tous les nombres stockés <br />
&nbsp; &nbsp; -- dans la colonne &quot;Nombre&quot; de la table dbo.Tb_Test_PGCD <br />
&nbsp; &nbsp; CTE_Nombres AS <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT Nombre, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ROW_NUMBER() OVER(ORDER BY Nombre DESC) Ordre <br />
&nbsp; &nbsp; &nbsp; FROM dbo.Tb_Test_PGCD <br />
&nbsp; &nbsp; ), <br />
&nbsp; &nbsp; -- Calcule récursivement le PGCD de tous les nombres stockés <br />
&nbsp; &nbsp; -- dans la colonne &quot;Nombre&quot; de la table dbo.Tb_Test_PGCD <br />
&nbsp; &nbsp; CTE_PGCD AS <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; -- Recherche du premier élément <br />
&nbsp; &nbsp; &nbsp; &nbsp; -- PGCD(n, 0 = n) <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT dbo.udf_Calcule_PGCD(Nombre, 0) AS PGCD, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 AS Indice <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM CTE_Nombres <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHERE Ordre = 1 <br />
&nbsp; &nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; &nbsp; -- Parcours des autres valeurs de la colonne <br />
&nbsp; &nbsp; &nbsp; &nbsp; -- &quot;Nombre&quot; de la table dbo.Tb_Test_PGCD <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT dbo.udf_Calcule_PGCD(PGCD, Nombre), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Indice + 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM CTE_Nombres, CTE_PGCD <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHERE Ordre = Indice <br />
&nbsp; &nbsp; ), <br />
&nbsp; &nbsp; CTE_MAX AS <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; -- Recherche de l'indice du dernier calcul <br />
&nbsp; &nbsp; &nbsp; -- Celui-ci a été incrémenté à chaque calcul de PGCD dans CTE_PGCD <br />
&nbsp; &nbsp; &nbsp; SELECT MAX(Indice) Indice <br />
&nbsp; &nbsp; &nbsp; FROM CTE_PGCD <br />
&nbsp; &nbsp; ) <br />
&nbsp; -- Recherche du dernier calcul de PGCD dans CTE_PGCD =&gt; résultat <br />
&nbsp; SELECT CTE_PGCD.PGCD <br />
&nbsp; FROM CTE_PGCD <br />
&nbsp; JOIN CTE_MAX ON CTE_MAX.Indice = CTE_PGCD.Indice <br />
END <br />
GO</div></td></tr></tbody></table></div>
<p>Effectuons quelques tests :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------ &nbsp;<br />
- Nicolas SOUQUET - 19/12/2008 &nbsp;<br />
------------------------------ &nbsp;<br />
SET NOCOUNT ON <br />
GO <br />
&nbsp;<br />
TRUNCATE TABLE dbo.Tb_Test_PGCD <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(1820) <br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(1176) <br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(700) <br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(9100) <br />
GO <br />
&nbsp;<br />
EXEC dbo.usp_Calcule_PGCD <br />
GO <br />
&nbsp;<br />
TRUNCATE TABLE dbo.Tb_Test_PGCD <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(18) <br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(15) <br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(21) <br />
INSERT INTO dbo.Tb_Test_PGCD VALUES(36) <br />
GO <br />
&nbsp;<br />
EXEC dbo.usp_Calcule_PGCD <br />
GO</div></td></tr></tbody></table></div>
<p>Retourne successivement:</p>
<blockquote><p>PGCD<br />
&#8212;&#8212;&#8212;&#8211;<br />
28</p>
<p>PGCD<br />
&#8212;&#8212;&#8212;&#8211;<br />
3
</p></blockquote>
<p>Une fois encore les <a href="http://blog.developpez.com/elsuket?title=snippets_utilite_des_cte_recursives">expressions de table commune</a> se sont montrées d&rsquo;une redoutable efficacité.</p>
<p>Merci à <a href="http://www.developpez.net/forums/d658574/bases-donnees/ms-sql-server/pgcd-sql-server/">Soazig</a> pour ce problème <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Snippets] Génération de nombres pseudo-aléatoires</title>
		<link>https://blog.developpez.com/elsuket/p6885/snippets/snippets_generation_de_nombres_aleatoire</link>
		<comments>https://blog.developpez.com/elsuket/p6885/snippets/snippets_generation_de_nombres_aleatoire#comments</comments>
		<pubDate>Sat, 06 Dec 2008 00:02:00 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Un participant au forum SQL Server de ce site a demandé comment on peut générer 10000 nombres entiers positifs aléatoires ne contenant pas de zéros, par une requête T-SQL. Je connaissais la fonction RAND(), qui suffit dans bien des situations &#8230; <a href="https://blog.developpez.com/elsuket/p6885/snippets/snippets_generation_de_nombres_aleatoire">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Un participant au forum SQL Server de ce site a demandé comment on peut générer 10000 nombres entiers positifs aléatoires ne contenant pas de zéros, par une requête T-SQL.<br />
Je connaissais la fonction RAND(), qui suffit dans bien des situations car on n&rsquo;a pas souvent besoin de générer une série de nombres aléatoires, pourtant celle-ci ne s&rsquo;est pas prêtée au jeu &#8230;</p>
<p><span id="more-35"></span></p>
<p>Avec une expression de table commune, j&rsquo;écrivais la requête suivante, dont je pensais qu&rsquo;elle allait générer 10 nombres aléatoires :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------ &nbsp;<br />
- Nicolas SOUQUET - 06/12/2008 &nbsp;<br />
------------------------------ &nbsp;<br />
WITH <br />
&nbsp; CTE_Random AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT 1 indice, RAND() nombre <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT indice + 1, RAND() nombre <br />
&nbsp; &nbsp; FROM CTE_Random <br />
&nbsp; &nbsp; WHERE indice &lt; 10 <br />
&nbsp; ) <br />
SELECT * <br />
FROM CTE_Random</div></td></tr></tbody></table></div>
<p>Problème : </p>
<blockquote><pre>indice      nombre
----------- ----------------------
1           0,948787066403352
2           0,810137410843534
3           0,810137410843534
4           0,810137410843534
5           0,810137410843534
6           0,810137410843534
7           0,810137410843534
8           0,810137410843534
9           0,810137410843534
10          0,810137410843534
</pre>
</blockquote>
<p>Seuls le premier nombre généré est différent des autres !</p>
<p>Je me suis alors souvenu de la fonction NEWID(), qui génère un GUID, et qui peut être utilisée pour identifier un ticket par exemple &#8230;<br />
L&rsquo;avantage de celle-ci par rapport à RAND(), c&rsquo;est qu&rsquo;elle génère des valeurs exclusivement différentes :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------ &nbsp;<br />
- Nicolas SOUQUET - 06/12/2008 &nbsp;<br />
------------------------------ &nbsp;<br />
WITH <br />
&nbsp; CTE_Random AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT 1 indice, NEWID() nombre <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT indice + 1, NEWID() nombre <br />
&nbsp; &nbsp; FROM CTE_Random <br />
&nbsp; &nbsp; WHERE indice &lt; 10 <br />
&nbsp; ) <br />
SELECT * <br />
FROM CTE_Random</div></td></tr></tbody></table></div>
<blockquote><pre>indice      nombre
----------- ------------------------------------
1           4BDE02EB-1535-4309-8FF4-9BE0FC9890FC
2           74A8CD0E-5158-42FC-8CB4-0965147FE41F
3           AF760F20-DEFA-4B25-ADB4-745B15C9BE5D
4           0200CCBE-454B-4D34-A755-52AC98384DD0
5           C9D8EA8F-64A7-47B4-A3DB-626EBA3C967B
6           3216696C-3316-46B7-BDD5-7F4EBEAF4F20
7           40F3B9A6-C6EE-4677-9455-2437C09F4930
8           28F01AB5-5924-4163-98A5-593A662D26AC
9           80F1C811-C929-4A86-B1BE-4726E27B43FD
10          8D794438-0A13-4658-9C20-6F546F7E41C8</pre>
</blockquote>
<p>Dès lors, comment passer d&rsquo;un GUID à une valeur numérique, ou au moins une représentation numérique de celui-ci ?<br />
Le tableau des transtypages autorisés dans la documentation des fonctions CAST et CONVERT précise que l&rsquo;on ne peut pas transtyper une donnée de type UNIQUEIDENTIFIER en un type de donnée numérique.<br />
Qu&rsquo;à cela ne tienne, on peut transtyper le type de données UNIQUEIDENTIFIER, de notre GUID, au type VARBINARY, et le type VARBINARY en type numérique :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------ &nbsp;<br />
- Nicolas SOUQUET - 06/12/2008 &nbsp;<br />
------------------------------ &nbsp;<br />
WITH <br />
&nbsp; CTE_Random AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT 1 indice, CAST(CAST(NEWID() AS VARBINARY) AS BIGINT) nombre <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT indice + 1, CAST(CAST(NEWID() AS VARBINARY) AS BIGINT) nombre <br />
&nbsp; &nbsp; FROM CTE_Random <br />
&nbsp; &nbsp; WHERE indice &lt; 10 <br />
&nbsp; ) <br />
SELECT * <br />
FROM CTE_Random</div></td></tr></tbody></table></div>
<blockquote><pre>indice      nombre
----------- --------------------
1           -5798444018420898861
2           -8387580781428009187
3           -8290221482251344193
4           -5517060763531941547
5           -5222611935137695036
6           -8084341965211989766
7           -6365110813593533953
8           -4855414462827669452
9           -6272538355892614409
10          -5045499018529999454</pre>
</blockquote>
<p>Le requis du participant au forum était d&rsquo;obtenir des nombres entiers positifs, or nous n&rsquo;avons là que des entiers négatifs.<br />
Utilisons la fonction ABS(), qui retourne la valeur absolue d&rsquo;un nombre :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------ &nbsp;<br />
- Nicolas SOUQUET - 06/12/2008 &nbsp;<br />
------------------------------ &nbsp;<br />
WITH <br />
&nbsp; CTE_Random AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT 1 indice, ABS(CAST(CAST(NEWID() AS VARBINARY) AS BIGINT)) nombre <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; SELECT indice + 1, ABS(CAST(CAST(NEWID() AS VARBINARY) AS BIGINT)) nombre <br />
&nbsp; &nbsp; &nbsp; FROM CTE_Random <br />
&nbsp; &nbsp; &nbsp; WHERE indice &lt; 10 <br />
&nbsp; ) <br />
SELECT * <br />
FROM CTE_Random</div></td></tr></tbody></table></div>
<blockquote><pre>indice      nombre
----------- --------------------
1           7906050049288686091
2           6497845688783947995
3           7055925192035141370
4           7818470519893116179
5           6240781906318427782
6           6648187948410848759
7           7992501322185322905
8           5480780527582611816
9           9050306324847691808
10          5335687916251733319</pre>
</blockquote>
<p>Comme nous avons transtypé en BIGINT, nous avons des entiers sur 19 chiffres.</p>
<p>Après avoir extrait de façon aléatoire 10 chiffres de chacun des 19 chiffres générés avec l&rsquo;aide de la fonction SUBSTRING(), et remplacé les zéros par des entiers générés avec la fonction RAND(), on obtient la requête suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------ &nbsp;<br />
- Nicolas SOUQUET - 06/12/2008 &nbsp;<br />
------------------------------ &nbsp;<br />
WITH &nbsp;<br />
&nbsp; CTE_RANDOM (Random, Indice) AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT REVERSE(REPLACE(SUBSTRING(CAST(ABS(CAST(CAST(NEWID() AS VARBINARY) AS BIGINT)) AS VARCHAR), CAST(RAND() * 10 AS INT), 10), '0', CAST(CAST(RAND() * 10 AS TINYINT) AS CHAR(1)))), 1 <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT REVERSE(REPLACE(SUBSTRING(CAST(ABS(CAST(CAST(NEWID() AS VARBINARY) AS BIGINT)) AS VARCHAR), CAST(RAND() * 10 AS INT), 10), '0', CAST(CAST(RAND() * 10 AS TINYINT) AS CHAR(1)))), Indice + 1 <br />
&nbsp; &nbsp; FROM CTE_RANDOM <br />
&nbsp; &nbsp; WHERE Indice &lt; 10000 <br />
&nbsp; ) <br />
SELECT Random <br />
FROM CTE_RANDOM <br />
WHERE Random NOT LIKE '0%' <br />
OPTION (MAXRECURSION 0)</div></td></tr></tbody></table></div>
<p>la clause OPTION avec l&rsquo;indicateur de requête MAXRECURSION est nécessaire pour outrepasser la récursivité maximale de 100 autorisée par SQL Server, et obtenir ainsi 10000 nombres aléatoires ne commençant pas par zéro.<br />
En effet comme l&rsquo;ensemble de nombres est retourné sous forme de chaîne, il peut commencer par zéro.<br />
Or lorsqu&rsquo;on transtype une chaîne de chiffres commençant par zéro en un type entier, ce(s) zéro est &laquo;&nbsp;supprimé&nbsp;&raquo;, et on obtiendra donc des nombres entiers de moins de 10 chiffres.</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Snippets &#8211; Utilité des CTE récursives</title>
		<link>https://blog.developpez.com/elsuket/p6541/snippets/snippets_utilite_des_cte_recursives</link>
		<comments>https://blog.developpez.com/elsuket/p6541/snippets/snippets_utilite_des_cte_recursives#comments</comments>
		<pubDate>Wed, 08 Oct 2008 21:21:23 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Voici quelques snippets utilisant des CTE récursives à des fins utilitaires : 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180------------------------------------------------------------------------- -- Nicolas SOUQUET - 08/10/2008 - Découper une chaîne en ses caractères - ------------------------------------------------------------------------- DECLARE @String VARCHAR(64) SELECT @String = 'Ceci est un test ...'; &#160; WITH &#8230; <a href="https://blog.developpez.com/elsuket/p6541/snippets/snippets_utilite_des_cte_recursives">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Voici quelques snippets utilisant des CTE récursives à des fins utilitaires :</p>
<p><span id="more-34"></span></p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br />134<br />135<br />136<br />137<br />138<br />139<br />140<br />141<br />142<br />143<br />144<br />145<br />146<br />147<br />148<br />149<br />150<br />151<br />152<br />153<br />154<br />155<br />156<br />157<br />158<br />159<br />160<br />161<br />162<br />163<br />164<br />165<br />166<br />167<br />168<br />169<br />170<br />171<br />172<br />173<br />174<br />175<br />176<br />177<br />178<br />179<br />180<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Découper une chaîne en ses caractères - <br />
------------------------------------------------------------------------- <br />
DECLARE @String VARCHAR(64) <br />
SELECT @String = 'Ceci est un test ...'; <br />
&nbsp;<br />
WITH CTE_PARSE AS <br />
( <br />
&nbsp; &nbsp; SELECT SUBSTRING(@String, 1, 1) Caractere, 1 Indice <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT SUBSTRING(@String, Indice + 1, 1), Indice + 1 <br />
&nbsp; &nbsp; FROM CTE_PARSE <br />
&nbsp; &nbsp; WHERE (Indice + 1) &lt;= LEN(@String) <br />
) <br />
SELECT Caractere <br />
FROM CTE_PARSE <br />
OPTION (MAXRECURSION 0) <br />
&nbsp;<br />
&nbsp;<br />
------------------------------------------------------------------------------------------------ <br />
-- Nicolas SOUQUET - 08/10/2008 - Découper les chaines d'une colonne d'une table en leurs mots - <br />
------------------------------------------------------------------------------------------------ <br />
CREATE TABLE TbPhrase <br />
( <br />
&nbsp; IDPhrase INT IDENTITY CONSTRAINT PK_TbPhrase PRIMARY KEY, <br />
&nbsp; Phrase VARCHAR(128) <br />
) <br />
GO <br />
&nbsp;<br />
INSERT INTO dbo.TbPhrase VALUES ('C''est le printemps chic chic') <br />
INSERT INTO dbo.TbPhrase VALUES ('Il fait beau demain') <br />
GO <br />
&nbsp;<br />
;WITH <br />
&nbsp; CTE (IDPhrase, Deb, Fin, Indice) AS &nbsp;<br />
&nbsp; ( &nbsp;<br />
&nbsp; &nbsp; &nbsp; SELECT T.IDPhrase, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 Deb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CHARINDEX(CHAR(32), T.Phrase + CHAR(32)) Fin, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 AS Indice <br />
&nbsp; &nbsp; &nbsp; FROM dbo.TbPhrase AS T <br />
&nbsp; &nbsp; UNION ALL &nbsp;<br />
&nbsp; &nbsp; &nbsp; SELECT T.IDPhrase, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CTE.Fin + 1, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CHARINDEX(CHAR(32), T.Phrase + CHAR(32), CTE.Fin + 1), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CTE.Indice + 1 <br />
&nbsp; &nbsp; &nbsp; FROM CTE <br />
&nbsp; &nbsp; &nbsp; JOIN dbo.TbPhrase AS T ON T.IDPhrase = CTE.IDPhrase <br />
&nbsp; &nbsp; &nbsp; WHERE CHARINDEX(CHAR(32), T.Phrase + CHAR(32), CTE.Fin + 1) &gt; 0 <br />
&nbsp; ) <br />
SELECT T.Phrase, <br />
&nbsp; &nbsp; SUBSTRING(T.Phrase, CTE.Deb , CTE.Fin - CTE.Deb) AS Mots <br />
FROM CTE &nbsp;<br />
JOIN dbo.TbPhrase AS T ON T.IDPhrase = CTE.IDPhrase <br />
ORDER BY CTE.IDPhrase <br />
&nbsp;<br />
-------------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Decouper une chaine en ses mots séparés par des virgules - <br />
-------------------------------------------------------------------------------------------- <br />
DECLARE @str VARCHAR(64) <br />
SET @str = 'toto,titi,tutu,tata'; <br />
&nbsp;<br />
WITH CTE (Deb, Fin) AS <br />
( <br />
&nbsp; SELECT 1 Deb, CHARINDEX(',', @str + ',') Fin <br />
&nbsp;UNION ALL <br />
&nbsp; SELECT Fin + 1, CHARINDEX(',', @str + ',', Fin + 1) <br />
&nbsp; FROM CTE <br />
&nbsp; WHERE CHARINDEX( ',', @str + ',', Fin + 1 ) &gt; 0 <br />
) <br />
SELECT SUBSTRING(@str, Deb , Fin - Deb), Deb, Fin <br />
FROM CTE <br />
&nbsp;<br />
-------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Découper une chaîne avec un séparateur - <br />
-------------------------------------------------------------------------- <br />
DECLARE @String VARCHAR(64) SET @String = 'un,deux,trois,quatre,cinq'; <br />
DECLARE @Separator CHAR(1) SET @Separator = ','; <br />
WITH INDICES AS <br />
( <br />
&nbsp; &nbsp; SELECT 0 Deb, 1 Fin <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT Fin, CHARINDEX(@Separator, @String, Fin) + LEN(@Separator) <br />
&nbsp; &nbsp; FROM INDICES <br />
&nbsp; &nbsp; WHERE Fin &gt; Deb <br />
) <br />
SELECT SUBSTRING( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @String, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Deb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CASE <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN Fin &gt; LEN(@Separator) THEN Fin - Deb - LEN(@Separator) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE LEN(@String) - Deb + 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; &nbsp; ) String, <br />
&nbsp; &nbsp; &nbsp; &nbsp; Deb, <br />
&nbsp; &nbsp; &nbsp; &nbsp; Fin, <br />
&nbsp; &nbsp; &nbsp; &nbsp; LEN(@String) - Deb + 1 Lgr <br />
FROM INDICES WHERE Deb &gt; 0 <br />
&nbsp;<br />
--------------------------------------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Fonction de mise en majuscule de la première lettre de tous les mots d'une phrase - <br />
--------------------------------------------------------------------------------------------------------------------- <br />
CREATE FUNCTION fPremiereLettreMajuscule (@str VARCHAR(8000)) <br />
&nbsp; RETURNS VARCHAR(8000) <br />
AS <br />
BEGIN <br />
&nbsp; DECLARE @result VARCHAR(8000); <br />
&nbsp;<br />
&nbsp; -- Extraction des mots de la phrase par recherche des espaces <br />
&nbsp; WITH <br />
&nbsp; &nbsp; CTE_Espaces AS <br />
&nbsp; &nbsp; ( <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT 1 Deb, CHARINDEX(' ', @str + ' ') Fin <br />
&nbsp; &nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; &nbsp; SELECT Fin + 1, CHARINDEX(' ', @str + ' ', Fin + 1) <br />
&nbsp; &nbsp; &nbsp; &nbsp; FROM CTE_Espaces <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHERE CHARINDEX(' ', @str + ' ', Fin + 1 ) &gt; 0 <br />
&nbsp; &nbsp; ) <br />
&nbsp; -- Formatage des mots et concaténation <br />
&nbsp; SELECT @result = ISNULL(@result, '') + UPPER(SUBSTRING(SUBSTRING(@str, Deb, Fin), 1, 1)) + LOWER(SUBSTRING(SUBSTRING(@str, Deb, Fin - Deb + 1), 2, Fin)) <br />
&nbsp; FROM CTE_Espaces <br />
&nbsp;<br />
&nbsp; RETURN @result <br />
END <br />
GO <br />
&nbsp;<br />
----------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Créer une plage de dates entre deux dates - <br />
----------------------------------------------------------------------------- <br />
DECLARE @DateDeb DATETIME SET @DateDeb = '20080810' <br />
DECLARE @DateFin DATETIME SET @DateFin = '20080820'; <br />
WITH DATES AS <br />
( <br />
&nbsp; &nbsp; SELECT @DateDeb Date, 1 Indice <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT @DateDeb + Indice Date, Indice + 1 Indice <br />
&nbsp; &nbsp; FROM DATES <br />
&nbsp; &nbsp; WHERE Date &lt; @DateFin <br />
) <br />
SELECT * FROM DATES <br />
&nbsp;<br />
------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Faire la somme de nombres d'une plage - <br />
------------------------------------------------------------------------- <br />
DECLARE @nMinBound INT, <br />
&nbsp; &nbsp; @nMaxBound INT <br />
&nbsp;<br />
SET @nMinBound = 1 <br />
SET @nMaxBound = 10000; <br />
&nbsp;<br />
WITH SommeDeNombres AS <br />
( <br />
&nbsp; &nbsp; SELECT 0 Somme, @nMinBound minBound, @nMaxBound maxBound <br />
&nbsp; UNION ALL <br />
&nbsp; &nbsp; SELECT Somme + minBound, minBound + 1, maxBound <br />
&nbsp; &nbsp; FROM SommeDeNombres <br />
&nbsp; &nbsp; WHERE minBound &lt;= maxBound <br />
) <br />
SELECT Somme <br />
FROM SommeDeNombres <br />
WHERE minBound = maxBound + 1 <br />
OPTION (MAXRECURSION 0) <br />
&nbsp;<br />
---------------------------------------------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 08/10/2008 - Générer la liste de tous les jours d'un mois de l'année courante - <br />
---------------------------------------------------------------------------------------------------- <br />
DECLARE @month TINYINT <br />
SET @month = 11; <br />
&nbsp;<br />
WITH <br />
&nbsp; CTE_Days AS <br />
&nbsp; ( <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(month, @month, DATEADD(month, -MONTH(GETDATE()), DATEADD(day, -DAY(GETDATE()) + 1, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)))) D <br />
&nbsp; &nbsp; UNION ALL <br />
&nbsp; &nbsp; &nbsp; SELECT DATEADD(day, 1, D) <br />
&nbsp; &nbsp; &nbsp; FROM CTE_Days <br />
&nbsp; &nbsp; &nbsp; WHERE D &lt; DATEADD(day, -1, DATEADD(month, 1, DATEADD(month, @month, DATEADD(month, -MONTH(GETDATE()), DATEADD(day, -DAY(GETDATE()) + 1, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)))))) <br />
&nbsp; ) <br />
SELECT D <br />
FROM CTE_Days</div></td></tr></tbody></table></div>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Gérer des couleurs en base de données</title>
		<link>https://blog.developpez.com/elsuket/p7831/snippets/title_139</link>
		<comments>https://blog.developpez.com/elsuket/p7831/snippets/title_139#comments</comments>
		<pubDate>Fri, 03 Jul 2009 13:27:20 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il peut vite devenir difficile de gérer de façon uniforme les couleurs pour plusieurs applications accédant à une base de données : &#8211; s&#8217;il s&#8217;agit d&#8217;une application web, les couleurs s&#8217;affichent sur 6 caractères alphanumériques de la base hexadécimale, &#8211; &#8230; <a href="https://blog.developpez.com/elsuket/p7831/snippets/title_139">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il peut vite devenir difficile de gérer de façon uniforme les couleurs pour plusieurs applications accédant à une base de données :</p>
<p>&#8211; s&rsquo;il s&rsquo;agit d&rsquo;une application web, les couleurs s&rsquo;affichent sur 6 caractères alphanumériques de la base hexadécimale,<br />
&#8211; s&rsquo;il s&rsquo;agit d&rsquo;une application lourde, elle peut interpréter les couleurs comme un entier qui est la somme RVB, ou bien sous forme hexadécimale.</p>
<p>Voyons comment gérer cela simplement &#8230;</p>
<p><span id="more-51"></span></p>
<p>Voici une table qui fera tous les calculs automatiquement à partir des trois composantes RVB :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - &nbsp;<br />
--------------------------------- <br />
CREATE TABLE TbCouleur <br />
( <br />
&nbsp; IDCouleur INT NOT NULL IDENTITY CONSTRAINT PK_TbCouleur PRIMARY KEY, <br />
&nbsp; nomCouleur VARCHAR(10) NOT NULL CONSTRAINT UQ_TbCouleur_nomCouleur UNIQUE, <br />
&nbsp; composanteRouge TINYINT, <br />
&nbsp; composanteVert TINYINT, <br />
&nbsp; composanteBleu TINYINT, <br />
&nbsp; Decimale AS (composanteRouge + composanteVert * 256 + composanteBleu * 256 * 256) PERSISTED NOT NULL, <br />
&nbsp; Hexadecimale AS (CAST(composanteRouge + composanteVert * 256 + composanteBleu * 256 * 256 AS VARBINARY(3))) PERSISTED NOT NULL, <br />
&nbsp; HTML AS (dbo.Fn_RVB_To_HTML(composanteRouge, composanteVert, composanteBleu)) &nbsp;PERSISTED NOT NULL, <br />
&nbsp; CONSTRAINT UQ_TbCouleur_composanteRouge_composanteVert_composanteBleu UNIQUE (composanteRouge, composanteVert, composanteBleu) <br />
)</div></td></tr></tbody></table></div>
<p>L&rsquo;utilisation de colonnes calculées (persistées, mais ce n&rsquo;est pas obligatoire !) pour faire effectuer tous les calculs au moteur de base de données rend très simple toute saisie de nouvelles couleurs.</p>
<p>Pour calculer le codage HTML, nous utilisons la fonction suivante, dont le code est un peu barbare, mais efficace :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - &nbsp;<br />
--------------------------------- <br />
CREATE FUNCTION Fn_RVB_To_HTML <br />
&nbsp; ( <br />
&nbsp; &nbsp; @rouge TINYINT, <br />
&nbsp; &nbsp; @vert TINYINT, <br />
&nbsp; &nbsp; @bleu TINYINT <br />
&nbsp; ) <br />
&nbsp; RETURNS CHAR(6) <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; RETURN <br />
&nbsp; ( <br />
&nbsp; &nbsp; CASE @rouge / 16 <br />
&nbsp; &nbsp; &nbsp; WHEN 0 THEN '0' <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '1' <br />
&nbsp; &nbsp; &nbsp; WHEN 2 THEN '2' <br />
&nbsp; &nbsp; &nbsp; WHEN 3 THEN '3' <br />
&nbsp; &nbsp; &nbsp; WHEN 4 THEN '4' <br />
&nbsp; &nbsp; &nbsp; WHEN 5 THEN '5' <br />
&nbsp; &nbsp; &nbsp; WHEN 6 THEN '6' <br />
&nbsp; &nbsp; &nbsp; WHEN 7 THEN '7' <br />
&nbsp; &nbsp; &nbsp; WHEN 8 THEN '8' <br />
&nbsp; &nbsp; &nbsp; WHEN 9 THEN '9' <br />
&nbsp; &nbsp; &nbsp; WHEN 10 THEN 'A' <br />
&nbsp; &nbsp; &nbsp; WHEN 11 THEN 'B' <br />
&nbsp; &nbsp; &nbsp; WHEN 12 THEN 'C' <br />
&nbsp; &nbsp; &nbsp; WHEN 13 THEN 'D' <br />
&nbsp; &nbsp; &nbsp; WHEN 14 THEN 'E' <br />
&nbsp; &nbsp; &nbsp; WHEN 15 THEN 'F' <br />
&nbsp; &nbsp; END + <br />
&nbsp; &nbsp; CASE @rouge % 16 <br />
&nbsp; &nbsp; &nbsp; WHEN 0 THEN '0' <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '1' <br />
&nbsp; &nbsp; &nbsp; WHEN 2 THEN '2' <br />
&nbsp; &nbsp; &nbsp; WHEN 3 THEN '3' <br />
&nbsp; &nbsp; &nbsp; WHEN 4 THEN '4' <br />
&nbsp; &nbsp; &nbsp; WHEN 5 THEN '5' <br />
&nbsp; &nbsp; &nbsp; WHEN 6 THEN '6' <br />
&nbsp; &nbsp; &nbsp; WHEN 7 THEN '7' <br />
&nbsp; &nbsp; &nbsp; WHEN 8 THEN '8' <br />
&nbsp; &nbsp; &nbsp; WHEN 9 THEN '9' <br />
&nbsp; &nbsp; &nbsp; WHEN 10 THEN 'A' <br />
&nbsp; &nbsp; &nbsp; WHEN 11 THEN 'B' <br />
&nbsp; &nbsp; &nbsp; WHEN 12 THEN 'C' <br />
&nbsp; &nbsp; &nbsp; WHEN 13 THEN 'D' <br />
&nbsp; &nbsp; &nbsp; WHEN 14 THEN 'E' <br />
&nbsp; &nbsp; &nbsp; WHEN 15 THEN 'F' <br />
&nbsp; &nbsp; END + <br />
&nbsp; &nbsp; CASE @vert / 16 <br />
&nbsp; &nbsp; &nbsp; WHEN 0 THEN '0' <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '1' <br />
&nbsp; &nbsp; &nbsp; WHEN 2 THEN '2' <br />
&nbsp; &nbsp; &nbsp; WHEN 3 THEN '3' <br />
&nbsp; &nbsp; &nbsp; WHEN 4 THEN '4' <br />
&nbsp; &nbsp; &nbsp; WHEN 5 THEN '5' <br />
&nbsp; &nbsp; &nbsp; WHEN 6 THEN '6' <br />
&nbsp; &nbsp; &nbsp; WHEN 7 THEN '7' <br />
&nbsp; &nbsp; &nbsp; WHEN 8 THEN '8' <br />
&nbsp; &nbsp; &nbsp; WHEN 9 THEN '9' <br />
&nbsp; &nbsp; &nbsp; WHEN 10 THEN 'A' <br />
&nbsp; &nbsp; &nbsp; WHEN 11 THEN 'B' <br />
&nbsp; &nbsp; &nbsp; WHEN 12 THEN 'C' <br />
&nbsp; &nbsp; &nbsp; WHEN 13 THEN 'D' <br />
&nbsp; &nbsp; &nbsp; WHEN 14 THEN 'E' <br />
&nbsp; &nbsp; &nbsp; WHEN 15 THEN 'F' <br />
&nbsp; &nbsp; END + <br />
&nbsp; &nbsp; CASE @vert % 16 <br />
&nbsp; &nbsp; &nbsp; WHEN 0 THEN '0' <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '1' <br />
&nbsp; &nbsp; &nbsp; WHEN 2 THEN '2' <br />
&nbsp; &nbsp; &nbsp; WHEN 3 THEN '3' <br />
&nbsp; &nbsp; &nbsp; WHEN 4 THEN '4' <br />
&nbsp; &nbsp; &nbsp; WHEN 5 THEN '5' <br />
&nbsp; &nbsp; &nbsp; WHEN 6 THEN '6' <br />
&nbsp; &nbsp; &nbsp; WHEN 7 THEN '7' <br />
&nbsp; &nbsp; &nbsp; WHEN 8 THEN '8' <br />
&nbsp; &nbsp; &nbsp; WHEN 9 THEN '9' <br />
&nbsp; &nbsp; &nbsp; WHEN 10 THEN 'A' <br />
&nbsp; &nbsp; &nbsp; WHEN 11 THEN 'B' <br />
&nbsp; &nbsp; &nbsp; WHEN 12 THEN 'C' <br />
&nbsp; &nbsp; &nbsp; WHEN 13 THEN 'D' <br />
&nbsp; &nbsp; &nbsp; WHEN 14 THEN 'E' <br />
&nbsp; &nbsp; &nbsp; WHEN 15 THEN 'F' <br />
&nbsp; &nbsp; END + <br />
&nbsp; &nbsp; CASE @bleu / 16 <br />
&nbsp; &nbsp; &nbsp; WHEN 0 THEN '0' <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '1' <br />
&nbsp; &nbsp; &nbsp; WHEN 2 THEN '2' <br />
&nbsp; &nbsp; &nbsp; WHEN 3 THEN '3' <br />
&nbsp; &nbsp; &nbsp; WHEN 4 THEN '4' <br />
&nbsp; &nbsp; &nbsp; WHEN 5 THEN '5' <br />
&nbsp; &nbsp; &nbsp; WHEN 6 THEN '6' <br />
&nbsp; &nbsp; &nbsp; WHEN 7 THEN '7' <br />
&nbsp; &nbsp; &nbsp; WHEN 8 THEN '8' <br />
&nbsp; &nbsp; &nbsp; WHEN 9 THEN '9' <br />
&nbsp; &nbsp; &nbsp; WHEN 10 THEN 'A' <br />
&nbsp; &nbsp; &nbsp; WHEN 11 THEN 'B' <br />
&nbsp; &nbsp; &nbsp; WHEN 12 THEN 'C' <br />
&nbsp; &nbsp; &nbsp; WHEN 13 THEN 'D' <br />
&nbsp; &nbsp; &nbsp; WHEN 14 THEN 'E' <br />
&nbsp; &nbsp; &nbsp; WHEN 15 THEN 'F' <br />
&nbsp; &nbsp; END + <br />
&nbsp; &nbsp; CASE @bleu % 16 <br />
&nbsp; &nbsp; &nbsp; WHEN 0 THEN '0' <br />
&nbsp; &nbsp; &nbsp; WHEN 1 THEN '1' <br />
&nbsp; &nbsp; &nbsp; WHEN 2 THEN '2' <br />
&nbsp; &nbsp; &nbsp; WHEN 3 THEN '3' <br />
&nbsp; &nbsp; &nbsp; WHEN 4 THEN '4' <br />
&nbsp; &nbsp; &nbsp; WHEN 5 THEN '5' <br />
&nbsp; &nbsp; &nbsp; WHEN 6 THEN '6' <br />
&nbsp; &nbsp; &nbsp; WHEN 7 THEN '7' <br />
&nbsp; &nbsp; &nbsp; WHEN 8 THEN '8' <br />
&nbsp; &nbsp; &nbsp; WHEN 9 THEN '9' <br />
&nbsp; &nbsp; &nbsp; WHEN 10 THEN 'A' <br />
&nbsp; &nbsp; &nbsp; WHEN 11 THEN 'B' <br />
&nbsp; &nbsp; &nbsp; WHEN 12 THEN 'C' <br />
&nbsp; &nbsp; &nbsp; WHEN 13 THEN 'D' <br />
&nbsp; &nbsp; &nbsp; WHEN 14 THEN 'E' <br />
&nbsp; &nbsp; &nbsp; WHEN 15 THEN 'F' <br />
&nbsp; &nbsp; END <br />
&nbsp; ) <br />
END</div></td></tr></tbody></table></div>
<p>Ainsi l&rsquo;ajout d&rsquo;une nouvelle couleur dans la table se fait simplement :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - &nbsp;<br />
--------------------------------- <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Blanc', 255, 255, 255) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Noir', 0, 0, 0) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Gris', 190, 190, 190) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Rouge', 255, 0, 0) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Vert', 0, 255, 0) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Bleau', 0, 0, 255) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Jaune', 255, 255, 0) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Orange', 255, 165, 0) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Rose', 255, 192, 203) <br />
INSERT INTO dbo.TbCouleur(nomCouleur, composanteRouge, composanteVert, composanteBleu) VALUES ('Violet', 238, 130, 238)</div></td></tr></tbody></table></div>
<p>ou encore à l&rsquo;aide de la procédure stockée suivante :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - &nbsp;<br />
--------------------------------- <br />
CREATE PROCEDURE Ps_Couleur_Ajouter <br />
&nbsp; @nomCouleur VARCHAR(10), <br />
&nbsp; @composanteRouge TINYINT, <br />
&nbsp; @composanteVert TINYINT, <br />
&nbsp; @composanteBleu TINYINT <br />
AS <br />
BEGIN <br />
&nbsp; INSERT INTO dbo.TbCouleur <br />
&nbsp; ( <br />
&nbsp; &nbsp; nomCouleur, <br />
&nbsp; &nbsp; composanteRouge, <br />
&nbsp; &nbsp; composanteVert, <br />
&nbsp; &nbsp; composanteBleu <br />
&nbsp; ) <br />
&nbsp; VALUES <br />
&nbsp; ( <br />
&nbsp; &nbsp; @nomCouleur, <br />
&nbsp; &nbsp; @composanteRouge, <br />
&nbsp; &nbsp; @composanteVert, <br />
&nbsp; &nbsp; @composanteBleu <br />
&nbsp; ) <br />
END</div></td></tr></tbody></table></div>
<p>Et pour ajouter les couleurs :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - &nbsp;<br />
--------------------------------- <br />
EXEC dbo.Ps_Couleur_Ajouter 'Blanc', 255, 255, 255 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Noir', 0, 0, 0 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Gris', 190, 190, 190 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Rouge', 255, 0, 0 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Vert', 0, 255, 0 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Bleau', 0, 0, 255 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Jaune', 255, 255, 0 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Orange', 255, 165, 0 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Rose', 255, 192, 203 <br />
EXEC dbo.Ps_Couleur_Ajouter 'Violet', 238, 130, 238</div></td></tr></tbody></table></div>
<p>Et le résultat est le suivant :</p>
<p><img src="http://blog.developpez.com/media/couleurs.PNG" width="652" height="301" alt="" /></p>
<p>Les trois fonctions suivantes permettent d&rsquo;obtenir la couleur souhaitée dans la représentation qui conviendra suivant l&rsquo;application :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">----------------------------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - Fn_Couleur_GetRVB - <br />
----------------------------------------------------- <br />
CREATE FUNCTION Fn_Couleur_GetRVB <br />
&nbsp; (@nomCouleur VARCHAR(10)) <br />
RETURNS TABLE <br />
WITH SCHEMABINDING <br />
AS <br />
RETURN <br />
( <br />
&nbsp; SELECT composanteRouge AS R, <br />
&nbsp; &nbsp; &nbsp; composanteVert AS V, <br />
&nbsp; &nbsp; &nbsp; composanteBleu AS B <br />
&nbsp; FROM dbo.TbCouleur <br />
&nbsp; WHERE nomCouleur = @nomCouleur <br />
) <br />
&nbsp;<br />
------------------------------------------------------ <br />
-- Nicolas SOUQUET - 03/07/2009 - Fn_Couleur_GetHTML - <br />
------------------------------------------------------ <br />
CREATE FUNCTION Fn_Couleur_GetHTML <br />
&nbsp; (@nomCouleur VARCHAR(10)) <br />
&nbsp; RETURNS CHAR(6) <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; RETURN <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT HTML <br />
&nbsp; &nbsp; FROM dbo.TbCouleur <br />
&nbsp; &nbsp; WHERE nomCouleur = @nomCouleur <br />
&nbsp; ) <br />
END <br />
&nbsp;<br />
---------------------------------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - Fn_Couleur_GetDecimale - <br />
---------------------------------------------------------- <br />
CREATE FUNCTION Fn_Couleur_GetDecimale <br />
&nbsp; (@nomCouleur VARCHAR(10)) <br />
&nbsp; RETURNS INT <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; RETURN <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT Decimale <br />
&nbsp; &nbsp; FROM dbo.TbCouleur <br />
&nbsp; &nbsp; WHERE nomCouleur = @nomCouleur <br />
&nbsp; ) <br />
END <br />
&nbsp;<br />
-------------------------------------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - Fn_Couleur_GetHexadecimale - <br />
-------------------------------------------------------------- <br />
CREATE FUNCTION Fn_Couleur_GetHexadecimale <br />
&nbsp; (@nomCouleur VARCHAR(10)) <br />
&nbsp; RETURNS VARBINARY(3) <br />
&nbsp; WITH SCHEMABINDING <br />
AS <br />
BEGIN <br />
&nbsp; RETURN <br />
&nbsp; ( <br />
&nbsp; &nbsp; SELECT Hexadecimale <br />
&nbsp; &nbsp; FROM dbo.TbCouleur <br />
&nbsp; &nbsp; WHERE nomCouleur = @nomCouleur <br />
&nbsp; ) <br />
END</div></td></tr></tbody></table></div>
<p>On peut ensuite envisager le code d&rsquo;une procédure comme suit :</p>
<div class="codecolorer-container text vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--------------------------------- <br />
-- Nicolas SOUQUET - 03/07/2009 - &nbsp;<br />
--------------------------------- <br />
CREATE PROCEDURE maProcedure <br />
&nbsp; @... <br />
&nbsp; @application <br />
AS <br />
BEGIN <br />
&nbsp; SELECT CASE ETAT <br />
&nbsp; &nbsp; &nbsp; &nbsp; WHEN uneValeur THEN CASE @application <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'HTML' THEN dbo.Fn_Couleur_GetHTML('Rouge') <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'EXE' THEN dbo.Fn_Couleur_GetDecimale('Rouge') <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; &nbsp; ELSE CASE @application <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'HTML' THEN dbo.Fn_Couleur_GetHTML('Blanc') <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHEN 'EXE' THEN dbo.Fn_Couleur_GetDecimale('Blanc') <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END <br />
&nbsp; &nbsp; &nbsp; END <br />
&nbsp; FROM dbo.TbEtat AS ETAT <br />
END</div></td></tr></tbody></table></div>
<p>Bien sûr il est préférable de stocker les divers états possibles dans une table et de gérer le CASE avec la valeur de clé de la table.<br />
On peut également penser à récupérer une représentation d&rsquo;une couleur à partir d&rsquo;une autre &#8230;</p>
<p>ElSuket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
