SqlClient.SqlDataAdapter.Fill(DataSet) 结果如果不选择查询

Posted

技术标签:

【中文标题】SqlClient.SqlDataAdapter.Fill(DataSet) 结果如果不选择查询【英文标题】:SqlClient.SqlDataAdapter.Fill(DataSet) results if not select query 【发布时间】:2020-09-23 13:19:26 【问题描述】:

如果执行的查询不是select语句,我需要知道SqlClient.SqlDataAdapter.Fill(DataSet)的结果。

例子:当用户输入的是insert语句而不是select语句时,即使不是select语句,数据适配器也会执行,如何知道执行语句的结果?

【问题讨论】:

你考虑过运行你的代码吗? 是的,它返回空数据集,但是执行了提供给数据适配器的删除语句。 一个名为Fill 的方法的全部意义在于填充一些东西。如果您没有填写DataTable - 是否填写DataSet - 然后不要在数据适配器上调用Fill。如果你想执行DELETE 语句,然后调用ExecuteNonQuery,就像你应该做的那样。 您希望INSERT INTO Person VALUES('Imad') 产生什么结果集? 让用户输入任意sql然后执行是灾难的秘诀。 【参考方案1】:

您在其他地方的评论中写道:

但我无法控制用户只编写选择语句。因为它将被 IT 人员使用。如果用户需要向表中插入数据并使用相同的页面,它将被执行。

这真的很容易解决:

    Dim sql = whatTheUserWrote.Trim()

    Dim sc = StringComparison.InvariantCultureIgnoreCase

    If "SELECT WITH".Split().Any(Function(s) sql.StartsWith(s, sc)) Then

      'uses something like: dbDataAdapter.Fill(someDatatable)
      RunSqlUsingDataAdapterFill(sql)

    Else If "INSERT UPDATE DELETE".Split().Any(Function(s) sql.StartsWith(s, sc)) Then

      'uses something like: Dim rowsAffected = dbCommand.ExecuteNonQuery()
      RunSqlUsingCommandExecuteNonQuery(sql)
  
    Else 

      Throw New ArgumentException("The SQL provided must start with one of these following words: SELECT WITH INSERT UPDATE DELETE", whatTheUserWrote, NameOf(whatTheUserWrote))

    End

顺便说一句,我认为为用户创建 SQL 查询客户端是一个非常糟糕的主意,但这不是我的工作!希望您的表/行级别权限对此进行了很好的排序

【讨论】:

但是如果 SQL 语句以空格开头怎么办?或者喜欢/* SELECT * FROM Foo */ DELETE FROM Foo?将 SQL 解析为单纯的字符串并不容易。 但是如果 SQL 语句以空格开头怎么办? Dim sql = whatTheUserWrote.Trim() 将 SQL 解析为字符串可能并不容易,但对您可以提供给用户的最具破坏性的功能强加一组规则确实很容易。如果他们不能遵循简单的指示,那么他们是否应该有权访问该功能是一个很好的决定;)【参考方案2】:

Docs: DataAdapter.Fill Method#Fill(DataSet)

Fill 方法使用关联的 SelectCommand 属性指定的 SELECT 语句从数据源中检索行。

Docs: IDbDataAdapter.SelectCommand Property

如果 SelectCommand 没有返回任何行,则不会将表添加到 DataSet,并且不会引发异常。

因此您的适配器将保持为空。

【讨论】:

但是语句会被执行。如何知道提供的语句的执行结果? 你问错问题了。如果你的用户可以输入任意SQL,那你为什么要通过DataSet.SelectCommand来执行呢?它是一个特殊的 API,例如可以帮助您用很少的代码行从数据库表中填充 UI 网格。如果您想执行可能不会选择记录而是更新记录的 SQL,请使用不同的 API。 情况是我的系统中有一个页面允许用户编写sql select语句以查看为表。但我无法控制用户只编写选择语句。因为它将被 IT 人员使用。如果用户需要向表中插入数据并使用相同的页面,它将被执行。 但是你在寻找什么“结果”呢?在 INSERT 或 UPDATE 语句的情况下,不可能以这种方式获得“受影响的 n 行”,因为您使用的整个 API 并不意味着这样做。如果您想要一个功能合理的系统,您可以解析用户输入的 SQL 并检测它是否包含 SELECT 语句。如果没有,请通过不同的 API 执行 SQL。此外,我不会让用户(管理员或非管理员)能够通过 Web 应用程序执行原始 SQL。如果他们粘贴DELETE FROM Users 并执行它会怎样?你有备份吗?

以上是关于SqlClient.SqlDataAdapter.Fill(DataSet) 结果如果不选择查询的主要内容,如果未能解决你的问题,请参考以下文章