Передать имена таблиц и столбцов в качестве параметров и получить значение - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь построить общий запрос, чтобы передать имя столбца, на которое я хочу рассчитывать, и имя таблицы, которую я хочу выбрать значение.

Пока это мой код:

ALTER PROCEDURE [dbo].[GenericCountAll]
    @TableName VARCHAR(100),
    @ColunName VARCHAR(100)
AS
BEGIN
    DECLARE @table VARCHAR(30);
    DECLARE @Rowcount INT;

    SET @table = N'SELECT COUNT(' + @ColunName +') FROM ' + @TableName + '';
    EXEC(@table)

    SET @Rowcount = @@ROWCOUNT
    SELECT @Rowcount
END

Попытка выполнить так:

EXEC GenericCountAll 'T_User', 'Id';

, но похоже, что я получаю два результата, первый результат всегда возвращает значение 1, а второй результат возвращает реальное число.Кто-нибудь может взглянуть?

1 Ответ

0 голосов
/ 12 мая 2018

Не создайте динамический SQL, как это!Представьте себе, если бы я запустил:

EXEC GenericCountAll '*/DROP PROCEDURE dboGenericCountAll;--', '1);/*';

В результате был бы выполнен SQL:

SELECT COUNT(1);/*) FROM */ DROP PROCEDURE dboGenericCountAll;--

Это просто DROP ваша процедура.И это просто простой пример.Если бы я знал, что могу продолжать делать злонамеренные действия, я мог бы даже создать новый логин или пользователя и сделать a db_owner или sysadmin (в зависимости от разрешений того, что когда-либо использовалось для запуска этой процедуры).

Я тоже не знаю, в чем смысл @@ROWCOUNT, сомневаюсь, что это необходимо.Таким образом, чтобы сделать это БЕЗОПАСНЫМ, вам нужно сделать что-то вроде этого:

ALTER procedure [dbo].[GenericCountAll]
    @TableName sysname, --Note the datatype change
    @ColumnName sysname
AS
BEGIN
    DECLARE @SQL nvarchar(MAX);

    SELECT  N'SELECT COUNT(' + QUOTENAME(c.[name]) + N') AS RowCount' + NCHAR(10) +
            N'FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.name) + N';'
    FROM sys.tables t
         JOIN sys.schemas s ON t.schema_id = s.schema_id
         JOIN sys.columns c ON t.object_id = c.object_id
    WHERE t.[name] = @TableName
      AND c.[name] = @ColumnName;
    /*
    If either the column or the table doesn't exist, then @SQL
    will have a value of NULL. This is a good thing, as it 
    is a great way to further avoid injection, if a bogus
    table or column name is passed
    */

    IF @SQL IS NOT NULL BEGIN;
        PRINT @SQL; --Your best debugging friend
        EXEC sp_executesql @SQL;
    END ELSE BEGIN;
        RAISERROR(N'Table does not exist, or the Column does not exist for the Table provided.',11,1);
    END;

END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...