【问题标题】:Unable to INSERT data using a SELECT statement无法使用 SELECT 语句插入数据
【发布时间】:2019-04-27 08:21:54
【问题描述】:

我有两张桌子; Studentpromote_student。我想将数据从Student 复制到promote_student

为了这个任务,我写了这个查询:

str = "INSERT INTO [promote_student] 
            SELECT * 
            FROM [Student] 
            WHERE [SrNo] = " & row.Cells("sr_no").Value & " 
              AND [session] = " & from_session.Text & ""

cmd = New OleDb.OleDbCommand(str, cn)
da.SelectCommand = cmd
da.Fill(ds, "promote_student")

这里sr_no 是唯一值,from_session 是“2018-2019”,但此查询没有复制任何内容。我也没有收到任何错误。

【问题讨论】:

    标签: sql vb.net ms-access


    【解决方案1】:

    在此查询中,如果不是您的查询给出错误运行时,您的promote_student 表列和Student 表列需要相同。并且请不要连接您的 SQL 查询,使用参数来保护 Sql 注入。你的查询看起来像:

      str = "INSERT INTO [promote_student] SELECT * FROM [Student] WHERE [SrNo]=@sr and [session]=@session"; 
    
                    cmd.Parameters.AddWithValue("@sr",row.Cells("sr_no").Value)
                    cmd.Parameters.AddWithValue("@session",row.Cells("sr_no").Value)
                    cmd = New OleDb.OleDbCommand(str, cn)
                    da.SelectCommand = cmd
                    da.Fill(ds, "promote_student")
    

    【讨论】:

    • 还应该注意他使用的是字符串值,并且在原始查询中它们没有被引号正确包围。在您的答案中使用绑定参数自然固定
    • 由于 MS Access 使用的是 OleDB(而不是 SQL Server 的本机客户端),它不支持 named 参数,如 @sr@session。 OleDB 仅支持 位置 参数,这意味着参数在查询文本中定义的顺序,以及它们添加到 OleDbCommand 的顺序必须相同 - 名称 的参数不相关.....您可以在查询文本中轻松使用WHERE [SrNo] = ? AND [Session] = ?,然后在指定参数时使用@p1@p2
    • 收到此错误 System.Data.OleDb.OleDbException: 'No value given for a or more required parameters.'在线 da.Fill(ds, "promote_student") 但已经有值
    • 您将要移动 cmd = New OleDb.OleDbCommand(str,cn) 之后的两个参数行,它们被分配给前一个 OleDbCommand,然后创建一个新参数行并将其传递给 OleDbDataAdapter没有定义参数。
    【解决方案2】:

    如果你想插入数据,你应该调用cmd.ExecuteNonQuery()

    我也不相信SELECT * FROM [Student] 是插入数据的最佳方式,尤其是在您有主键的情况下。相反,您希望使用要从中选择的列来指定要插入的列。

    我强烈考虑使用参数来避免 SQL 注入。有关这方面的更多信息,请参阅Bobby Tables。我使用? 作为参数的占位符。对于OleDbCommand,重要的是要注意不是参数的名称,而是声明它们的顺序很重要。我指定了数据类型,因此请考虑使用OleDbParameter Constructor (String, OleDbType) 添加您的参数。

    最后,我也会考虑实现Using

    托管资源由 .NET Framework 垃圾收集器 (GC) 处理,无需您进行任何额外编码。托管资源不需要 Using 块。但是,您仍然可以使用 Using 块来强制处置托管资源,而不是等待垃圾收集器。

    这是一些示例代码:

    Using con As OleDbConnection = cn,
          cmd As New OleDbCommand("INSERT INTO [promote_student] (column1, column2, column3) SELECT column1, column2, column3 FROM [Student] WHERE [SrNo] = ? AND [session] = ?", con)
            con.Open()
    
            cmd.Parameters.Add("@srNo", OleDbType.[Type]).Value = row.Cells("sr_no").Value
            cmd.Parameters.Add("@session", OleDbType.[Type]).Value = from_session.Text
    
            cmd.ExecuteNonQuery()
    End Using
    

    请注意,我不知道您的表结构,因此提供了一个示例。您将不得不更改列名以适合

    还要注意我使用了OleDbType.[Type]。您需要将 [Type] 替换为您在数据库中使用的数据类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      相关资源
      最近更新 更多