<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="https://blog.datafly.pro/feed/rss2/xslt" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Datafly.pro</title>
    <link>https://blog.datafly.pro/</link>
    <atom:link href="http://blog.datafly.pro/feed/rss2" rel="self" type="application/rss+xml" />
    <description></description>
    <language>fr</language>
    <pubDate>Thu, 06 Jun 2024 09:16:56 +0100</pubDate>
    <copyright></copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>Dotclear</generator>
          <item>
        <title>Datafrogs juin 2024 : ménage de printemps</title>
        <link>https://blog.datafly.pro/post/datafrogs-202406</link>
        <guid isPermaLink="false">urn:md5:d2676c8e971af378c519017f17ec628f</guid>
        <pubDate>Thu, 06 Jun 2024 09:48:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;Pour cette session des Datafrogs, le 1er juin, le sujet de notre présentation était &quot;Ménage de printemps&quot;.&lt;/p&gt;

&lt;p&gt;Il y a sûrement plein de choses qui ne servent plus à rien dans vos instances SQL Server, ce qui crée des trous de sécurité et augmente inutilement la consommation de ressources :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Combien de login avez vous qui ne servent plus à rien ?&lt;img alt=&quot;&quot; class=&quot;media&quot; height=&quot;153&quot; src=&quot;https://blog.datafly.pro/public/images/mickey.gif&quot; style=&quot;float: right; margin: 0px 0px 1em 1em;&quot; width=&quot;200&quot; /&gt;&lt;/li&gt;
	&lt;li&gt;Combien d'utilisateurs SQL sont orphelins dans mes bases ?&lt;/li&gt;
	&lt;li&gt;Combien de bases ne sont plus accédées ?&lt;/li&gt;
	&lt;li&gt;Combien de fichiers de données ou de groupes de fichiers sont vides ?&lt;/li&gt;
	&lt;li&gt;Combien de table ne sont plus accédés ?&lt;/li&gt;
	&lt;li&gt;Combien d'index ne sont plus utilisés ?&lt;/li&gt;
	&lt;li&gt;Combien d'index sont redondants ou inclus ?&lt;/li&gt;
	&lt;li&gt;Combien de statistiques sont redondantes ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous verrez que ce n'est pas si simple que cela à trouver et nettoyer.&lt;/p&gt;

&lt;p&gt;Les diapositives sont &lt;strong&gt;&lt;a href=&quot;https://blog.datafly.pro/public/Documents/datafrogs-menage-de-printemps.pdf&quot;&gt;ici&lt;/a&gt;&lt;/strong&gt;, et les scripts (une partie) &lt;strong&gt;&lt;a href=&quot;https://blog.datafly.pro/public/Documents/datafrogs_menage-de-printemps.zip&quot;&gt;là&lt;/a&gt;&lt;/strong&gt;. La vidéo suivra.&lt;/p&gt;

&lt;p&gt;Bon ménage...&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Retrouvez la version d'origine</title>
        <link>https://blog.datafly.pro/post/Retrouvez-la-version-d-origine</link>
        <guid isPermaLink="false">urn:md5:c06b57653c61fb525aaf928ae0ca6b43</guid>
        <pubDate>Thu, 18 Apr 2024 23:23:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;Savez-vous que les fichiers de données ou de sauvegarde de SQL Server embarquent l'information sur la version d'origine qui a servi à les créer ?&lt;/p&gt;

&lt;p&gt;Dans pas mal de cas, il peut être utile de savoir de quelle version provient un fichier de données ou de sauvegarde, voire connaître pour une base de données existante dans quelle version elle a été créée au départ.&lt;/p&gt;

&lt;p&gt;Voici comment obtenir cette information...&lt;/p&gt;          &lt;p&gt;Un numéro de version interne est enregistré dans le fichier (mdf ou bak), voici la liste :&lt;/p&gt;

&lt;table border=&quot;1&quot; style=&quot;width: 100%&quot;&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;td style=&quot;background-color: #ffff99;&quot;&gt;Appellation commerciale&lt;/td&gt;
			&lt;td style=&quot;width: 260.82px; background-color: #ffff99;&quot;&gt;N° version&lt;/td&gt;
			&lt;td style=&quot;width: 1197.63px; background-color: #ffff99;&quot;&gt;N° interne&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style=&quot;width: 274.214px;&quot;&gt;2000&lt;/td&gt;
			&lt;td&gt;80 / 8.0&lt;/td&gt;
			&lt;td&gt;539&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2005&lt;/td&gt;
			&lt;td&gt;90 / 9.0&lt;/td&gt;
			&lt;td&gt;611,612&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2008&lt;/td&gt;
			&lt;td&gt;100 / 10.0&lt;/td&gt;
			&lt;td&gt;655&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2008R2&lt;/td&gt;
			&lt;td&gt;100 / 10.5&lt;/td&gt;
			&lt;td&gt;661&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2012&lt;/td&gt;
			&lt;td&gt;110 / 11.0&lt;/td&gt;
			&lt;td&gt;706&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2014&lt;/td&gt;
			&lt;td&gt;120 / 12.0&lt;/td&gt;
			&lt;td&gt;782&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2016&lt;/td&gt;
			&lt;td&gt;130 / 13.0&lt;/td&gt;
			&lt;td&gt;852&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2017&lt;/td&gt;
			&lt;td&gt;140 / 14.0&lt;/td&gt;
			&lt;td&gt;869&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2019&lt;/td&gt;
			&lt;td&gt;150 / 15.0&lt;/td&gt;
			&lt;td&gt;904&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2022&lt;/td&gt;
			&lt;td&gt;160 / 16.0&lt;/td&gt;
			&lt;td&gt;957&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Voici maintenant le moyen d'extraire l'information, reportez-vous au tableau pour trouver la version correspondante...&lt;/p&gt;

&lt;h2&gt;Depuis une sauvegarde&lt;/h2&gt;

&lt;p&gt;Pour obtenir l'information depuis un fichier de sauvegarde .BAK, lancez la commande TSQL suivante et relevez la valeur dans la colonne DatabaseVersion :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;
RESTORE HEADERONLY FROM DISK = 'x:\path\file.bak'  -- remplacez par votre fichier bak&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;A partir d'un fichier de données&lt;/h2&gt;

&lt;p&gt;Si vous ne voulez pas attacher la base de données (et potentiellement la migrer vers une version ultérieure), il faut aller chercher l'information en hexadécimal dans le fichier.&lt;/p&gt;

&lt;p&gt;Heureusement il y a plus simple, avec la procédure stockée spDBVersion que vous trouverez &lt;a href=&quot;http://scripts.mssql.fr/knowledge-base/identifier-la-version-sql-server-dun-fichier-mdf/&quot;&gt;ici&lt;/a&gt;. Elle n'est pas de moi et provient d'un forum msdn.&lt;/p&gt;

&lt;h2&gt;Dans une base en ligne&lt;/h2&gt;

&lt;p&gt;Pour obtenir l'information de la version de création depuis une base de données existante et en ligne, utilisez la commande suivante et relevez la valeur dans la ligne dbi_createversion :&amp;nbsp;&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;
DBCC DBINFO(nom_de_la_base) WITH TABLERESULTS&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bonne exploration archéologique dans les versions de SQL Server... Comme cela m'arrive souvent, vous constaterez peut-être que les bases de données de certains progiciels dits &quot;modernes&quot; ont été créées à l'origine sous SQL Server 2000 il y a 20 ans...&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Nouveau SSMS 20.0</title>
        <link>https://blog.datafly.pro/post/2024/03/22/Nouveau-SSMS-20.0</link>
        <guid isPermaLink="false">urn:md5:24f79025d7b2b44c440c13769f626bbb</guid>
        <pubDate>Fri, 22 Mar 2024 14:00:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; height=&quot;141&quot; src=&quot;https://blog.datafly.pro/public/screenshots/.SSMS20_m.png&quot; style=&quot;float: right; margin: 0px 0px 1em 1em;&quot; width=&quot;271&quot; /&gt;Le nouveau SSMS (SQL Server Management Studio) version 20 est arrivé.&lt;/p&gt;

&lt;p&gt;Pas encore visible sur le site français, mais déjà téléchargeable (et en français si souhaité) sur le site US : &lt;a href=&quot;https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16&quot;&gt;https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A noter :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Cette version 20 ne met pas à jour les versions précédentes (19.x et antérieures) mais s'installe en plus !&lt;/li&gt;
	&lt;li&gt;Vous pouvez récupérer votre configuration depuis les versions 19.x ou 18.x mais pas les précédentes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A première vue, pas de changement majeur de l'interface, mais attention aux paramètres de sécurité de connexion (chiffrement, trust server certificate), maintenant configurables à la connexion.&lt;/p&gt;

&lt;p&gt;Vous pouvez visiter les release notes à partir de la page citée plus haut.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>SSMSInfoReports : nouvelle release v9.2</title>
        <link>https://blog.datafly.pro/post/2024/03/19/SSMSInfoReports-%3A-nouvelle-release-v9.2</link>
        <guid isPermaLink="false">urn:md5:b8c02c5a91fad3be7117f99de0a81511</guid>
        <pubDate>Tue, 19 Mar 2024 16:32:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; height=&quot;85&quot; src=&quot;https://blog.datafly.pro/public/logos/github.png&quot; style=&quot;float: right; margin: 0px 0px 1em 1em;&quot; width=&quot;85&quot; /&gt;Encore une nouvelle version de mes rapports custom pour SQL Server Management Studio, la 9.2 !&lt;br /&gt;
Avec dans cette release des corrections de bugs, des améliorations, et un nouveau rapport qui interroge le Query Store.&lt;br /&gt;
Il y a maintenant 18 rapports !&lt;br /&gt;
Pour télécharger les rapports, c'est sur github : &lt;a href=&quot;https://github.com/datafly/SSMSInfoReports&quot;&gt;https://github.com/datafly/SSMSInfoReports&lt;/a&gt;&lt;br /&gt;
J'avais aussi fait il y a quelque temps une vidéo qui explique comment les installer et les utiliser : &lt;a href=&quot;https://www.youtube.com/watch?v=rIY4QGWvvzQ&quot;&gt;https://www.youtube.com/watch?v=rIY4QGWvvzQ&lt;/a&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Tracer l'activité des développeurs sur la production</title>
        <link>https://blog.datafly.pro/post/2024/02/12/Tracer-developpeurs</link>
        <guid isPermaLink="false">urn:md5:b2446549a7f0e349b0676a068db95bef</guid>
        <pubDate>Mon, 12 Feb 2024 11:26:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/images/.loupe_s.jpg&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; /&gt;Hélas, on a laissé jouer les développeurs sur la base de production !&lt;/p&gt;

&lt;p&gt;Question posée : par quel moyen surveiller leurs actions ?&lt;/p&gt;

&lt;p&gt;Dans cet article, on utilise la fonction d'audit de SQL Server pour capturer toutes leurs requêtes.&lt;/p&gt;          &lt;h2&gt;Comment fonctionne l'audit de SQL Server ?&lt;/h2&gt;

&lt;p&gt;L'audit dans SQL Server permet d'assurer le suivi des actions effectuées sur les bases de données. D'une manière générale, cela permet aux administrateurs de surveiller et d'enregistrer une série d'activités et d'événements du système.&lt;/p&gt;

&lt;p&gt;SQL Server propose deux niveaux d'audit :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Audit au niveau du serveur : Suivi des actions au niveau du serveur, comme les changements de configuration ou les tentatives de connexion.&lt;/li&gt;
	&lt;li&gt;Audit au niveau de la base de données : Surveillance des actions spécifiques à une base de données, telles que les modifications de schéma ou l'accès aux données : select, insert, update, delete, etc..&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour configurer l'audit dans SQL Server, vous devez d'abord :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Configurer l'audit avec la commande CREATE SERVER AUDIT, en spécifiant la destination (généralement un fichier, mais il est possible d'envoyer l'audit vers l'event log windows applications ou sécurité). Dans le cas d'une destination fichier, vous pouvez préciser ses caractéristiques : taille, nombre, rotation.&lt;/li&gt;
	&lt;li&gt;Créer une ou plusieurs spécifications d'audit : Définissez ce que vous voulez auditer, au niveau du serveur ou de la base de données, en précisant vers quel audit serveur (créé à l'étape précédente) doivent être envoyées les données.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une fois l'audit configuré, vous pouvez activer ou désactiver à volonté l'audit ou une spécification d'audit : vous avez la flexibilité de démarrer ou d'arrêter l'audit selon vos besoins.&lt;/p&gt;

&lt;p&gt;Pour lire les données d'audit, vous pouvez passer par SQL Server Management Studio, ou lire le fichier avec la fonction SQL fn_get_audit_file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attention &lt;/strong&gt;: l'audit peut avoir un impact sur les performances du serveur, surtout s'il est configuré pour auditer un grand nombre d'événements. Limitez l'audit aux actions et aux événements les plus critiques.&lt;/p&gt;

&lt;h2&gt;Exemple&lt;/h2&gt;

&lt;p&gt;Voici un exemple de configuration à adapter à votre cas de figure : mes développeurs sont membre d'un rôle de bases de données 'Developpers_role', il va donc être plus facile de les tracer.&lt;/p&gt;

&lt;p&gt;Je configure d'abord l'audit, vers une destination de fichiers dans le répertoire log de SQL Server, avec 5 fichiers de 100 MB en rotation.&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;USE master;
GO
DECLARE @errorlogpath NVARCHAR(1000)
      , @sql NVARCHAR(MAX);
SELECT @errorlogpath = LEFT(path, LEN(path) - 1)
FROM sys.dm_os_server_diagnostics_log_configurations;
-- Create server audit
SET @sql
    = N'CREATE SERVER AUDIT [Developpers_Audit]
TO FILE
(    FILEPATH = ''' + @errorlogpath
      + N'''
    ,MAXSIZE = 100 MB
    ,MAX_ROLLOVER_FILES = 5
    ,RESERVE_DISK_SPACE = OFF
) WITH (QUEUE_DELAY = 1000, ON_FAILURE = CONTINUE);';
EXEC (@sql);
-- Enable the server audit.  
ALTER SERVER AUDIT Developpers_Audit   
WITH (STATE = ON) ;  
GO  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Je vais maintenant configurer la spécification d'audit dans la base de données à surveiller : je capture les SELECT, UPDATE, INSERT, DELETE et EXECUTE sur tous les objets du schéma dbo, uniquement pour les développeurs. Facultativement, je peux aussi capturer les CREATE, ALTER ou DROP de tous les utilisateurs.&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- Target database
USE AdventureWorks2019;  
GO  
-- Create the database audit specification.  
CREATE DATABASE AUDIT SPECIFICATION DB_Developpers_Audit  
FOR SERVER AUDIT Developpers_Audit  
-- actions filtrées sur les développeurs
ADD (SELECT , UPDATE, INSERT , DELETE, EXECUTE
     ON Schema::dbo BY Developpers_role )
-- si nécessaire pour tous les create/alter/drop
-- , ADD  (SCHEMA_OBJECT_CHANGE_GROUP)  
WITH (STATE = ON) ;  
GO &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Et maintenant, voici comment lire mon fichier d'audit en SQL (je peux bien sûr envoyer cela vers une table...)&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- Read audit file
SELECT event_time
     , action_id
     , server_principal_name
     , database_principal_name
     , database_name
     , object_name
     , statement
     , duration_milliseconds
     , response_rows
     , affected_rows
FROM fn_get_audit_file('Developpers_audit*.sqlaudit', DEFAULT, DEFAULT)
WHERE action_id IN ( 'SL', 'UP', 'DL', 'EX','CR','AL','DR');&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bon audit, et n'oubliez pas de gronder les développeurs pour leurs requêtes gourmandes sur la production...&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Comment utiliser les rapports SSMSInfoReports</title>
        <link>https://blog.datafly.pro/post/2023/12/28/Comment-utiliser-les-rapports-SSMSInfoReports-video</link>
        <guid isPermaLink="false">urn:md5:6f648445eac15c651f5cd38fdf26f8ed</guid>
        <pubDate>Thu, 28 Dec 2023 11:34:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;Pour comprendre à quoi servent mes rapports custom pour SSMS (SSMSInfoReports), comment les installer et les utiliser : la vidéo.&lt;/p&gt;

&lt;p&gt;&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;305&quot; src=&quot;https://www.youtube-nocookie.com/embed/rIY4QGWvvzQ&quot; width=&quot;500&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>SSMSInfoReports : nouvelle release v9</title>
        <link>https://blog.datafly.pro/post/2023/10/31/SSMSInfoReports-%3A-nouvelle-release-v9</link>
        <guid isPermaLink="false">urn:md5:fb9fccba4aa72a746c8933e5b3e56923</guid>
        <pubDate>Tue, 31 Oct 2023 16:28:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; height=&quot;236&quot; src=&quot;https://blog.datafly.pro/public/screenshots/Inforeports/.Performance_report_m.png&quot; style=&quot;float: right; margin: 0px 0px 1em 1em;&quot; width=&quot;230&quot; /&gt;Une nouvelle release de mes rapports custom pour SQL Server Management Studio, la v9 !&lt;/p&gt;

&lt;p&gt;Enormément d'améliorations partout dans cette release et en prime un rapport supplémentaire sur les locks et deadlocks, ce qui porte maintenant le nombre de rapports à 17.&lt;/p&gt;

&lt;p&gt;Pour ceux qui ne les connaîtraient pas déjà, cet ensemble de rapports chaînés vous permettent d'avoir un aperçu rapide et graphique d'une instance et de ses bases de données, sous tous ses aspects : configurations, erreurs, stockage, backups, jobs, sécurité, performances... Et tout cela sans devoir passer par des dizaines de requêtes ou boîtes de dialogue. Un sacré gain de temps !&lt;/p&gt;

&lt;p&gt;Côté pratique, ils se lancent directement dans SSMS et peuvent être exportés (pdf) voire imprimés... je m'en sers tous les jours ! (pour l'anecdote, j'ai appris que des consultants Microsoft les utilisent et les déploient chez leur clients...)&lt;/p&gt;

&lt;p&gt;Vous pouvez les télécharger sur &lt;a href=&quot;https://github.com/datafly/ssmsinforeports&quot;&gt;https://github.com/datafly/ssmsinforeports&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La v9 est publiée comme il se doit dans la section &quot;Releases&quot;&lt;/p&gt;          &lt;h3&gt;Notes de version :&lt;/h3&gt;

&lt;p&gt;En plus des nombreuses améliorations d'affichage ou de requêtes, voici les principales :&lt;/p&gt;

&lt;h4&gt;Main Server Dashboard&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Liste des volumes/disques améliorée : utilise désormais xp_cmdshell et WMIC plutôt que Ole automation. Affiche maintenant les noms de volume et les points de montage.&lt;/li&gt;
	&lt;li&gt;Amélioration du parsing d’errorlog : ne traite pas les journaux trop grands&lt;/li&gt;
	&lt;li&gt;Amélioration de l’affichage des jobs : affichage des catégories de travail et appel du rapport filtré sur les catégories&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Server Report&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Affichage correct de la version pour SQL Server 2022&lt;/li&gt;
	&lt;li&gt;Affichage des protocoles et ports (si la version le permet)&lt;/li&gt;
	&lt;li&gt;Affichage de l’Instant File Initialization (si la version le permet)&lt;/li&gt;
	&lt;li&gt;Affichage de Lock Pages In Memory&lt;/li&gt;
	&lt;li&gt;Intégrité : affichage des « suspect pages » et des memory dumps&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;All Databases Report&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Refonte complète du tableau des backups&lt;/li&gt;
	&lt;li&gt;Nouvelles options de tri&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Database Report&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Affichage des database scoped configurations (si existantes)&lt;/li&gt;
	&lt;li&gt;Amélioration de l’affichage des fichiers&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Index Report&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Affichage des missing indexes pour les tables sélectionnées (lorsqu’il y en a)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Performance Report&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Affichage des bases avec Query Store activé&lt;/li&gt;
	&lt;li&gt;N’inclut plus les graphiques de ressources par base (long à afficher), qui sont maintenant reportées vers un rapport à part appelé à partir d’un bouton.&lt;/li&gt;
	&lt;li&gt;Bouton d’appel du nouveau rapport « Lock-Deadlocks » (si la version le permet)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Nouveau rapport « Locks-Deadlocks »&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Affichage détaillé des dernières attentes de verrous et derniers deadlocks à partir du system_health&lt;/li&gt;
	&lt;li&gt;Ce rapport n’est pas compatible avec SQL Server 2008/R2.&lt;/li&gt;
&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Utiliser les indicateurs de requête, la présentation</title>
        <link>https://blog.datafly.pro/post/2023/10/30/Utiliser-les-indicateurs-de-requ%C3%AAte-la-pr%C3%A9sentation</link>
        <guid isPermaLink="false">urn:md5:aa1c0d7d60da16c772b3cd9a9b722f25</guid>
        <pubDate>Mon, 30 Oct 2023 11:42:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;Téléchargez la présentation de la conférence Datafrogs &quot;utiliser les indicateurs de requête (Query hints)&quot;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.datafly.pro/public/Documents/Datafrogs_-_Query_Hints.pdf&quot;&gt;https://blog.datafly.pro/public/Documents/Datafrogs_-_Query_Hints.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La vidéo de la présentation est aussi en ligne (il manque quelques minutes d'image à la fin) :&lt;/p&gt;

&lt;p&gt;&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;305&quot; src=&quot;https://www.youtube-nocookie.com/embed/gBn66jbZhW4&quot; width=&quot;500&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Conférence Datafrogs 14 octobre 2023</title>
        <link>https://blog.datafly.pro/post/2023/10/13/Conf%C3%A9rence-Datafrogs-octobre-2023</link>
        <guid isPermaLink="false">urn:md5:0c1beba1c6dfdcbc2be563afaa6a9c62</guid>
        <pubDate>Fri, 13 Oct 2023 08:59:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; height=&quot;219&quot; src=&quot;https://blog.datafly.pro/public/Illustrations_articles/.1697094252316_m.jpg&quot; style=&quot;float: right; margin: 0px 0px 1em 1em;&quot; width=&quot;198&quot; /&gt;Samedi 14 octobre à 14h45, j'aurai le plaisir de présenter une sessions sur les &quot;Query Hints&quot; ou &quot;Indicateurs de requête&quot;.&lt;/p&gt;

&lt;p&gt;L’optimiseur de SQL Server décide du meilleur plan d’exécution et il s’en débrouille plutôt bien. Mais comment faire pour lui forcer la main si on est sûr de pouvoir faire mieux que lui ?&lt;/p&gt;

&lt;p&gt;Dans cette session, je vous montrerai les différents indicateurs de requêtes et leurs effets.&lt;/p&gt;

&lt;p&gt;Le lien (linkedin) vers l'évênement : &lt;span class=&quot;break-words
      &quot;&gt;&lt;span&gt;&lt;span dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://lnkd.in/gZZRT7zK&quot;&gt;https://lnkd.in/gZZRT7zK&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Best practices N° 4 - configuration de l'instance SQL</title>
        <link>https://blog.datafly.pro/post/2024/03/22/Best-practices-N%C2%B0-4-configuration-de-l-instance-SQL</link>
        <guid isPermaLink="false">urn:md5:07e83620907b4910109e30441907117f</guid>
        <pubDate>Mon, 25 Sep 2023 14:23:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/images/.best-practice_t.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; /&gt;Etape importante de configuration post-installation, à minima retoucher les paramètres de l'instance :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Mémoire maximale&lt;/li&gt;
	&lt;li&gt;Compression et checksum des sauvegardes&lt;/li&gt;
	&lt;li&gt;Parallélisme&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voyons comment faire cela avec quelques scripts SQL&lt;/p&gt;          &lt;p&gt;Concernant la mémoire maximale, il est utile de configurer ce paramètre pour éviter que SQL Server lutte avec l'OS pour sa consommation de mémoire. S'il s'agit d'un serveur dédié à SQL Server, la règle suivante peut s'appliquer :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Réserver 1 Go pour l'OS&lt;/li&gt;
	&lt;li&gt;Y ajouter 1 Go pour chaque 4 Go de RAM installée entre 4 et 16 Go&lt;/li&gt;
	&lt;li&gt;Y ajouter 1 Go pour chaque 8 Go de RAM installée à partir de 16 Go&lt;/li&gt;
	&lt;li&gt;Configurer max server memory avec la mémoire qui reste.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le script suivant fait le calcul et applique la modification :&lt;br type=&quot;_moz&quot; /&gt;
 &lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- configurer max server memory
DECLARE @memOsBase DECIMAL(9, 2)
      , @memOs4_16GB DECIMAL(9, 2)
      , @memOsOver_16GB DECIMAL(9, 2)
      , @memOsTot DECIMAL(9, 2)
      , @memForSql DECIMAL(9, 2)
      , @sql NVARCHAR(MAX)
      , @memInMachine DECIMAL(9, 2);
-- Get current machine memory configuration
SELECT @memInMachine = physical_memory_kb / (1024 * 1024.)
FROM sys.dm_os_sys_info;
SET @memOsBase = 1;
SET @memOs4_16GB = CASE
                       WHEN @memInMachine &amp;lt;= 4 THEN
                           0
                       WHEN @memInMachine &amp;gt; 4
                            AND @memInMachine &amp;lt;= 16 THEN
(@memInMachine - 4) / 4
                       WHEN @memInMachine &amp;gt;= 16 THEN
                           3
                   END;
SET @memOsOver_16GB = CASE
                          WHEN @memInMachine &amp;lt;= 16 THEN
                              0
                          ELSE
(@memInMachine - 16) / 8
                      END;
SET @memOsTot = @memOsBase + @memOs4_16GB + @memOsOver_16GB;
SET @memForSql = @memInMachine - @memOsTot;

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
SET @sql
    = N'EXEC sp_configure ''max server memory'',' + CAST(CAST(@memForSql * 1024 AS INT) AS VARCHAR(10))
      + N'; RECONFIGURE;';
PRINT @sql;
EXEC (@sql);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bien sûr, il faut adapter cette configuration si d'autres processus tournent sur le serveur.&lt;/p&gt;

&lt;p&gt;N'oublions pas de configurer la compression et le checksum des sauvegardes, qui améliorent leur performance, leur volumétrie et leur sécurité :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;EXEC sys.sp_configure N'backup compression default', N'1'
GO
EXEC sys.sp_configure N'backup checksum default', N'1'
GO
RECONFIGURE WITH OVERRIDE
GO&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Concernant le parallélisme, c'est plus délicat : cela dépend du type de travail exécuté sur notre serveur SQL. Une règle de départ pourrait être :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Positionner &quot;max degree of parallelism&quot; (nombre de processeurs pour le parallélisme) à la moitié des CPU&lt;/li&gt;
	&lt;li&gt;Augmenter &quot;cost threshold for parallelism&quot; (seuil de coût) à 30&lt;/li&gt;
	&lt;li&gt;On peut aussi activer &quot;Optimize for adhoc workload&quot; (optimiser pour les charges de travail adhoc permet d'éviter de saturer le cache de plans avec des requêtes qui ne sont exécutées qu'une seule fois)&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
DECLARE @cpu_count INT, @sql NVARCHAR(MAX);
-- Get current machine cpu configuration
SELECT @cpu_count=cpu_count
FROM sys.dm_os_sys_info;
SET @sql=N'EXEC sys.sp_configure ''max degree of parallelism'','
         +CAST(CASE WHEN @cpu_count&amp;lt;=3 THEN 2 ELSE FLOOR(@cpu_count / 2)END AS VARCHAR(3))+N'; RECONFIGURE;'+CHAR(10);
SET @sql=@sql+N'EXEC sys.sp_configure ''cost threshold for parallelism'',30; RECONFIGURE;'+CHAR(10);
SET @sql=@sql+N'EXEC sys.sp_configure ''optimize for ad hoc workloads'',1; RECONFIGURE;';
PRINT @sql
EXEC (@sql)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Best practices N° 3 : configurer les historiques</title>
        <link>https://blog.datafly.pro/post/Best-practices-3-configurer-les-historiques</link>
        <guid isPermaLink="false">urn:md5:07801e80856f424e641111d611064bce</guid>
        <pubDate>Sun, 24 Sep 2023 11:13:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/images/.best-practice_t.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; /&gt;SQL Server ne conserve par défaut que 6 archives du journal d'erreur, et l'historique des travaux de l'agent SQL est bien trop court.&lt;/p&gt;

&lt;p&gt;Nous allons remédier à cela avec quelques scripts SQL.&lt;/p&gt;          &lt;p&gt;Voici encore deux petits scripts :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- Passer le nombre d'archives d'errorlog à 12
DECLARE @Numlogs INT;
DECLARE @RegTable TABLE
(
    Value VARCHAR(128)
  , Data VARCHAR(128)
);
INSERT @RegTable
(
    Value
  , Data
)
EXEC xp_instance_regread N'HKEY_LOCAL_MACHINE'
                       , N'Software\Microsoft\MSSQLServer\MSSQLServer'
                       , N'NumErrorLogs';
SELECT @Numlogs = CAST(Data AS INT)
FROM @RegTable;
IF @Numlogs &amp;lt; 12
   OR @Numlogs IS NULL
BEGIN
    EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE'
                            , N'Software\Microsoft\MSSQLServer\MSSQLServer'
                            , N'NumErrorLogs'
                            , REG_DWORD
                            , 12;
END;&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- augmenter la taille de l'historique de l'agent
EXEC msdb.dbo.sp_set_sqlagent_properties @jobhistory_max_rows = 100000
                                       , @jobhistory_max_rows_per_job = 10000;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Best practices N° 2 : configurer database mail, les notifications et les alertes</title>
        <link>https://blog.datafly.pro/post/Best-practices-2-configurer-database-mail</link>
        <guid isPermaLink="false">urn:md5:82a956374471d7ece6972fc8159428f7</guid>
        <pubDate>Sat, 23 Sep 2023 10:35:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/images/.best-practice_t.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; /&gt;Etre notifié par mail en cas de problème, c'est indispensable !&lt;/p&gt;

&lt;p&gt;Ici, nous configurons Database Mail, étape importante des best practices après l'installation d'une instance SQL Server.&lt;/p&gt;

&lt;p&gt;Tant qu'à faire, simplifions l'opération en configurant avec un script SQL.&lt;/p&gt;          &lt;p&gt;Activer et configurer Database Mail : modifiez les variables en début de script selon votre environnement et exécutez le script :&lt;br /&gt;
 &lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;DECLARE @server_email_address NVARCHAR(128) = N'myserver.mydomain.com' -- notifications : sender email address
      , @mailserver_name NVARCHAR(128) = N'192.168.0.1'                -- smtp server name or ip address
      , @smtpport INT = 25                                             -- smtp server port
      , @smtpenable_ssl BIT = 0                                        -- smtp server : enable ssl (0|1)
      , @smtpusername NVARCHAR(128) = NULL                             -- smtp server authentication username
      , @smtppassword NVARCHAR(128) = NULL                             -- smtp server authentication password
      , @display_name NVARCHAR(128) = N'SQL Alerting - ' + CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(128));

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'Database Mail XPs', 1;
RECONFIGURE WITH OVERRIDE;
IF NOT EXISTS
(
    SELECT *
    FROM msdb.dbo.sysmail_profile
    WHERE name = N'AdminDBMail'
)
    EXECUTE msdb.dbo.sysmail_add_profile_sp @profile_name = 'AdminDBMail'
                                          , @description = 'Notification mail profile';
ELSE
    PRINT 'Mail profile already existing, not modified';

IF NOT EXISTS
(
    SELECT *
    FROM msdb.dbo.sysmail_account
    WHERE name = N'SQLAlert'
)
    EXECUTE msdb.dbo.sysmail_add_account_sp @account_name = 'SQLAlert'
                                          , @description = 'SMTP account for SQL Agent Notifications'
                                          , @email_address = @server_email_address
                                          , @display_name = @display_name
                                          , @mailserver_name = @mailserver_name
                                          , @port = @smtpport
                                          , @enable_ssl = @smtpenable_ssl
                                          , @username = @smtpusername
                                          , @password = @smtppassword;
ELSE
    PRINT 'Mail account already existing, not modified';

IF NOT EXISTS
(
    SELECT *
    FROM msdb.dbo.sysmail_profileaccount PA
        JOIN msdb.dbo.sysmail_account A
            ON PA.account_id = A.account_id
        JOIN msdb.dbo.sysmail_profile P
            ON PA.profile_id = P.profile_id
    WHERE A.name = N'SQLAlert'
          AND P.name = 'AdminDBMail'
)
BEGIN
    EXECUTE msdb.dbo.sysmail_add_profileaccount_sp @profile_name = 'AdminDBMail'
                                                 , @account_name = 'SQLAlert'
                                                 , @sequence_number = 1;

    EXEC msdb.dbo.sp_set_sqlagent_properties @email_save_in_sent_folder = 1
                                           , @databasemail_profile = N'AdminDBMail'
                                           , @use_databasemail = 1;
END;
ELSE
    PRINT 'Profile_account already existing, not modified';&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configurons maintenant l'opérateur, activons les notifications sur échec des jobs de maintenance et configurons les alertes indispensables : même principe, modifions les variables de début de script avant de l'exécuter.&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;DECLARE @operator_name NVARCHAR(128) = N'SQLAdmin'                -- operator name
      , @operator_email NVARCHAR(128) = N'myemail@mydomain.com';    -- operator email

IF NOT EXISTS
(
    SELECT *
    FROM msdb.dbo.sysoperators
    WHERE name = @operator_name
)
    EXEC msdb.dbo.sp_add_operator @name = @operator_name
                                , @enabled = 1
                                , @pager_days = 0
                                , @email_address = @operator_email;
ELSE
    PRINT 'Operator already existing, not modified';

-- Configuration des notifications
EXEC msdb.dbo.sp_update_job @job_name=N'DatabaseIntegrityCheck - SYSTEM_DATABASES',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name;
EXEC msdb.dbo.sp_update_job @job_name=N'DatabaseIntegrityCheck - USER_DATABASES',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name;
EXEC msdb.dbo.sp_update_job @job_name=N'IndexOptimize - USER_DATABASES',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name;
EXEC msdb.dbo.sp_update_job @job_name=N'DatabaseBackup - SYSTEM_DATABASES - FULL',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name
EXEC msdb.dbo.sp_update_job @job_name=N'DatabaseBackup - USER_DATABASES - FULL',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name
EXEC msdb.dbo.sp_update_job @job_name=N'DatabaseBackup - USER_DATABASES - DIFF',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name
EXEC msdb.dbo.sp_update_job @job_name=N'DatabaseBackup - USER_DATABASES - LOG',
        @notify_level_email=2,
        @notify_level_page=2,
        @notify_email_operator_name=@operator_name
-- Configuration des alertes
IF NOT EXISTS
(
    SELECT *
    FROM msdb.dbo.sysoperators
    WHERE name = @operator_name
)
    EXEC msdb.dbo.sp_add_operator @name = @operator_name
                                , @enabled = 1
                                , @pager_days = 0
                                , @email_address = @operator_email;
ELSE
    PRINT 'Operator already existing, not modified';

-- Configure alerts
DECLARE @sev INT = 19;
DECLARE @alert_name sysname;
WHILE @sev &amp;lt;= 25
BEGIN
    SET @alert_name = @@SERVERNAME + ' Alert - ' + 'Severity level ' + CAST(@sev AS VARCHAR);
    IF NOT EXISTS (SELECT * FROM msdb.dbo.sysalerts WHERE name = @alert_name)
    BEGIN
        EXEC msdb.dbo.sp_add_alert @name = @alert_name
                                 , @severity = @sev
                                 , @delay_between_responses = 600     --10 minutes
                                 , @include_event_description_in = 1; --Email
        EXEC msdb.dbo.sp_add_notification @alert_name = @alert_name
                                        , @operator_name = @operator_name
                                        , @notification_method = 1;
    END;
    ELSE
        PRINT @alert_name + ' : alert already existing, not modified';
    SET @sev = @sev + 1;
END;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Best practices N° 1 : tâches de maintenance</title>
        <link>https://blog.datafly.pro/post/Best-practices-1-maintenance</link>
        <guid isPermaLink="false">urn:md5:5ef4927f4367ba5413f15fbf1894b495</guid>
        <pubDate>Fri, 22 Sep 2023 09:40:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/images/.best-practice_t.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; /&gt;A l'installation d'une instance SQL Server, il y a au minimum quelques &quot;best practices&quot; à appliquer.&lt;br /&gt;
Cette série d'articles décrit les principales configurations indispensables et les moyens de les mettre en place avec de simples requêtes SQL : tâches de maintenance, alertes, notifications par email, configuration de l'instance, ...&lt;/p&gt;

&lt;p&gt;Nous commençons ici par la configuration des tâches de maintenance.&lt;/p&gt;          &lt;h2&gt;Mettre en place les tâches de maintenance : backup, check d'intégrité, optimisation d'index.&lt;/h2&gt;

&lt;p&gt;Pour cela les scripts du MVP suédois &lt;a href=&quot;https://ola.hallengren.com/&quot;&gt;Ola Hallengren&lt;/a&gt; sont les meilleurs (et bien plus puissants que les plans de maintenance intégrés à Management Studio). Ils sont utilisés et recommandés quasi unanimement par la communauté d’experts et MVP renommés : Jonathan Kehayias (SQLSkills), Brent Ozar (brentozar.com), Paul Randall (SQLSkills), Benjamin Nevarez (SQLSkills), Tibor Karaszi, etc…&lt;/p&gt;

&lt;p&gt;Ils sont régulièrement maintenus par leur auteur depuis janvier 2008 et prennent en charge les versions de SQL Server 2005 à 2022 (non, pas 2000… !)&lt;/p&gt;

&lt;p&gt;Le script crée seulement 4 procédures stockées qui gèrent l’ensemble des tâches de maintenance, avec nombre d’options utiles entièrement documentées.&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;DatabaseBackup : backups de tous types&lt;/li&gt;
	&lt;li&gt;DatabaseIntegrityCheck : intégrité&lt;/li&gt;
	&lt;li&gt;IndexOptimize : index et statistiques&lt;/li&gt;
	&lt;li&gt;CommandExecute : procédure de lancement des commandes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comment faire :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Téléchargez le script SQL sur &lt;a href=&quot;https://ola.hallengren.com/scripts/MaintenanceSolution.sql&quot;&gt;https://ola.hallengren.com/scripts/MaintenanceSolution.sql&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Modifiez les quelques paramètres à votre convenance au début du script :&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;USE [master] -- Specify the database in which the objects will be created.

SET NOCOUNT ON

DECLARE @CreateJobs nvarchar(max)          = 'Y'         -- Specify whether jobs should be created.
DECLARE @BackupDirectory nvarchar(max)     = NULL        -- Specify the backup root directory. If no directory is specified, the default backup directory is used.
DECLARE @CleanupTime int                   = NULL        -- Time in hours, after which backup files are deleted. If no time is specified, then no backup files are deleted.
DECLARE @OutputFileDirectory nvarchar(max) = NULL        -- Specify the output file directory. If no directory is specified, then the SQL Server error log directory is used.
DECLARE @LogToTable nvarchar(max)          = 'Y'         -- Log commands to a table.&lt;/code&gt;&lt;/pre&gt;

&lt;ol&gt;
	&lt;li&gt;Base de données où créer les objets de maintenance : personnellement, je préfère remplacer [master] par [msdb]&lt;/li&gt;
	&lt;li&gt;@CreateJobs : par défaut, des travaux de l'agent SQL Server seront créés et vous n'aurez plus qu'à les planifier&lt;/li&gt;
	&lt;li&gt;@BackupDirectory : si non renseigné, les sauvegardes sont créées dans le dossier de backup par défaut, sinon indiquer le chemin de remplacement&lt;/li&gt;
	&lt;li&gt;@CleanupTime : indiquer en heures la rétention des sauvegardes sur le disque&lt;/li&gt;
	&lt;li&gt;@OutputFileDirectory : si non renseigné, les tâches créeront des rapports (fichiers texte) dans le dossier log par défaut, sinon indiquer le chemin de remplacement&lt;/li&gt;
	&lt;li&gt;@LogToTable : par défaut, toutes les opérations effectuées seront journalisées dans une table nommée CommandLog&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Exécutez le script (en tant qu'administrateur SQL Server, bien sûr).&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Vous n'avez plus qu'à planifier chacun des 11 travaux de maintenance :&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
	&lt;li&gt;DatabaseIntegrityCheck - SYSTEM_DATABASES&lt;/li&gt;
	&lt;li&gt;DatabaseIntegrityCheck - USER_DATABASES&lt;/li&gt;
	&lt;li&gt;IndexOptimize - USER_DATABASES&lt;/li&gt;
	&lt;li&gt;DatabaseBackup - SYSTEM_DATABASES - FULL&lt;/li&gt;
	&lt;li&gt;DatabaseBackup - USER_DATABASES - FULL&lt;/li&gt;
	&lt;li&gt;DatabaseBackup - USER_DATABASES - DIFF&lt;/li&gt;
	&lt;li&gt;DatabaseBackup - USER_DATABASES - LOG&lt;/li&gt;
	&lt;li&gt;CommandLog Cleanup&lt;/li&gt;
	&lt;li&gt;Output File Cleanup&lt;/li&gt;
	&lt;li&gt;sp_delete_backuphistory&lt;/li&gt;
	&lt;li&gt;sp_purge_jobhistory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pourquoi pas planifier tout cela avec des commandes SQL ? Par exemple (modifiez selon votre convenance) :&lt;code class=&quot;language-sql&quot; style=&quot;white-space: pre-wrap;&quot;&gt;-- Integrity Check - SYSTEM_DATABASES : 23:00&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;DECLARE @schedule_id INT
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'DatabaseIntegrityCheck - SYSTEM_DATABASES')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DatabaseIntegrityCheck - SYSTEM_DATABASES', @name=N'DatabaseIntegrityCheck - SYSTEM_DATABASES',
        @enabled=1,
        @freq_type=4, -- Daily
        @freq_interval=1, -- Once
        @freq_subday_type=1, -- at specified time
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20240101,
        @active_end_date=99991231,
        @active_start_time=230000,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT

-- Integrity Check - USER_DATABASES : 23:00
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'DatabaseIntegrityCheck - USER_DATABASES')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DatabaseIntegrityCheck - USER_DATABASES', @name=N'DatabaseIntegrityCheck - USER_DATABASES',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=1,
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20210101,
        @active_end_date=99991231,
        @active_start_time=230500,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT

-- Index Optimize : 00:00
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'IndexOptimize - USER_DATABASES')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'IndexOptimize - USER_DATABASES', @name=N'IndexOptimize - USER_DATABASES',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=1,
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20210101,
        @active_end_date=99991231,
        @active_start_time=000000,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT

-- Backups Full SYSTEM_DATABASES : 01:00
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'DatabaseBackup - SYSTEM_DATABASES - FULL')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DatabaseBackup - SYSTEM_DATABASES - FULL', @name=N'DatabaseBackup - SYSTEM_DATABASES - FULL',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=1,
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20220207,
        @active_end_date=99991231,
        @active_start_time=010000,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT

-- Backups Full USER_DATABASES : 01:00
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'DatabaseBackup - USER_DATABASES - FULL')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DatabaseBackup - USER_DATABASES - FULL', @name=N'DatabaseBackup - USER_DATABASES - FULL',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=1,
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20220207,
        @active_end_date=99991231,
        @active_start_time=010500,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT


-- Backups differential - USER_DATABASES : 12:30
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'DatabaseBackup - USER_DATABASES - DIFF')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DatabaseBackup - USER_DATABASES - DIFF', @name=N'DatabaseBackup - USER_DATABASES - DIFF',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=1,
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20220207,
        @active_end_date=99991231,
        @active_start_time=123000,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT

-- Backups log - USER_DATABASES : hourly between 5:15 and 1:00
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'DatabaseBackup - USER_DATABASES - LOG')
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'DatabaseBackup - USER_DATABASES - LOG', @name=N'DatabaseBackup - USER_DATABASES - LOG',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=8,
        @freq_subday_interval=1,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20220207,
        @active_end_date=99991231,
        @active_start_time=051500,
        @active_end_time=010000, @schedule_id = @schedule_id OUTPUT

-- All Cleanup tasks : Daily 5:30
IF NOT EXISTS (SELECT * FROM msdb..sysschedules WHERE name = N'Maintenance History Cleanup')
BEGIN
EXEC msdb.dbo.sp_add_jobschedule @job_name=N'CommandLog Cleanup', @name=N'Maintenance History Cleanup',
        @enabled=1,
        @freq_type=4,
        @freq_interval=1,
        @freq_subday_type=1,
        @freq_subday_interval=0,
        @freq_relative_interval=0,
        @freq_recurrence_factor=1,
        @active_start_date=20210101,
        @active_end_date=99991231,
        @active_start_time=053000,
        @active_end_time=235959, @schedule_id = @schedule_id OUTPUT
EXEC msdb.dbo.sp_attach_schedule @job_name=N'Output File Cleanup',@schedule_id=@schedule_id
EXEC msdb.dbo.sp_attach_schedule @job_name=N'sp_delete_backuphistory',@schedule_id=@schedule_id
EXEC msdb.dbo.sp_attach_schedule @job_name=N'sp_purge_jobhistory',@schedule_id=@schedule_id
END&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>N'oubliez pas les correctifs</title>
        <link>https://blog.datafly.pro/post/2023/07/08/N-oubliez-pas-les-correctifs</link>
        <guid isPermaLink="false">urn:md5:59a888c637d2b2d3b92c7434440b816e</guid>
        <pubDate>Sat, 08 Jul 2023 17:46:00 +0100</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;On ne le dira jamais assez, il faut installer les correctifs sur vos instances SQL Server.&lt;/p&gt;

&lt;p&gt;Microsoft a enfin mis en ligne &lt;a href=&quot;https://learn.microsoft.com/en-us/troubleshoot/sql/releases/download-and-install-latest-updates&quot;&gt;une page tenue à jour qui recense les correctifs&lt;/a&gt; pour toutes les versions de SQL Server, de la version 6.5 (hé oui !) à la version 2022.&lt;/p&gt;

&lt;p&gt;Mais bien sûr, si vous utilisez SQL Server 2012 (fin du support étendu le 12 juillet 2023, on y est) ou une version encore plus ancienne, envisagez à court terme la mise à jour vers une version encore supportée par Microsoft.&lt;/p&gt;

&lt;p&gt;Pour installer un correctif, pour ma part, j'attends en général une quinzaine de jours avant de l'appliquer, histoire d'éviter des régressions imprévues (il y a même eu des retraits de correctifs en catastrophe dans le passé, quelques jours après leur sortie).&lt;/p&gt;

&lt;p&gt;En ce qui concerne SQL Server 2022 par exemple, le correctif Cumulative Update 4 avait quelques bugs qui pourraient se révéler gênants.&lt;/p&gt;

&lt;p&gt;En voilà un, heureusement corrigé depuis par le Cumulative Update 5 :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- Créons une table avec un  index descendant
DECLARE @T table (i integer NOT NULL INDEX ii (i DESC));
INSERT @T (i) VALUES (1), (2), (3);

-- Cette requête renvoie les données en ordre descendant !
SELECT Ascending = T.i
FROM @T AS T
WHERE T.i IN (1, 2, 3)
ORDER BY T.i ASC; -- Mais nous avions demandé un ordre ascendant

-- Cette requête renvoie les données en ordre ascendant !
SELECT Descending = T.i
FROM @T AS T
WHERE T.i IN (1, 2, 3)
ORDER BY T.i DESC; -- Mais nous avions demandé un ordre descendant

-- CU 4 : L'ordre est incorrect avec un index descendant et un prédicat IN sur cette clé&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Datafrogs Conférence : Recherche Full-Text</title>
        <link>https://blog.datafly.pro/post/2023/03/18/Datafrogs-%3A-Recherche-Full-Text</link>
        <guid isPermaLink="false">urn:md5:7d0d524a9899fefedc29fbb12462e4fb</guid>
        <pubDate>Sat, 18 Mar 2023 18:12:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/logos/.datafrogs_s.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; /&gt;Vous trouverez ici les diapositives et les démonstration de notre session sur la recherche en texte intégral lors de la conférence Datafrogs de ce 18 mars 2023.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.datafly.pro/public/Documents/Microsoft SQL Server Full-Text Search (FTS) DataFrogs 2023-03.pdf&quot; title=&quot;Slides de la présentation&quot;&gt;Slides de la présentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.datafly.pro/public/Documents/Demos FTS Datafrog.zip&quot; title=&quot;Démonstrations&quot;&gt;Démonstrations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;305&quot; src=&quot;https://www.youtube-nocookie.com/embed/Nz6aQCR-Xvo&quot; width=&quot;500&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Les index filtrés</title>
        <link>https://blog.datafly.pro/post/Les-index-filtres</link>
        <guid isPermaLink="false">urn:md5:604129a0257de6989f325ddb40313f2b</guid>
        <pubDate>Thu, 02 Mar 2023 10:27:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;Depuis SQL Server 2008, il est possible de créer des index filtrés : des index nonclustered avec un prédicat WHERE, qui ne vont indexer qu'une partie de la table.&lt;/p&gt;

&lt;p&gt;Bien que peu utilisés (je le constate souvent dans les bases que j'examine), l'utilisation des index filtrés peut nous aider à résoudre certaines problématiques de performances et peuvent réduire le volume de stockage.&lt;/p&gt;

&lt;p&gt;Il faut cependant bien comprendre quelles sont les limites à leur utilisation : dans beaucoup de cas, les index filtrés que j'ai rencontré étaient mal utilisés !&lt;/p&gt;          &lt;p&gt;Un index filtré est un index avec un prédicat de filtre : une cause WHERE ! Une partie des lignes seulement est donc indexée : l'index est &quot;partiel&quot;, sa taille est réduite. Cela permettra d'améliorer les performances de certaines requêtes, consommera moins d'espace de stockage qu'un index &quot;complet&quot;, et cette taille réduite permettra de limiter les coûts de maintenance.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Comment créer un index filtré&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;En ajoutant simplement une clause WHERE lors de la création de l'index, par exemple :&lt;/p&gt;

&lt;p&gt;CREATE NONCLUSTERED INDEX ix$CommandesActives ON IDClient WHERE CommandeActive = 1&lt;/p&gt;

&lt;p&gt;Seuls sont supportés les opérateurs de comparaison simples : =,&amp;lt;,&amp;lt;=,&amp;gt;,&amp;gt;=,&amp;lt;&amp;gt;.&lt;br /&gt;
Vous pouvez assembler plusieurs conditions avec AND, mais vous n'avez pas le droit au OR ou NOT, ni au LIKE ou aux fonctions dans le prédicat de filtre. Et vous ne pouvez pas non plus créer un index filtré sur une colonne calculée ou sur une vue indexée. Le filtre ne peut pas non plus être appliqué à une clé primaire ou une contrainte unique.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chose importante&lt;/strong&gt; : pour qu'un index filtré puisse être créé ou mis à jour, certaines options SET de la connexion doivent être correctement positionnées. C'est le cas par défaut dans SQL Server Management Studio, mais pas forcément dans votre application cliente : si les options requises ne sont pas toutes positionnées correctement, les mises à jour échoueront !&lt;/p&gt;

&lt;pre&gt;
Échec de UPDATE car les options SET suivantes comportent des paramètres incorrects...&lt;/pre&gt;

&lt;ul&gt;
	&lt;li&gt;Doivent être activés : ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER.&lt;/li&gt;
	&lt;li&gt;Doit être désactivé : NUMERIC_ROUNDABORT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Index filtrés et performances&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;L'index filtré est utile pour les requêtes qui effectuent des sélection dans un sous-ensemble de données bien défini (celui du filtre de l'index), surtout si il y a besoin de parcourir l'index en entier (index scan) ou en partie : l'index étant beaucoup plus petit, le parcours nécessite moins de lectures et est donc plus rapide.&lt;/p&gt;

&lt;p&gt;C'est surtout utile lorsqu'une colonne n'a que quelques valeurs pertinentes, inégalement distribuées. Par exemple, ma grosse table des commandes a une colonne &lt;strong&gt;CommandeActive &lt;/strong&gt;: la plus grande partie des commandes de ma table sont déjà livrées et terminées (CommandeActive=0) et je n'ai qu'un faible sous-ensemble de commandes actuellement actives (CommandeActive=1).&lt;/p&gt;

&lt;p&gt;Si j'indexe ma table des commandes avec un index filtré qui filtre sur &lt;strong&gt;WHERE CommandeActive = 1&lt;/strong&gt;, certaines requêtes, celles qui ciblent uniquement des commandes actives (et qui le précisent bien dans le prédicat de recherche) pourront être améliorées. Non, pas toutes les requêtes, dans certains cas un autre index existant (ou un parcours de table) peut être plus efficace, et l'optimiseur choisit !&lt;/p&gt;

&lt;p&gt;Autre avantage de l'index filtré : des statistiques filtrées seront de fait créées, améliorant l'estimation des cardinalités !&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Les limites à l'utilisation d'un index filtré : attention !&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;Tout d'abord, pour qu'un index filtré puisse être choisi par l'optimiseur dans un plan d'exécution, il est indispensable que le prédicat de recherche correspondant au filtre soit exprimé dans la requête SELECT (ou UPDATE ou DELETE). Par exemple :&lt;/p&gt;

&lt;pre&gt;
SELECT ID, ClientID, DateCommande FROM Commande &lt;strong&gt;WHERE CommandeActive = 1&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;Mais il faut savoir que le prédicat de recherche doit utiliser &lt;u&gt;une constante, et surtout pas une variable&lt;/u&gt;. La requête suivante sera incapable d'utiliser l'index filtré :&lt;/p&gt;

&lt;pre&gt;
SELECT ID, ClientID, DateCommande FROM Commande &lt;strong&gt;WHERE CommandeActive = @VarActive&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;Dans ce cas on pourra trouver un avertissement dans le plan d'exécution : &quot;Unmatched Index&quot; (à regarder dans les propriétés du plan d'exécution). Cela signifie qu'un index existe bien, mais il ne peut pas être utilisé pour résourdre la requête. En effet, lorsqu'on utilise une variable dans un prédicat de recherche, l'optimiseur ne connait pas la valeur au moment de la compilation du plan.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;&quot; class=&quot;media&quot; src=&quot;https://blog.datafly.pro/public/screenshots/.unmatched_m.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Il est donc parfois nécessaire de &quot;doubler&quot; l'index filtré par sa version non filtrée pour parer à différents cas de figure !&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Et les NULLS ?&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;L'index filtré peut aussi nous permettre de contourner une problématique absurde propre à SQL Server : lorsqu'on crée un index unique sur une colonne, SQL Server traite le NULL comme une valeur et ne nous permet d'en insérer qu'un seul !&lt;/p&gt;

&lt;p&gt;L'index filtré peut nous permettre de parer à cela, comme dans l'exemple suivant :&lt;/p&gt;

&lt;pre&gt;
CREATE UNIQUE INDEX ux$UniqueNameAllowNulls ON dbo.Persons (UniqueName) WHERE UniqueName IS NOT NULL&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>SQL Server 2022 : Database Ledger</title>
        <link>https://blog.datafly.pro/post/2023/02/27/SQL-Server-2022-Database-Ledger</link>
        <guid isPermaLink="false">urn:md5:970383583b47568f6224b80a8cccdd05</guid>
        <pubDate>Mon, 27 Feb 2023 09:16:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;Un petit webcast sur Database Ledger, nouvelle fonctionnalité de sécurité de SQL Server 2022. Basé sur la technologie de la blockchain, cela permet d'assurer la traçabilité des modifications et de garantir l'intégrité des données, pour des bases de données à haute sécurité. Dans la démo, j'ai joué au vilain pirate pour altérer ma base de données...&lt;/p&gt;

&lt;p&gt;&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;305&quot; src=&quot;https://www.youtube-nocookie.com/embed/OvJzZnqSWl4&quot; width=&quot;500&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>SQL Server 2022 : bug Filestream</title>
        <link>https://blog.datafly.pro/post/2023/02/23/SQL-Server-2022-%3A-bug-Filestream</link>
        <guid isPermaLink="false">urn:md5:f1e1e8dd4c9ec8cb054d308d73e5891c</guid>
        <pubDate>Thu, 23 Feb 2023 09:20:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;En construisant mes démos, je suis tombé sur ce bug : lorsqu'on tente d'ajouter un filegroup filestream à une base de données, on obtient le message d'erreur suivant.&lt;/p&gt;

&lt;pre&gt;
Msg 35221, Level 16, State 1, Line 2

Could not process the operation. Always On Availability Groups replica manager is disabled on this instance of SQL Server. Enable Always On Availability Groups, by using the SQL Server Configuration Manager. Then, restart the SQL Server service, and retry the currently operation. For information about how to enable and disable Always On Availability Groups, see SQL Server Books Online.&lt;/pre&gt;

&lt;p&gt;Cela n'a bien entendu aucun rapport avec Always On...&lt;/p&gt;

&lt;p&gt;Ce problème (entre autres) est corrigé avec le Cumulative Update #1, qu'il est donc urgent de télécharger &lt;a href=&quot;https://www.microsoft.com/download/details.aspx?familyid=4fa9aa71-05f4-40ef-bc55-606ac00479b1&quot; title=&quot;SQL Server 2022 CU1&quot;&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Question : Random values</title>
        <link>https://blog.datafly.pro/post/2023/02/08/Question-%3A-Random-values</link>
        <guid isPermaLink="false">urn:md5:09228e5df6b9c44820af150eb3593fb4</guid>
        <pubDate>Wed, 08 Feb 2023 16:37:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>          &lt;p&gt;&lt;strong&gt;Question &lt;/strong&gt;: Aurais-tu une technique pour qu’au sein d’un SELECT, la fonction Rand() change de valeur sur chaque ligne ? Car malheureusement, elle garde la même valeur sur chaque ligne...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Réponse &lt;/strong&gt;: effectivement, pour un UPDATE SET col = RAND(), la fonction n'est effectuée qu'une seule fois et la valeur sera la même pour toutes les lignes. Mais il existe une solution, avec la création d'une vue et d'une fonction, qui forcera la fonction à s'exécuter pour chaque ligne.&lt;br /&gt;
 &lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-sql&quot;&gt;-- Création d'une vue
CREATE VIEW [dbo].[V_RAND] AS
SELECT RAND() AS RAND  
GO
-- Création d'une fonction
CREATE FUNCTION [dbo].[F_GET_RAND] ()
    RETURNS FLOAT
    AS
    BEGIN
      RETURN (SELECT RAND FROM V_RAND)
    END;
GO

UPDATE MATABLE SET MACOLONNEFLOAT = dbo.F_GET_RAND()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Installations rapides</title>
        <link>https://blog.datafly.pro/post/Installations-rapides</link>
        <guid isPermaLink="false">urn:md5:2ede88b9fd99c4f4c909d3411e869f99</guid>
        <pubDate>Sun, 20 Nov 2022 13:01:00 +0000</pubDate>
        <dc:creator>Arian Papillon</dc:creator>
                        <description>&lt;p&gt;Si comme moi vous déployez fréquemment des instances SQL Server pour des tests divers et que vous êtes pressé, le plus rapide est de le faire avec un fichier de configuration.&lt;/p&gt;

&lt;p&gt;Dans cet article, un exemple de fichier de configuration compact pour une installation simple de SQL Server 2022.&lt;/p&gt;          &lt;p&gt;Voici un exemple de fichier de configuration minimal pour une installation simple et rapide (uniquement le moteur de bases de données, instance par défaut). Nommez le fichier avec l'extension .ini.&lt;/p&gt;

&lt;p&gt;A vous de changer :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Le nom et l'ID de l'instance si c'est une instance nommée&lt;/li&gt;
	&lt;li&gt;La collation par défaut&lt;/li&gt;
	&lt;li&gt;Les comptes de service et passwords&lt;/li&gt;
	&lt;li&gt;Les chemins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensuite, il suffit de lancer l'installation avec le setup de SQL Server et le paramètre configurationfile, par exemple :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;d:\setup.exe /configurationfile=c:\temp\SQLInstall.ini&lt;/strong&gt;&lt;br /&gt;
 &lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-plain&quot;&gt;;SQL Server 2022 INI Installation Configuration File
[OPTIONS]
;Change installation parameters below
;SQL Server instance name
INSTANCENAME=&quot;MSSQLSERVER&quot;
INSTANCEID=&quot;MSSQLSERVER&quot;
;Default collation
SQLCOLLATION=&quot;French_CI_AS&quot;
;Service domain accounts and passwords (SQL Server and SQL Agent)
SQLSVCACCOUNT=&quot;MyDomain\SQLSvc&quot;
SQLSVCPASSWORD=&quot;MyP@ssw0rd&quot;
AGTSVCACCOUNT=&quot;MyDomain\SQLSvc&quot;
AGTSVCPASSWORD=&quot;MyP@ssw0rd&quot;
SQLSYSADMINACCOUNTS=&quot;MyDomain\SQLAdmins&quot;
;Security mode and password of sa account
SECURITYMODE=&quot;SQL&quot;
SAPWD=&quot;MyP@ssw0rd&quot;
;Path configurations
INSTALLSHAREDDIR=&quot;C:\Program Files\Microsoft SQL Server&quot;
INSTALLSHAREDWOWDIR=&quot;C:\Program Files (x86)\Microsoft SQL Server&quot;
INSTANCEDIR=&lt;/code&gt;&quot;C:\Program Files\Microsoft SQL Server&quot;&lt;code class=&quot;language-plain&quot;&gt;
SQLUSERDBDIR=&quot;D:\MSSQLData\MSSQL16.MSSQLSERVER\MSSQL\Data&quot;
SQLUSERDBLOGDIR=&quot;L:\MSSQLData\MSSQL16.MSSQLSERVER\MSSQL\Data&quot;
SQLTEMPDBDIR=&quot;T:\MSSQLData\MSSQL16.MSSQLSERVER\MSSQL\Data&quot;
SQLTEMPDBLOGDIR=&quot;T:\MSSQLData\MSSQL16.MSSQLSERVER\MSSQL\Data&quot;
SQLBACKUPDIR=&quot;S:\MSSQLData\MSSQL16.MSSQLSERVER\MSSQL\Backup&quot;

;For simple installation, no changes are needed here
ACTION=&quot;Install&quot;
FEATURES=SQLENGINE
QUIET=&quot;False&quot;
QUIETSIMPLE=&quot;True&quot;
IACCEPTSQLSERVERLICENSETERMS=&quot;True&quot;
SUPPRESSPRIVACYSTATEMENTNOTICE=&quot;True&quot;
SUPPRESSPAIDEDITIONNOTICE=&quot;True&quot;
SQLSVCSTARTUPTYPE=&quot;Automatic&quot;
AGTSVCSTARTUPTYPE=&quot;Automatic&quot;
SQLSVCINSTANTFILEINIT=&quot;True&quot;
TCPENABLED=&quot;1&quot;
NPENABLED=&quot;0&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
      </channel>
</rss>
