Tengo que refactorizar y documentar una serie de foo.sql
consultas que serán compartidas por un equipo de soporte técnico de DB (para configuraciones de clientes y cosas por el estilo). Hay tipos de tickets que vienen regularmente donde cada cliente tiene sus propios servidores y bases de datos, pero de lo contrario el esquema es el mismo en todos los ámbitos.
Los procedimientos almacenados no son una opción en este momento. Estoy debatiendo si usar dinámico o SQLCMD, no he usado mucho ya que soy un poco nuevo en SQL Server.
Las secuencias de comandos SQLCMD definitivamente me parecen "más limpias", más fáciles de leer y realizar pequeños cambios en las consultas según sea necesario, pero también obliga al usuario a habilitar el modo SQLCMD. La dinámica es más difícil ya que el resaltado de sintaxis es pérdida debido a que la consulta se escribe utilizando la manipulación de cadenas.
Estos se están editando y ejecutando usando Management Studio 2012, SQL versión 2008R2. ¿Cuáles son algunos de los pros / contras de cualquiera de los métodos, o algunas de las "mejores prácticas" de SQL Server en un método u otro? ¿Es uno de ellos "más seguro" que el otro?
Ejemplo dinámico:
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);
Ejemplo de 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));
fuente
use ...
tu guión? ¿Es importante para la correcta ejecución de la consulta posterior? Lo pregunto porque si cambiar la base de datos actual es uno de los resultados esperados de su consulta, la versión dinámica de SQL solo lo cambiará en el alcance de la consulta dinámica, no en el alcance externo, a diferencia de la variación SQLCMD (que, de Por supuesto, tiene un solo alcance).use
declaración probablemente podría omitirse, ya que el alcance no se cambiará durante este script en particular de todos modos. Tengo una pequeña cantidad de casos de uso en los que habrá búsquedas entre servidores, pero eso podría estar fuera del alcance de esta publicación.Respuestas:
Solo para sacarlos del camino:
Técnicamente hablando, ambas opciones son consultas "dinámicas" / ad hoc que no se analizan / validan hasta que se envían. Y ambos son susceptibles a la inyección de SQL, ya que no se parametrizan (aunque con los guiones SQLCMD, si estás de paso en una variable a partir de una secuencia de comandos CMD entonces usted tiene la oportunidad de reemplazar
'
con''
, que puede o puede no funcionar dependiendo de la ubicación del Se están utilizando variables).Hay ventajas y desventajas de cada enfoque:
Si su personal de soporte no está haciendo consultas ad hoc y solo está completando esas variables, entonces no necesitan estar en SSMS donde puedan editar esos scripts y realizar cambios no deseados.
Crearía scripts CMD para solicitar al usuario los valores de las variables deseadas y luego llamaría a SQLCMD.EXE con esos valores. La secuencia de comandos CMD podría incluso registrar la ejecución en un archivo, completa con la marca de tiempo y los valores variables enviados.
Cree un script CMD por script SQL y colóquelo en una carpeta compartida en red. Un usuario hace doble clic en el script CMD y simplemente funciona.
Aquí hay un ejemplo que:
%OrderIDsSeparatedByCommas%
como la variable SQLCMD$(OrderIDsSeparatedByCommas)
Probar script SQL (llamado: FixProblemX.sql ):
Script CMD (llamado: FixProblemX.cmd ):
Asegúrese de editar la
ScriptLogPath
variable hacia la parte superior del script.Además, las secuencias de comandos SQL (especificadas por el modificador de
-i
línea de comandos para SQLCMD.EXE ) pueden beneficiarse de tener una ruta totalmente calificada, pero no del todo seguro.fuente