带有 VB.net 变量字符串条件的动态 SQL 查询

Posted

技术标签:

【中文标题】带有 VB.net 变量字符串条件的动态 SQL 查询【英文标题】:Dynamic SQL Query With VB.net Variables String condition 【发布时间】:2021-02-02 20:40:14 【问题描述】:

大家好,可能是一个快速的答案,但我正在努力解决这个问题,认为一定有更好的方法。

如果字符串的条件不为 null 或为空,我有 4 个字符串,我将其添加到查询中,但第一个始终不需要 AND,因此我添加了 WHERE 1 = 1,然后我可以添加 AND ID = @ID 等,因此可以添加所有四个。我错过了什么?

   Dim sqlBuilder As New StringBuilder()
    '1 = 1 allows an and.
    sqlBuilder.Append("SELECT * FROM table WHERE 1=1 ")

    If Surname <> "" Then
        sqlBuilder.Append(" AND Surname=@surname")
    End If
    If Payroll <> "" Then
        sqlBuilder.Append(" AND payroll = @payroll")
    End If
    If VehicleReg <> "" Then
        sqlBuilder.Append(" AND registration = @registration")
    End If
    If OrgID > 0 Then
        sqlBuilder.Append(" AND OrganisationID = @orgid")
    End If

【问题讨论】:

您遇到错误了吗?如果有,那是什么? 你的所作所为对我来说似乎很好,但我建议的唯一一件事是检查你的 builder 的长度,然后只在需要时添加“AND” 没有错误我只是想知道是否有更好的方法。 我个人会坚持使用这个(或其他一些 LINQ 构建的链)而不是一个“上帝查询”。请参阅我对@jmcilhinney 答案的评论了解原因。 【参考方案1】:

有一种简单的方法可以使用单个不变的 SQL 查询,同时将参数设为可选,例如

Dim query = "SELECT * FROM Person WHERE (@FirstName IS NULL OR FirstName = @FirstName) AND (@LastName IS NULL OR LastName = @LastName)"
Dim command As New SqlCommand

command.CommandText = query

With command.Parameters
    .Add("@FirstName", SqlDbType.VarChar, 50).Value = If(firstNameTextBox.TextLength = 0, CObj(DBNull.Value), firstNameTextBox.Text)
    .Add("@LastName", SqlDbType.VarChar, 50).Value = If(lastNameTextBox.TextLength = 0, CObj(DBNull.Value), lastNameTextBox.Text)
End With

通过将参数设置为 NULL,您可以有效地忽略它。例如,如果@FirstName 参数设置为NULL,那么@FirstName IS NULL 为真,并且第一组条件匹配每一行,否则它只匹配那些包含指定名字的行。对于第二组标准也是如此。您可以根据需要对任意多组条件执行相同的操作,将参数与 NULL 或列与参数进行比较。

需要注意的一点是,我在上面的示例中为四个条件使用了两个参数。这是可能的,因为SqlClient 支持真正的命名参数。对于不支持真正命名参数的提供程序,例如OleDb 的 Jet 或 ACE,你实际上需要添加两倍的参数,因为你不能在 SQL 代码中两次使用相同的参数,例如

Dim query = "SELECT * FROM Person WHERE (@FirstName1 IS NULL OR FirstName = @FirstName2) AND (@LastName1 IS NULL OR LastName = @LastName2)"
Dim command As New OleDbCommand

command.CommandText = query

Dim firstName = If(firstNameTextBox.TextLength = 0, CObj(DBNull.Value), firstNameTextBox.Text)
Dim lastName = If(lastNameTextBox.TextLength = 0, CObj(DBNull.Value), lastNameTextBox.Text)

With command.Parameters
    .Add("@FirstName1", SqlDbType.VarChar, 50).Value = firstName
    .Add("@FirstName2", SqlDbType.VarChar, 50).Value = firstName
    .Add("@LastName1", SqlDbType.VarChar, 50).Value = lastName
    .Add("@LastName2", SqlDbType.VarChar, 50).Value = lastName
End With

【讨论】:

唯一的麻烦是不同的情况很可能有不同的最优计划。使用这种方法,优化器可能会根据第一个参数选择一个计划并坚持下去。通过根据原始提供的参数创建 SQL,您可以在每种情况下获得一个计划,这几乎肯定会更好。

以上是关于带有 VB.net 变量字符串条件的动态 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询字符串在 SQL Server Management Studio 中有效,但在带有 SQLCommand.ExecuteReader 的 VB.net 中无效

带有 if 语句的 SQL 参数 vb.net

使用带有 ADO 的 Excel 2010 VBA(或带有 LINQ 的 vb.net)查询表的最佳 SQL 语句是啥

vb.net SQL 导致 - “必须声明标量变量”

使用 vb.net 根据 SQL 数据库中存在的记录动态显示/隐藏 DataGrid 按钮列时遇到问题

VB.NET 无法更新 datagridview 中的 SQL 数据