Aunque aconsejaría en contra de dynamic sql en general, en este caso creo que puede salirse con la suya comprobando si la variable @Table contiene un nombre de tabla válido.
- La pregunta es si usted planea permitir nombres de esquema y/o consultas a través del db, estoy asumiendo que usted no quiere salir de la db (o el servidor) aquí, pero sí permiten diferentes esquemas de (AdventureWorks muestra cómo se pueden usar)
- También PODRÍA incluir vistas para @Table.
- Probablemente sería "bueno" si también verificara si el objeto encontrado tiene una columna ID y arroja un error de "usuario amigable" si no es así. Opcional sin embargo.
Solo poniendo QuoteName() alrededor de @table NO lo protegerá de todo.Aunque es una gran función, está lejos de ser perfecta. En mi humilde opinión, su mejor opción sería analizar la variable @Table, verificar si su contenido es válido y luego crear un sql dinámico basado en las partes obtenidas. empecé a cabo haciendo la mayor parte de arriba y es sorprendente que no se requiere una gran cantidad de comprobación de algo que parece tan simple como esto =)
CREATE PROCEDURE [dbo].[GetDataByID] (
@ID bigint,
@Table nvarchar(300)
)
AS
DECLARE @sql nvarchar(max)
DECLARE @server_name sysname,
@db_name sysname,
@schema_name sysname,
@object_name sysname,
@schema_id int
SELECT @server_name = ParseName(@Table, 4),
@db_name = ParseName(@Table, 3),
@schema_name = ParseName(@Table, 2),
@object_name = ParseName(@Table, 1)
IF ISNULL(@server_name, @@SERVERNAME) <> @@SERVERNAME
BEGIN
RaisError('Queries are restricted to this server only.', 16, 1)
Return(-1)
END
IF ISNULL(@db_name, DB_Name()) <> DB_Name()
BEGIN
RaisError('Queries are restricted to this database only.', 16, 1)
Return(-1)
END
IF @schema_name IS NULL
BEGIN
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE name = @object_name
AND type IN ('U', 'V'))
BEGIN
RaisError('Requested @Table not found. [%s]', 16, 1, @object_name)
Return(-1)
END
SELECT @sql = 'SELECT * FROM ' + QuoteName(@object_name) + ' WHERE ID = @ID'
END
ELSE
BEGIN
SELECT @schema_id = Schema_id(@schema_name)
IF @schema_id IS NULL
BEGIN
RaisError('Unrecognized schema requested [%s].', 16, 1, @schema_name)
Return(-1)
END
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE name = @object_name
AND schema_id = @schema_id
AND type IN ('U', 'V'))
BEGIN
RaisError('Requested @Table not found. [%s].[%s]', 16, 1, @schema_name, @object_name)
Return(-1)
END
SELECT @sql = 'SELECT * FROM ' + QuoteName(@schema_name) + '.' + QuoteName(@object_name) + ' WHERE ID = @ID'
END
EXEC sp_executesql @stmt = @sql,
@params = N'@ID bigint',
@ID = @ID
Return(0)
Supra compila, pero es posible que tenga que limar algunos errores como yo no' Basta con verificar todas las rutas de código.
Sólo una pequeña cosa que no afecta mucho las cosas, pero ¿no es el param de '@ Table' ese el problema aquí? '@ ID' es un' bigint', por lo que solo puede ser un número cuando se llega al punto de construir la declaración SQL dinámica, ¿verdad? –
Supongo que ambos ... –