使用列名参数时无法选择值

时间:2013-05-07 12:26:00

标签: sql vb.net parameterized-query

Try
    Using connection As New SqlConnection(ConnectionString)
        connection.Open()
        SQL = "SELECT @PARAM FROM SystemOps"
        sqlCmd = New SqlClient.SqlCommand(SQL, connection)
        sqlCmd.Parameters.Add(New SqlClient.SqlParameter("@PARAM", SqlDbType.VarChar)).Value = "SystemNavn"
        ' .. and so on...

当我运行代码时,它返回的结果为"SystemNavn"(这是表中列的名称),而不是当前行中该列的值。我做错了什么?

3 个答案:

答案 0 :(得分:2)

您不能将参数名称用于列名或任何其他SQL语法。您只能将参数用作文字值的占位符。参数总是被替换为值的文字形式,因此在您的示例中,正在运行的命令基本上被评估为:

SELECT 'SystemNavn` FROM SystemOps

为了拥有一个变量列名,我建议动态构建SQL字符串,如下所示:

Dim columnName As String = "SystemNavn"
SQL = "SELECT [" & columnName & "] FROM SystemOps"

但是,通过这样做,您可能会遇到潜在的SQL注入攻击,因此您需要小心。我知道,在这种情况下避免攻击的最安全的方法是从数据库中获取列名列表,并将columnName变量与该列表进行比较,以确保它实际上是有效的列名。

当然,如果列名永远不会改变,那么就没有理由让它成为变量。在这种情况下,只需将其直接硬编码到SQL命令中,从而避免使用参数或变量:

SQL = "SELECT SystemNavn FROM SystemOps"

答案 1 :(得分:1)

在这种情况下,您的查询不需要任何参数。只是做

SQL = "SELECT SystemNavn FROM SystemOps"  

这是安全的。如果以后需要对此进行过滤,则可以执行以下操作:

SQL = "SELECT SystemNavn FROM SystemOps WHERE COL_A = @ColA"

仅供参考,对于上面的代码,因为它是VARCHAR类型,所以它的执行方式如下:

SELECT 'SystemNavn' FROM SystemOps

这就是为什么你要'SystemNavn'回来了。

答案 2 :(得分:0)

您不能使用参数指定列或表的名称。

参数集合用于指定要搜索,插入,更新或删除的值。

您的代码应更改为此类

    Using connection As New SqlConnection(ConnectionString)
        connection.Open()
        SQL = "SELECT SystemNavn, <other fiels if needed> " & _
              "FROM SystemOps WHERE <keyfield_name> = @PARAM"
        sqlCmd = New SqlClient.SqlCommand(SQL, connection)
        sqlCmd.Parameters.AddWithValue("@PARAM", paramValue)
        ......
    End Using

当然上面的例子假设您有一个WHERE子句,如果您想要无条件地检索SystemNavn列的每个值,那么您不需要参数化查询,因为您的sql命令的每个部分都是由您提供的并且不用担心sql注入。