Je dois refactoriser et documenter un certain nombre de foo.sql
requêtes qui seront partagées par une équipe de support technique DB (pour les configurations client et des choses comme ça). Il existe des types de tickets qui viennent régulièrement lorsque chaque client a ses propres serveurs et bases de données, mais sinon le schéma est le même à tous les niveaux.
Les procédures stockées ne sont pas une option à l'heure actuelle. Je suis en train de débattre de l'utilisation de Dynamic ou SQLCMD, je n'en ai pas beaucoup utilisé car je suis un peu nouveau chez SQL Server.
Les scripts SQLCMD Je me sens vraiment "plus" propre pour moi, plus facile à lire et à apporter de petites modifications aux requêtes selon les besoins, mais force également l'utilisateur à activer le mode SQLCMD. La dynamique est plus difficile car la mise en évidence de la syntaxe est une perte due à l'écriture de la requête à l'aide de la manipulation de chaînes.
Ceux-ci sont en cours d'édition et exécutés à l'aide de Management Studio 2012, SQL version 2008R2. Quels sont les avantages / inconvénients de l'une ou l'autre méthode, ou certaines des "meilleures pratiques" de SQL Server sur une méthode ou l'autre? L'un d'eux est-il "plus sûr" que l'autre?
Exemple dynamique:
declare @ServerName varchar(50) = 'REDACTED';
declare @DatabaseName varchar(50) = 'REDACTED';
declare @OrderIdsSeparatedByCommas varchar(max) = '597336, 595764, 594594';
declare @sql_OrderCheckQuery varchar(max) = ('
use {@DatabaseName};
select
-- stuff
from
{@ServerName}.{@DatabaseName}.[dbo].[client_orders]
as "Order"
inner join {@ServerName}.{@DatabaseName}.[dbo].[vendor_client_orders]
as "VendOrder" on "Order".o_id = "VendOrder".vco_oid
where "VendOrder".vco_oid in ({@OrderIdsSeparatedByCommas});
');
set @sql_OrderCheckQuery = replace( @sql_OrderCheckQuery, '{@ServerName}', quotename(@ServerName) );
set @sql_OrderCheckQuery = replace( @sql_OrderCheckQuery, '{@DatabaseName}', quotename(@DatabaseName) );
set @sql_OrderCheckQuery = replace( @sql_OrderCheckQuery, '{@OrderIdsSeparatedByCommas}', @OrderIdsSeparatedByCommas );
print (@sql_OrderCheckQuery); -- For debugging purposes.
execute (@sql_OrderCheckQuery);
Exemple SQLCMD:
:setvar ServerName "[REDACTED]";
:setvar DatabaseName "[REDACTED]";
:setvar OrderIdsSeparatedByCommas "597336, 595764, 594594"
use $(DatabaseName)
select
--stuff
from
$(ServerName).$(DatabaseName).[dbo].[client_orders]
as "Order"
inner join $(ServerName).$(DatabaseName).[dbo].[vendor_client_orders]
as "VendOrder" on "Order".o_id = "VendOrder".vco_oid
where "VendOrder".vco_oid in ($(OrderIdsSeparatedByCommas));
la source
use ...
votre script? Est-ce important pour l'exécution correcte de la requête suivante? Je demande parce que si la modification de la base de données actuelle est l'un des résultats attendus de votre requête, la version SQL dynamique ne la modifiera que dans la portée de la requête dynamique, pas dans la portée externe, contrairement à la variation SQLCMD (qui, de n’a qu’une seule portée).use
instruction pourrait probablement être omise, car la portée ne sera pas modifiée de toute façon pendant ce script particulier. J'ai un petit nombre de cas d'utilisation où il y aura des recherches inter-serveurs mais qui pourraient être au-delà de la portée de cet article.Réponses:
Juste pour les éliminer:
Techniquement parlant, ces deux options sont des requêtes "dynamiques" / ad hoc qui ne sont pas analysées / validées tant qu'elles n'ont pas été soumises. Et les deux sont sensibles à l'injection SQL car ils ne sont pas paramétrés (bien qu'avec les scripts SQLCMD, si vous transmettez une variable à partir d'un script CMD, vous avez la possibilité de la remplacer
'
par''
, qui peut ou non fonctionner selon l'endroit où le variables sont utilisées).Il y a des avantages et des inconvénients à chaque approche:
Si vos assistants ne font pas de requêtes ad hoc et remplissent simplement ces variables, ils n'ont pas besoin d'être dans SSMS où ils peuvent éditer ces scripts et apporter des modifications indésirables.
Je créerais des scripts CMD pour demander à l'utilisateur les valeurs de variable souhaitées, puis j'appellerais SQLCMD.EXE avec ces valeurs. Le script CMD pourrait même consigner l'exécution dans un fichier, avec horodatage et valeurs variables soumises.
Créez un script CMD par script SQL et placez-le dans un dossier partagé en réseau. Un utilisateur double-clique sur le script CMD et cela fonctionne.
Voici un exemple qui:
%OrderIDsSeparatedByCommas%
comme variable SQLCMD$(OrderIDsSeparatedByCommas)
Tester le script SQL (nommé: FixProblemX.sql ):
Script CMD (nommé: FixProblemX.cmd ):
Assurez-vous de modifier la
ScriptLogPath
variable vers le haut du script.En outre, les scripts SQL (spécifiés par le
-i
commutateur de ligne de commande pour SQLCMD.EXE ) peuvent bénéficier d'un chemin d'accès complet, mais pas entièrement sûr.la source