【问题标题】:Vb.NET MS Access SQL UPDATE Syntax IssueVb.NET MS Access SQL UPDATE 语法问题
【发布时间】:2016-12-26 06:29:06
【问题描述】:

我已经为此苦苦琢磨了好几个小时,但还没有做好,所以我决定发帖。

我的 Vb.NET 应用程序在硬盘上有 2 张 Jpg。一个是LowRes,另一个是HighRes。我想通过INSERT 将两张图片保存在Microsoft Access 2007 数据库中的同一记录中,这工作正常,然后UPDATE 添加第二张。 UPDATE 不起作用。

我拼凑了一堆我在网上找到的INSERT 代码(边走边学),最终找到了一些真正有效的方法。然而,尝试调整函数以执行更新以添加第二张图片被证明是困难的。我怀疑这与我指定参数错误有关?

数据库有 1 个表 Records 和 3 列 RecordID(这是文本,以及从 Form1.Tb_RecordID.Text 提取的自动编号主键)、HighRes(这是 OLE)和 LowRes(其中也是 OLE)。该数据库名为Database.accdb

我调用子程序:

Save_To_Database("LowProfile.jpg", "LowRes")

如果我想要INSERT "LowRes" 列中的 OLE 图像。然后我打电话给

Update_To_Database("HighProfile.jpg", "HighRes")

HighRes 图片更新记录。我最终希望一对一地整合这些函数,并使用 ByVals 来确定它是应该更新还是插入。

这很好用:

Sub Save_To_Database(ByVal Filename As String, ByVal Res As String)

    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb"
    Dim theQuery As String = "INSERT INTO Records([RecordID],[" & Res & "]) values (" & Form1.Tb_RecordID.Text & ", @Img)"

    Try
        Dim fs As FileStream
        fs = New FileStream(Filename, FileMode.Open, FileAccess.Read)
        Dim picByte As Byte() = New Byte(fs.Length - 1) {}
        fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length))
        fs.Close()
        Dim CN As New OleDbConnection(cnString)
        CN.Open()
        Dim imgParam As New OleDbParameter()
        imgParam.OleDbType = OleDbType.Binary
        imgParam.ParameterName = "Img"
        imgParam.Value = picByte
        Dim cmd As New OleDbCommand(theQuery, CN)
        cmd.Parameters.Add(imgParam)
        cmd.ExecuteNonQuery()
        MessageBox.Show("Image successfully saved.")
        cmd.Dispose()
        CN.Close()
        CN.Dispose()
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try

End Sub

但是,我的UPDATE 代码失败,SQL 语句出现语法错误:

Sub Update_To_Database(ByVal Filename As String, ByVal Res As String)

    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb"
    Dim theQuery As String = "UPDATE Records SET ([" & Res & "]) values (@Img) WHERE RecordID =" & Form1.Tb_RecordID.Text

    MsgBox(theQuery)

    Try
        Dim fs As FileStream
        fs = New FileStream(Filename, FileMode.Open, FileAccess.Read)
        Dim picByte As Byte() = New Byte(fs.Length - 1) {}
        fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length))
        fs.Close()
        Dim CN As New OleDbConnection(cnString)
        CN.Open()
        Dim imgParam As New OleDbParameter()
        imgParam.OleDbType = OleDbType.Binary
        imgParam.ParameterName = "Img"
        imgParam.Value = picByte
        Dim cmd As New OleDbCommand(theQuery, CN)
        cmd.Parameters.Add(imgParam)
        cmd.ExecuteNonQuery()
        MessageBox.Show("Image successfully saved.")
        cmd.Dispose()
        CN.Close()
        CN.Dispose()
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try

End Sub

有人看到问题了吗?或者改进代码的方法?

【问题讨论】:

  • 使用类似UPDATE Records SET ([" & Res & "]) = @Img WHERE
  • 我找到了这个线程:Tinyurl.com/hkjwtwz 并且非常喜欢他如何构建他的 SQL,甚至它如何检查记录是否存在。我试图修改它来做类似的事情,但我不知道如何处理 imgParam 或 fs。
  • 还有阿拜。它仍然抛出语法错误。我做了一个 Msgbox 来查看字符串,它说:“UPDATE Records SET ([HighRes]) = @img WHERE RecordID =1”,如果有帮助的话。
  • SQL Injection alert - 您应该将您的 SQL 语句连接在一起 - 使用 参数化查询 来避免 SQL 注入
  • 尝试去掉 [HighRes]: 周围的括号。 UPDATE Records SET [HighRes] = @Img ....

标签: sql vb.net ms-access


【解决方案1】:

您最初的问题是您尝试使用插入语句的语法编写更新语句。一个简单的解决方法是将更新语句更改为正确的语法。

但是,您的代码中有很多东西可以并且应该被更改,所以我根据您的代码编写了一个仍然可以进一步改进的示例:

Sub Save_To_Database(ByVal Filename As String, ByVal RecordId As String, ByVal IsHighResolution As Boolean, ByVal IsNew As Boolean)

    Dim theQuery As String
    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb"

    If IsNew Then
        theQuery = "INSERT INTO Records([RecordID],[" & IIf(IsHighResolution, "HighRes", "LowRes") & "]) values (@RecordId, @Img)"
    Else
        theQuery = "UPDATE Records SET " & IIf(IsHighResolution, "HighRes", "LowRes") & " = @Img WHERE RecordID = @RecordId"
    End If

    Try
        Using fs As New FileStream(Filename, FileMode.Open, FileAccess.Read)
            Dim picByte As Byte() = New Byte(fs.Length - 1) {}
            fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length))
            Using CN As New OleDbConnection(ConnectionString)

                Dim cmd As New OleDbCommand(theQuery, CN)
                cmd.Parameters.Add("Img", OleDbType.Binary).Value = picByte
                cmd.Parameters.Add("@RecordId", OleDbType.Integer).Value = RecordId

                CN.Open()
                cmd.ExecuteNonQuery()
                MessageBox.Show("Image successfully saved.")
            End Using
        End Using

    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try

End Sub

兴趣点:

  1. 插入和更新现在由相同的方法处理,唯一的区别是布尔参数指定这是新记录还是现有记录。

  2. 现在查询不受 sql 注入的影响。这里唯一的连接是你不能在 sql 中参数化的列名,但它是在 sub 本身内部决定的。当你使用 sub 时,你只传递一个布尔值,表明这是一个高分辨率图像。

  3. 建议在您使用任何实现 IDisposable 接口的东西时使用 Using 块。即使在抛出异常的情况下,这也可以确保正确关闭和处理。

  4. 参数代码简化。

【讨论】:

  • 您在我想到的一些改进方面击败了我,例如包括 byVals 和查询的 If 语句以及将记录 ID 设置为参数。我从不知道 IIF,我会记下它。它看起来也好多了。仍然没有掌握使用的窍门。我明天测试一下。下一个项目是弄清楚如何阅读并填充适当的图片框。
  • 好的,所以我试了一下,它在 INSERT 语句上抛出了一个错误,但说 UPDATE 语句是成功的,即使没有记录/信息写入数据库。它成功地没有更新任何东西。我给出了错误:“标准表达式中的数据类型不匹配。”我尝试了旧的 concatenate INSERT 语句,它工作正常,这让我认为 @RecordId 参数有问题。当我调用 sub 时,我 CInt 记录 ID,我将 ByVal 更改为整数,它仍然给出错误。我错过了一些东西。
  • 此外,RecordID 是由自动编号序列创建的,并且是从禁用和只读字段中读取的,我怀疑它可能/将容易受到任何类型的 SQL 注入的攻击......但仍然。
  • 你能发布你的表的创建语句吗?
  • 表是在 Access 中预先创建的。这两个字段都是 OLE 字段,我检查了。
猜你喜欢
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
相关资源
最近更新 更多