Variable table name using dynamic SQL in C#

后端 未结 4 1699
没有蜡笔的小新
没有蜡笔的小新 2020-12-21 19:06

I\'ve been looking around for a way to enter a variable table name and it seems the best way is to use dynamic sql, although it can lead to SQL injection. Can anyone demonst

4条回答
  •  生来不讨喜
    2020-12-21 20:01

    It seems that you have to use dynamic SQL, which basically means you're going to have to concatenate the table name into a query string and run it through the 'sp_executesql' stored procedure in TSQL.

    Using SqlCommand is not dynamic SQL. Although you are dynamically building an SQL string, you are still running a plain old SQL string in the end.

    To do so safely and project against SQL injection, you must ensure the table name is valid, and you must do so yourself through any means necessary. Fortunately, you have 3 good options, one of which is very easy and virtually fool-proof.

    As others have mentioned, you could:

    1. Check the name against a white list, or
    2. Look up the name in a system table to see if it's a real table name, or
    3. Just use the QUOTENAME function to escape the characters and make them a quoted identifier.

    I had a similar question about dropping a table by name, and that's where the QUOTENAME function was mentioned: https://stackoverflow.com/a/19528324/88409

    To use dynamic SQL, you would actually have to do something like this:

    string sql = 
        "declare @query nvarchar(max) = 'SELECT * FROM ' + QUOTENAME(@tablename) + ' WHERE ' + QUOTENAME(@columnname) + ' = @cv'; " +
        "declare @params nvarchar(500) = N'@cv nvarchar(500)'; " +
        "exec sp_executesql @query, @params, @cv=@columnvalue;";
    
    SqlCommand command = new SqlCommand( sql, conn );
    command.Parameters.AddWithValue( "@tablename", tableName );
    command.Parameters.AddWithValue( "@columnname", columnName );
    command.Parameters.AddWithValue( "@columnvalue", columnValue );
    

    If by chance the SqlCommand class doesn't support such a complex query with 'declare' statements, then you'll need to just move the value of the 'sql' string into a stored procedure that takes those same three parameters then call it by name by setting the SqlCommand.CommandType to StoredProcedure like so:

    SqlCommand command = new SqlCommand( "MyStoredProcedureName", conn );
    command.CommandType = System.Data.CommandType.StoredProcedure;
    command.Parameters.AddWithValue( "@tablename", tableName );
    command.Parameters.AddWithValue( "@columnname", columnName );
    command.Parameters.AddWithValue( "@columnvalue", columnValue );
    

提交回复
热议问题