Единственный способ, которым я могу думать о том, чтобы сделать это "безопасно", - это изменить свой встроенный запрос на параметризованный вызов хранимой процедуры, а затем изящно обработать имена объектов там. Это, однако, требует, чтобы у проверяемого столбца всегда был один и тот же тип данных (в данном случае я предположил int
):
CREATE PROC TableMaxCount @Table sysname, @Column sysname, @Value int AS
BEGIN
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SELECT MAX(' + QUOTENAME(@Column) + NCHAR(13) + NCHAR(10) +
N'FROM ' + QUOTENAME(@Table) + NCHAR(13) + NCHAR(10) +
N'WHERE ' + QUOTENAME(@Column) + N' = @Value;';
EXEC sp_executesql @SQL, N'@Value int', @Value = @Value;
END
Это, однако, приведет к ошибке, если пользователь введет значение, которое не является таблицей или столбцом для чтения. Если это нежелательно, и вы хотите проверить имена объектов, вы можете сделать что-то более похожее на это:
CREATE PROC TableMaxCount @Table sysname, @Column sysname, @Value int AS
BEGIN
DECLARE @SQL nvarchar(MAX);
SELECT @SQL = N'SELECT MAX(' + QUOTENAME(c.[name]) + NCHAR(13) + NCHAR(10) +
N'FROM ' + QUOTENAME(t.[name]) + NCHAR(13) + NCHAR(10) +
N'WHERE ' + QUOTENAME(c.[name]) + N' = @Value;'
FROM sys.tables t
JOIN sys.columns c ON t.object_id = c.object_id
JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.[name] = @Table
AND c.[name] = @Column
AND s.[name] = N'dbo'; --Assumes always dbo schema
EXEC sp_executesql @SQL, N'@Value int', @Value = @Value;
END
Боюсь, мой C # в лучшем случае ужасен, но, надеюсь, вы уже знаете, как использовать параметризованный код для вызова SQL. Если нет, я знаю, что документация действительно охватывает это. ( Свойство SqlCommand.Parameters )