我正在尝试进行设置,以便将表名作为参数传递给命令文本,但是我无法使其正常工作。我四处张望,发现了这样的问题:使用C#进行MySQL的参数化查询,但是我没有任何运气。
这是相关的代码(connection == MySqlConnection包含连接字符串):
MySqlConnection
public static DataSet getData(string table) { DataSet returnValue = new DataSet(); try { MySqlCommand cmd = connection.CreateCommand(); cmd.Parameters.AddWithValue("@param1", table); cmd.CommandText = "SELECT * FROM @param1"; connection.Open(); MySqlDataAdapter adap = new MySqlDataAdapter(cmd); adap.Fill(returnValue); } catch (Exception) { } finally { if (connection.State == ConnectionState.Open) connection.Close(); } return returnValue; }
如果我更改:
cmd.CommandText = "SELECT * FROM @param1";
至:
cmd.CommandText = "SELECT * FROM " + table;
作为一种测试方法,它是可行的(我正在将XML从数据集中写入控制台以进行检查)。因此,我很确定问题只是以错误的方式使用了参数功能。有指针吗?
另外,如果我记错了,请更正我,但是使用Parameter功能应该提供针对SQL注入的完全保护,对吗?
您 不能 参数化表名,列名或任何其他数据库对象。您 只能 参数化您的值。
您需要在SQL查询中将其作为字符串串联传递,但是在此之前,我建议使用 强 验证或白名单(仅固定设置的 可能的 正确值)。
如果用“参数功能” 表示参数化语句,是的,这是正确的。
顺便说一下,请注意,有一个称为动态SQL支持的概念,SELECT * FROM @tablename但不建议这样做。
SELECT * FROM @tablename
正如我们已经看到的,我们可以在动态SQL的帮助下使该过程正常工作,但是也应该清楚,在存储过程中生成该动态SQL并没有获得任何好处。您也可以从客户端发送动态SQL。因此,可以:1)如果SQL语句非常复杂,则可以节省一些网络流量并进行封装。2)如我们所见,从SQL 2005开始,有一些处理权限的方法。 然而,这是一个坏主意。 人们想要参数化表名似乎有几个原因 。一个阵营似乎是对SQL编程不熟悉的人,但是他们从其他语言(例如C ++,VB等)中受益匪浅,其中参数化是一件好事。参数化表名称以实现通用代码并增加可维护性似乎是程序员的美德。 但是,就数据库对象而言,古老的真理并不成立。在适当的数据库设计中,每个表都是唯一的,因为它描述了唯一的实体。(或者至少应该如此!)当然,最后要得到一打或更多的查找表,这些查找表都有一个id,一个name列和一些审计列,这并不少见。但是它们确实描述了不同的实体,并且它们的相似之处仅应视为偶然,并且将来的要求可能会使表格更加不同。
正如我们已经看到的,我们可以在动态SQL的帮助下使该过程正常工作,但是也应该清楚,在存储过程中生成该动态SQL并没有获得任何好处。您也可以从客户端发送动态SQL。因此,可以:1)如果SQL语句非常复杂,则可以节省一些网络流量并进行封装。2)如我们所见,从SQL 2005开始,有一些处理权限的方法。 然而,这是一个坏主意。
人们想要参数化表名似乎有几个原因 。一个阵营似乎是对SQL编程不熟悉的人,但是他们从其他语言(例如C ++,VB等)中受益匪浅,其中参数化是一件好事。参数化表名称以实现通用代码并增加可维护性似乎是程序员的美德。
但是,就数据库对象而言,古老的真理并不成立。在适当的数据库设计中,每个表都是唯一的,因为它描述了唯一的实体。(或者至少应该如此!)当然,最后要得到一打或更多的查找表,这些查找表都有一个id,一个name列和一些审计列,这并不少见。但是它们确实描述了不同的实体,并且它们的相似之处仅应视为偶然,并且将来的要求可能会使表格更加不同。