从多个连接的字符串创建参数化 MySQL 查询

Creating a parameterised MySQL query from multiple concatenated strings

我打算做的是创建一些函数,这将帮助我创建大量 MySqlCommand。但我错了(下面提供的信息)。

背景

我是通过在class中定义常量实现的,例如:

Public Const Create_Table = "CREATE TABLE IF NOT EXISTS `@arg0` (@arg1)"

诸如此类的字符串构成了我的参数化查询的基础。现在,这些参数不是单个值,它们实际上是串联的字符串。所以我知道我正在接近这里的危险水域,所以请耐心等待。

我使用以下函数连接参数:

Public Shared Function ListToQuery(values As List(Of String),
                                   Optional ByVal separator As String = ", ") As String
    Dim queryBuilder As New StringBuilder

    For Each value As String In values
        queryBuilder.Append((value) & separator)
    Next
    Dim query As String = queryBuilder.ToString
    Return query.Remove(query.Length - 2)
End Function

一切正常;当我用列表调用它时:

Dim myValues As New List(Of String)
myValues.AddRange({"Int Primary", "Text Name"})
MsgBox(ListToQuery(myValues))

它 returns "Int Primary, Text Name" - 完全正常。 然而,这就是事情开始出错的地方。

我的下一部分是基于几个参数创建 MySqlCommand,一个 String 数组。这是通过调用以下函数实现的:

Public Shared Function BuildCommand(args() As String, Command As String, connection As MySqlConnection) As MySqlCommand

    Dim cmd As New MySqlCommand(Command, connection)
    For i As Integer = 0 To args.Length - 1
        'cmd.CommandText = cmd.CommandText.Replace("@arg" & i, args(i))
        cmd.Parameters.AddWithValue("@arg" & i, MySqlHelper.EscapeString(args(i)))
    Next
    Return cmd

End Function

问题

我这样调用这个函数:

Dim myCommand as MySqlCommand = BuildCommand({"MyTableName", ListToQuery(myValues)}, Create_Table, myConnection)
Dim dr = myCommand.ExecuteReader()

似乎发生了什么,这是发生了错误,我发现了一些似乎在参数化查询中发生的事情:

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Int Primary, Text Name')' at line 1

如果我正确解释此错误,则该参数似乎已封装在 ' 中。现在请注意我的代码中 BuildCommand() 的注释。如果我要使用纯串联,该查询将 运行 就好了。

编辑:结果查询应该是:

CREATE TABLE IF NOT EXISTS `MyTableName` (Int Primary, Text Name)

问题

事实上,我有一对。首先,我想问一下这是否是一种安全的方式(即即使连接我的参数并在查询中使用参数)到 运行 一个命令,其次,我怎样才能避免出现这个错误?

我不太确定我是否可以在不导致查询变为 'unsafe' 或不修改一般 MySQL 语句的情况下单独解析每个参数。

我一直在与另一位用户讨论这个问题,他设法找到了这个问题:Parameterized dynamic sql query。这是在问一个类似的问题。但是,这与我遇到的问题不同。

提前致谢。

此函数生成一个 CREATE TABLE 命令。我多次遇到同样的问题,但直到现在我都没有找到合适的解决方案。相反,我自己创建查询:

    Public Shared Function BuildCommand(args() As String, connection As MySqlConnection) As MySqlCommand
    Dim sb As New StringBuilder
    Dim cmd As New MySqlCommand
    cmd.Connection = connection
    sb.Append("CREATE TABLE IF NOT EXISTS`")
    sb.Append(args(0))
    sb.Append("`(")
    For i As Integer = 1 To args.Length - 1
        sb.Append("`")
        sb.Append(args(i))
        sb.Append("`,")
    Next
    sb.Remove(sb.Length - 1, 1)
    sb.Append(")")
    cmd.CommandText = sb.ToString
    Return cmd
End Function

此代码与您之前给我看的代码不同,但现在我看到了您所做的更改以及您在什么情况下使用这些代码,事情就变得容易多了。

添加 SQL 参数时,您不需要转义它们的值,因为这是自动完成的。这可能就是为什么你会经历它被两次逃脱的原因。

变化:

cmd.Parameters.AddWithValue("@arg" & i, MySqlHelper.EscapeString(args(i)))

至:

cmd.Parameters.AddWithValue("@arg" & i, args(i))

...它应该可以工作(而且是安全的)!