Muszę przeformułować i udokumentować szereg foo.sql
zapytań, które będą udostępniane przez zespół wsparcia technicznego DB (w przypadku konfiguracji klienta i tym podobnych). Istnieją rodzaje biletów, które przychodzą regularnie, gdy każdy klient ma własne serwery i bazy danych, ale poza tym schemat jest taki sam we wszystkich obszarach.
Procedury przechowywane nie są obecnie dostępne. Zastanawiam się, czy użyć dynamicznego, czy SQLCMD, nie używałem ich zbyt często, ponieważ jestem trochę nowy w SQL Server.
Skrypty SQLCMD Wydaje mi się, że zdecydowanie „dla mnie” wygląda na czystsze, łatwiejsze do odczytania i wprowadzania w razie potrzeby niewielkich zmian w zapytaniach, ale także zmusza użytkownika do włączenia trybu SQLCMD. Dynamika jest trudniejsza, ponieważ wyróżnianie składni jest utratą z powodu pisania zapytań przy użyciu operacji na łańcuchach.
Są one edytowane i uruchamiane za pomocą Management Studio 2012, wersja SQL 2008R2. Jakie są zalety / wady jednej z metod lub niektóre „najlepsze praktyki” programu SQL Server dotyczące jednej lub drugiej metody? Czy jeden z nich jest „bezpieczniejszy” niż drugi?
Dynamiczny przykład:
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);
Przykład 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));
źródło
use ...
twojego skryptu? Czy ważne jest prawidłowe wykonanie następnego zapytania? Pytam, ponieważ jeśli zmiana bieżącej bazy danych jest jednym z oczekiwanych wyników zapytania, dynamiczna wersja SQL zmieni ją tylko w zakresie zapytania dynamicznego, a nie w zakresie zewnętrznym, w przeciwieństwie do wariantu SQLCMD (który z oczywiście ma tylko jeden zakres).use
Oświadczenie mogło być prawdopodobnie pominięte, jako zakres nie zostanie zmieniony podczas tego konkretnego scenariusza jakikolwiek. Mam niewielką liczbę przypadków użycia, w których będą przeprowadzane wyszukiwania między serwerami, ale może to wykraczać poza zakres tego postu.Odpowiedzi:
Aby to usunąć:
Technicznie rzecz biorąc, obie te opcje to zapytania „dynamiczne” / ad hoc, które nie są analizowane / sprawdzane przed przesłaniem. I oba są podatne na SQL Injection, ponieważ nie są parametryzowane (choć ze skryptami Sqlcmd, jeśli przechodzą w zmiennej ze skryptu CMD potem masz możliwość wymiany
'
z''
, co może lub może nie działać w zależności od tego, gdzie używane są zmienne).Każde podejście ma wady i zalety:
Jeśli twoi pracownicy pomocy technicznej nie wykonują zapytań ad hoc i po prostu wypełniają te zmienne, nie muszą znajdować się w SSMS, gdzie mogą edytować te skrypty i wprowadzać niepożądane zmiany.
Utworzyłbym skrypty CMD, aby zapytać użytkownika o pożądane wartości zmiennych, a następnie wywołać SQLCMD.EXE z tymi wartościami. Skrypt CMD może nawet zapisać wykonanie do pliku, wraz ze znacznikiem czasu i przesłanymi wartościami zmiennych.
Utwórz jeden skrypt CMD dla każdego skryptu SQL i umieść w udostępnionym sieciowym folderze. Użytkownik dwukrotnie klika skrypt CMD i po prostu działa.
Oto przykład:
%OrderIDsSeparatedByCommas%
jako zmiennej SQLCMD$(OrderIDsSeparatedByCommas)
Testuj skrypt SQL (o nazwie: FixProblemX.sql ):
Skrypt CMD (o nazwie: FixProblemX.cmd ):
Zmodyfikuj
ScriptLogPath
zmienną u góry skryptu.Również skrypty SQL (określone przez
-i
przełącznik wiersza polecenia dla SQLCMD.EXE ) mogą skorzystać z posiadania w pełni kwalifikowanej ścieżki, ale nie do końca pewni.źródło