sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo debo pasar un nombre de tabla a un proceso almacenado?

En primer lugar, debe NUNCA hacer composiciones de comandos SQL en una aplicación cliente como esta, eso es qué es la inyección SQL. (Está bien para una herramienta de administración que no tiene privilegios propios, pero no para una aplicación de uso compartido).

En segundo lugar, sí, una llamada parametrizada a un procedimiento almacenado es más limpia y segura.

Sin embargo , ya que necesitará usar Dynamic SQL para hacer esto, aún no desea incluir la cadena pasada en el texto de la consulta ejecutada. En su lugar, desea usar la cadena pasada para buscar los nombres de los actuales tablas que el usuario debe poder consultar en el camino.

He aquí un simple ejemplo ingenuo:

CREATE PROC spCountAnyTableRows( @PassedTableName as NVarchar(255) ) AS
-- Counts the number of rows from any non-system Table, *SAFELY*
BEGIN
    DECLARE @ActualTableName AS NVarchar(255)

    SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_NAME = @PassedTableName

    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';'

    EXEC(@SQL)
END

Algunos han preguntado justamente por qué esto es más seguro. Con suerte, el pequeño Bobby Tables puede aclarar esto:0

Respuestas a más preguntas:

  1. No se garantiza que QUOTENAME solo sea seguro. MS nos alienta a usarlo, pero no han garantizado que los piratas informáticos no puedan engañarlo. FYI, la seguridad real tiene que ver con las garantías. La búsqueda en la tabla con QUOTENAME es otra historia, es irrompible.

  2. QUOTENAME no es estrictamente necesario para este ejemplo, la traducción de búsqueda en INFORMACION_ESQUEMA solo suele ser suficiente. QUOTENAME está aquí porque es una buena forma de seguridad incluir una solución completa y correcta. QUOTENAME aquí en realidad protege contra un problema potencial distinto, pero similar, conocido como inyección latente .

Debo señalar que puede hacer lo mismo con los nombres de columna dinámicos y el INFORMATION_SCHEMA.COLUMNS mesa.

También puede omitir la necesidad de procedimientos almacenados utilizando una consulta SQL parametrizada (ver aquí:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=marco de red-4.8). Pero creo que los procedimientos almacenados brindan una instalación de seguridad más manejable y menos propensa a errores para casos como este.