<?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>David Barbarin &#187; CLR</title>
	<atom:link href="https://blog.developpez.com/mikedavem/pcategory/sql-server-2005/clr/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/mikedavem</link>
	<description>MVP DataPlatform - MCM SQL Server</description>
	<lastBuildDate>Thu, 09 Sep 2021 21:19:50 +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>UDF CLR ou UDF SQL</title>
		<link>https://blog.developpez.com/mikedavem/p7285/sql-server-2005/clr/title_123</link>
		<comments>https://blog.developpez.com/mikedavem/p7285/sql-server-2005/clr/title_123#comments</comments>
		<pubDate>Thu, 26 Feb 2009 08:22:10 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[CLR]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Une des nouveautés introduites par sqlserver sont les types et fonctions utilisateurs (UDT / UDF) basés sur le common runtime language (CLR). Bien que cette nouvelle fonctionnalité s&#8217;éloigne de la norme SQL, elle permet d&#8217;étendre le champ d&#8217;action du développeur. &#8230; <a href="https://blog.developpez.com/mikedavem/p7285/sql-server-2005/clr/title_123">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><font size="2">Une des nouveautés introduites par sqlserver sont les types et fonctions utilisateurs (UDT / UDF) basés sur le common runtime language (CLR). Bien que cette nouvelle fonctionnalité s&rsquo;éloigne de la norme SQL, elle permet d&rsquo;étendre le champ d&rsquo;action du développeur. Mais dans quel cas est-il judicieux de les utiliser ?</font></p>
<p><span id="more-58"></span></p>
<p><font size="2">Il y a quelques jours un internaute posait la question suivante sur le forum (<a href="http://www.developpez.net/forums/d694077/bases-donnees/ms-sql-server/developpement/creation-tables-p-contraintes/#post4052842">Discussion sur le forum</a>) </p>
<p><em>Voilà, je débute en SQL et il m&rsquo;est demandé de créer une base sous SQL server.<br />
Je voudrais faire la chose suivante:<br />
Créer une table avec un champ &lsquo;nom&rsquo; pour lequel je n&rsquo;autorise que certains caractères, à savoir:<br />
les lettres minuscules et majuscules<br />
le caractère espace<br />
le caractere &lsquo;<br />
J&rsquo;interdirais donc tout le reste.</em><br />
</font></p>
<p><font size="2">Un membre du forum a répondu à cette problématique par une fonction utilisateur SQL (UDF)<br />
(Merci à <em><strong>Elsuket</strong></em> pour son code)<br />
</font><br />
<strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE FUNCTION uFn_VerifieNom (@chaineAVerifier VARCHAR(20)) &nbsp;<br />
RETURNS BIT AS &nbsp;<br />
BEGIN &nbsp;<br />
&nbsp;DECLARE @listeCarateresAutorises VARCHAR(128) &nbsp;<br />
&nbsp;SET @listeCarateresAutorises = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ''' &nbsp;<br />
&nbsp;DECLARE @indice TINYINT, @ok BIT &nbsp;<br />
&nbsp;SELECT @indice = 1, @ok = 1 &nbsp;<br />
&nbsp;WHILE @indice = LEN(@chaineAVerifier) + 1 &nbsp;<br />
&nbsp;BEGIN &nbsp;<br />
&nbsp; &nbsp; &nbsp;IF PATINDEX('%' + SUBSTRING(@chaineAVerifier, @indice, 1) + '%', @listeCarateresAutorises) = 0 &nbsp;<br />
&nbsp; &nbsp; BEGIN &nbsp;<br />
&nbsp; &nbsp; &nbsp;SET @ok = 0 &nbsp; &nbsp;<br />
&nbsp; &nbsp; END &nbsp;<br />
&nbsp; &nbsp; SET @indice = @indice + 1 &nbsp;<br />
&nbsp;END &nbsp;<br />
&nbsp;RETURN @ok &nbsp;<br />
END</div></div>
<p></strong>
</p>
<p><font size="2">Bien que cette fonction fonctionne très bien, on comprend bien que les fonctions de chaînes proposés par TSQL ne permettent pas de manière aisée de traiter ce problème qui est vérifier si un nom correspond bien à &laquo;&nbsp;un modèle&nbsp;&raquo; défini. On peut également s&rsquo;interroger sur les performances d&rsquo;une telle fonction.<br />
Une autre approche consiste à utiliser les expressions régulières mais SQL Server ne possède pas de support intrinsèque pour celles-ci. Il faut donc passer par la construction d’une UDF CLR. (Fonction réalisée avec C#)<br />
</font></p>
<p>
<strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">using System; &nbsp;<br />
using System.Data; &nbsp;<br />
using System.Data.SqlClient; &nbsp;<br />
using System.Data.SqlTypes; &nbsp;<br />
using Microsoft.SqlServer.Server; &nbsp;<br />
using System.Text.RegularExpressions; &nbsp;<br />
&nbsp;<br />
public partial class UserDefinedFunctions &nbsp;<br />
{ &nbsp;<br />
&nbsp; &nbsp; static readonly string nameRegex = &quot;^[a-zA-Z\'\\s]*$&quot;; &nbsp;<br />
&nbsp;<br />
&nbsp; &nbsp; [Microsoft.SqlServer.Server.SqlFunction] &nbsp;<br />
&nbsp; &nbsp; public static SqlBoolean VerifName(SqlString name) &nbsp;<br />
&nbsp; &nbsp; { &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Regex exp = new Regex(nameRegex); &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return exp.IsMatch(name.Value); &nbsp;<br />
&nbsp; &nbsp; } &nbsp;<br />
};</div></div>
<p></strong>
</p>
<p><font size="2">Une première constatation est que la vérification de la chaîne de caractère par une expression régulière est beaucoup plus simple à écrire et que la création de notre fonction à proprement dite n’est pas complexe au niveau syntaxe du code. </p>
<p>Une autre question se pose également. Si la création de l&rsquo;UDF CLR n&rsquo;est pas complexe en soit, est-elle plus performante que l&rsquo;UDF SQL ? Pour y répondre, nous allons tester ces 2 fonctions et comparer leurs temps de traitement avec un jeu de données important.<br />
</font></p>
<p>
<strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE test_nom &nbsp;<br />
( &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;id INT NOT NULL IDENTITY(1,1) PRIMARY KEY, &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nom VARCHAR(255) NOT NULL <br />
) &nbsp;<br />
GO <br />
&nbsp;<br />
DECLARE @i INT &nbsp;<br />
SET @i=0 &nbsp;<br />
WHILE (@i &lt; 110000) &nbsp;<br />
BEGIN &nbsp;<br />
&nbsp; &nbsp;INSERT INTO test_nom (nom) &nbsp;<br />
&nbsp; &nbsp; &nbsp;SELECT SUBSTRING( &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'abcdefghijklmnopqrstuvwyz01234567890zywvutsr'' ' &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;, convert(smallint, 1+ rand() * 35) &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;, convert(smallint, 2+ rand() * 10)) &nbsp;<br />
&nbsp; &nbsp; SET @i = @i + 1 &nbsp;<br />
END &nbsp;<br />
GO</div></div>
<p></strong></p>
<p>On réalise ensuite nos tests avec les 2 UDF : </p>
<p><strong></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SET STATISTICS TIME ON &nbsp;<br />
&nbsp;<br />
-- Test avec UDF CLR <br />
SELECT id,nom,dbo.VerifName(nom) AS verif_pattern &nbsp;<br />
FROM test_nom &nbsp;<br />
&nbsp;<br />
-- Test avec UDF SQL <br />
SELECT id,nom,uFn_VerifieNom(nom) AS verif_pattern &nbsp;<br />
FROM test_nom <br />
&nbsp;<br />
SET STATISTICS TIME OFF</div></div>
<p></strong>
</p>
<p><font size="2">On vérifie nos résultats :</font><br />
<strong><br />
(110000 row(s) affected)  </p>
<p>SQL Server Execution Times:<br />
   CPU time = 2829 ms,  elapsed time = 8985 ms.  </p>
<p>(110000 row(s) affected)  </p>
<p>SQL Server Execution Times:<br />
   CPU time = 54671 ms,  elapsed time = 66781 ms</strong>
</p>
<p><font size="2">Force est de constater que l’UDF CLR a traité beaucoup plus rapidement notre jeu de données en prenant beaucoup moins de ressources CPU !!!<br />
Dans le cas de notre test l’utilisation d’une UDF CLR est plus donc adaptée pour traiter un volume de données important.<br />
</font></p>
<p>David BARBARIN (Mikedavem)<br />
Elève ingénieur CNAM Lyon </p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
