Ich muss eine Reihe von Änderungen vornehmen und dokumentieren foo.sql
Abfragen , die von einem Team des technischen Supports von DB geteilt werden (für Kundenkonfigurationen und ähnliches). Es gibt Arten von Tickets, bei denen jeder Kunde seine eigenen Server und Datenbanken hat, ansonsten ist das Schema auf der ganzen Linie gleich.
Gespeicherte Prozeduren sind derzeit keine Option. Ich überlege, ob ich Dynamic oder SQLCMD verwenden soll. Ich habe von beidem nicht viel verwendet, da ich bei SQL Server ein bisschen neu bin.
SQLCMD-Skripte Ich bin der Meinung, dass sie auf jeden Fall "sauberer" aussehen und nach Bedarf leichter zu lesen und geringfügige Änderungen an den Abfragen vorzunehmen sind, aber sie zwingen den Benutzer, den SQLCMD-Modus zu aktivieren. Dynamisch ist schwieriger, da die Syntaxhervorhebung aufgrund von Abfragen, die mithilfe von Zeichenfolgenmanipulation geschrieben werden, verloren geht.
Diese werden mit Management Studio 2012, SQL-Version 2008R2, bearbeitet und ausgeführt. Was sind einige der Vor- / Nachteile einer der beiden Methoden oder einige der "Best Practices" von SQL Server für die eine oder die andere Methode? Ist einer von ihnen "sicherer" als der andere?
Dynamisches Beispiel:
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);
SQLCMD-Beispiel:
: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));
quelle
use ...
in Ihrem Skript? Ist es wichtig, dass die nachfolgende Abfrage korrekt ausgeführt wird? Ich frage, weil, wenn das Ändern der aktuellen Datenbank eines der erwarteten Ergebnisse Ihrer Abfrage ist, die dynamische SQL-Version dies nur im Bereich der dynamischen Abfrage ändert, nicht im äußeren Bereich, im Gegensatz zur SQLCMD-Variante (welche von Natürlich hat nur ein Anwendungsbereich).use
Anweisung könnte wahrscheinlich weggelassen werden, da der Gültigkeitsbereich in diesem speziellen Skript sowieso nicht geändert wird. Ich habe eine kleine Anzahl von Anwendungsfällen, in denen serverübergreifende Suchvorgänge durchgeführt werden, die jedoch möglicherweise den Rahmen dieses Beitrags sprengen.Antworten:
Nur um diese aus dem Weg zu räumen:
Technisch gesehen handelt es sich bei beiden Optionen um "dynamische" / Ad-hoc-Abfragen, die erst nach Übermittlung analysiert / validiert werden. Und beide sind für SQL Injection anfällig , da sie nicht parametriert werden (wenn auch mit dem SQLCMD - Skripts, wenn Sie in einer Variablen von einem CMD - Skript sind vorbei , dann haben Sie die Möglichkeit , ersetzen
'
mit''
, die Arbeit kann oder auch nicht , je nachdem , wo die Variablen werden verwendet).Jeder Ansatz hat Vor- und Nachteile:
Wenn Ihre Supportmitarbeiter keine Ad-hoc-Abfragen durchführen und nur diese Variablen ausfüllen, müssen sie sich nicht in SSMS befinden, wo sie diese Skripte bearbeiten und unerwünschte Änderungen vornehmen können.
Ich würde CMD-Skripte erstellen, um den Benutzer zur Eingabe der gewünschten Variablenwerte aufzufordern, und dann SQLCMD.EXE mit diesen Werten aufrufen . Das CMD-Skript könnte sogar die Ausführung in einer Datei protokollieren, einschließlich des Zeitstempels und der übermittelten Variablenwerte.
Erstellen Sie ein CMD-Skript pro SQL-Skript und legen Sie es in einem freigegebenen Netzwerkordner ab. Ein Benutzer klickt doppelt auf das CMD-Skript und es funktioniert einfach.
Hier ist ein Beispiel, das:
%OrderIDsSeparatedByCommas%
Führt das SQL-Skript aus und übergibt den Wert von als SQLCMD-Variable$(OrderIDsSeparatedByCommas)
Test-SQL-Skript (Name: FixProblemX.sql ):
CMD-Skript (Name: FixProblemX.cmd ):
Stellen Sie sicher, dass Sie die
ScriptLogPath
Variable oben im Skript bearbeiten .Die SQL-Skripte (die von der
-i
Befehlszeilenoption für SQLCMD.EXE angegeben werden ) verfügen möglicherweise über einen vollständig qualifizierten Pfad, sind sich jedoch nicht ganz sicher.quelle