【问题标题】:SQL output as variable in VB.netSQL 输出为 VB.net 中的变量
【发布时间】:2013-10-15 14:48:02
【问题描述】:

我似乎无法弄清楚如何在 VB 中将 SQL 查询的输出作为变量。我需要类似下面的内容,以便可以在另一个 SQL 查询中使用该变量。 SQL 不允许在运行查询时使用变量作为列标题,所以我想我可以使用 VB 将一个 SQL 任务的实际输出作为动态变量插入到更新查询的循环中。让我(希望)解释一下。

我有以下疑问:

DECLARE @id int = (SELECT max(id) FROM [views]), @ViewType nvarchar(3);

WHILE @id IS NOT NULL
BEGIN

    SELECT @ViewType = (SELECT [View] FROM [views] WHERE id = @id);

    UPDATE a
    SET a.[@ViewType] = '1'
    FROM [summary] a
    INNER JOIN [TeamImage] b
    ON a.[Part_Number] = b.[PartNum]

    WHERE b.[View] = @ViewType;

SELECT @id = max(id) FROM [views] WHERE id < @id;

END;

SET a.[@ViewType] = '1' 显然在 SQL 中不起作用。但是如果我可以让 (SELECT [View] FROM [views] WHERE id = @id) 等于一个变量,那么我可以在 VB 中编写 SQL 查询并执行它,该变量将成为字符串的一部分并因此执行正确。

我是 VB 的新手,但到目前为止,这是我所掌握的:

Dim cn As SqlConnection = New SqlConnection("Data Source=Server1;" & _
                                                 "Initial Catalog=DB1;" & _
                                                 "Integrated Security=SSPI")
cn.Open()

Dim cmd As New sqlCommand("SELECT max(id) FROM orientation_view_experiment;", cn)
vID = cmd.ExecuteNonQuery()

Do While vID > 0
    Dim cmd2 As New sqlCommand("SELECT [View] FROM [views] WHERE id ='" + vID + "'"
    vViewType = cmd2.ExecuteNonQuery()

    Dim cmd3 As New sqlCommand("UPDATE a
    SET a.'" + vViewType + "' = '1' & _
    FROM [summary] a & _
    INNER JOIN [TeamImage] b & _
    ON a.[Part_Number] = b.[PartNum] & _

    WHERE b.[View] = '" + vViewType + "';"
    cmd3.ExecuteNonQuery()
vID = vID - 1
Loop

cn.Close()

我希望其中一些有意义,但在这一点上我有点迷失了。我觉得我知道我需要 SQL 来做什么,但不能完全弄清楚如何让计算机/程序服从我的意愿,只做我需要它做的事情。

感谢您提供的任何帮助/指导。

【问题讨论】:

  • 该代码将容易受到 sql 注入攻击。它实际上是在乞求被黑。

标签: sql vb.net variables


【解决方案1】:

您的代码是错误的,因为您坚持将ExecuteNonQuery 用于SELECT 语句。 ExecuteNonQuery 不返回选择的行,而只返回受 INSERT/DELETE/UPDATE 查询影响的行数(我认为对于 SELECT,它总是返回零)

您需要ExecuteScalar 来获取 MAX 值和 VIEW 值,因为当您希望从 SQL 语句中仅获取第一行的第一个字段时,ExecuteScalar 是最佳选择

Dim cmd As New sqlCommand("SELECT max(id) FROM orientation_view_experiment;", cn)
vID = Convert.ToInt32(cmd.ExecuteScalar())

Do While vID > 0
    Dim cmd2 As New sqlCommand("SELECT [View] FROM [views] WHERE id =" + vID.ToString()
    Dim result = cmd2.ExecuteScalar()
    if Not string.IsNullOrEmpty(result)) Then
       vViewType = result.ToString()

       Dim cmd3 As New sqlCommand("UPDATE a SET a.[" + vViewType + "] = '1' " & _
                                  "FROM [summary] a " & _
                                  "INNER JOIN [TeamImage] b " & _
                                  "ON a.[Part_Number] = b.[PartNum] " & _
                                  "WHERE b.[View] = @vType"
       cmd3.Parameters.AddWithValue("@vType", vViewType)
       cmd3.ExecuteNonQuery()
    End If
Loop

您的代码的最后一部分对我来说不是很清楚,但是您可以在表summary 中的列名周围使用几个方括号,并为表TeamImage 中的视图字段使用一个参数。

作为最后的建议,请确保您的最终用户不能直接修改表 TeamImage 中的 View 列,因为这样的字符串连接可能会导致 Sql Injection 攻击

【讨论】:

  • Steve,非常感谢您花时间编辑脚本以反映 ExecuteScalar 的使用。我需要解决这个问题,因为我不确定你为什么在最后使用 Parameter 部分,而我们在 SET 部分不需要它,但我可以阅读。此外,View 列不可直接修改,因为我们在导入数据时运行验证。
  • 如果 vViewType 包含 SQL 中不允许的引号或空格或其他字符,则该参数会有所帮助。使用参数是在 sql 命令中传递任何类型值的最佳实践。太糟糕了,参数不能用于列名。在 SET 之前不存在 Sql Injection 或解析问题的风险,因为我们肯定会处理整数数值MAX(ID)
【解决方案2】:

command 的不同方法进行一些研究。当您调用ExecuteNonQuery 时,这将返回受影响的记录数。我认为您希望 ExecuteScalar 作为您的 cmdcmd2 方法,因此您可以从数据库中获取值。

【讨论】:

    【解决方案3】:

    您是否尝试将 '" + vViewType + "' 替换为 [" + vViewType + "] ... 换句话说,使用方括号来分隔列名而不是用于分隔字符串文字的单引号?

    另外,我鼓励在调试器中停下来,检查您在 cmd3 中生成的命令并尝试直接执行它。它可能会帮助您识别其他类似的问题,例如 vViewType 为您提供记录计数而不是 [View] 列中的实际值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-02
      • 2011-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 2012-01-13
      相关资源
      最近更新 更多