SQLite 错误 20:数据库插入中的数据类型不匹配

SQLite Error 20: Datatype mismatch in database insertion

我正在制作一个 POS 样式系统,这是我用于存储活动订单数据并将数据输入数据库的代码。这应该一切正常,但是我在“Push”IF 语句中的 cmd.ExecuteNonQuery() 上收到错误。

它给我一个 SQLite 错误 20:数据类型不匹配。

为什么?

TIA

Imports Microsoft.Data.Sqlite
Public Class CurrentOrder
    Public Shared OrderID As Integer
    Public Shared Items As New ArrayList
    Public Shared ItemsString As String
    Public Shared CustName As String
    Public Shared Table As Integer
    Public Shared Cost As Double 'How much the restaurant will have to pay to make the meal
    Public Shared Price As Double 'How much the customer will pay for this order

    Public Shared Sub Database(ByVal Mode As String)
        Dim Connection As New SqliteConnection("Data Source = Database.db")
        Dim SQLcommand As String
        Dim CMD As New SqliteCommand
        'ItemsString = ""

        If Items.Count = 0 Then
            MessageBox.Show("Please add items to order", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Exit Sub
        End If

        If Mode = "Push" Then
            For i = 0 To Items.Count - 1
                ItemsString = ItemsString + Items(i) 'Concatatanation to take a list to a string
            Next
            Order.Label3.Text = ItemsString
            SQLcommand = "INSERT INTO Orders VALUES ('@OrderID', '@ItemsString', '@CustName', '@Table', '@Cost', '@Price')" 'SQL Push Statement

            Try
                CMD.Connection = Connection
                Connection.Open()
                CMD.CommandText = SQLcommand
                CMD.ExecuteNonQuery() 'Error 20: Datatype mismatch
                Connection.Close()
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try



        ElseIf Mode = "Pull" Then

            SQLcommand = ("SELECT * FROM Orders WHERE OrderID = " & OrderID) 'SQL Pull Statement

            Try
                CMD.Connection = Connection
                Connection.Open()
                CMD.CommandText = SQLcommand
                Dim reader As SqliteDataReader = CMD.ExecuteReader()
                While reader.Read()
                    Order.Label3.Text = reader("ItemID") & ", " & reader("Name") & ", " & reader("Price")
                End While
                reader.Close()
                Connection.Close()
            Catch e As Exception
                MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End If


    End Sub
End Class

在 table 中,您有不同的数据类型,并且您正在发送不同的数据类型。例如,在 table 中,您使用 Int 并传递 decimal.

在处理金钱时,最好使用 Decimal 而不是 Double

我不知道为什么这个 class 有所有这些 Shared 项。在调用代码中创建一个实例可能会更好。

ArrayList 不应在新代码中使用。看看 List(Of T) 是否会填满账单。

字段在 Classe 中通常 Public。您希望 Property 成为 Public.

Class像这样的没有用户界面。您不想显示 class 中的消息框。在表单 Class.

中显示来自用户界面代码的消息框

不要在数据库的单个字段中存储多个项目。你应该有一个 Orders table 主键 OrderID 和一个 OrderDetails table 的项目。

您的 for 循环只是将所有项目集中在一起。如果没有任何分隔符,您将无法再次将它们分开。此外,vb.net 中的串联运算符是 &.

对于插入语句,通常最好列出字段名称,然后列出值。我不知道你为什么用单引号将参数名称括起来。

您可以将 CommandTextConnection 直接传递给命令的构造函数。

您在插入中引用了多个参数,但从未将它们添加到参数集合中或为它们设置值。

显然,您为 OrderID 提供了唯一值,这不是自动编号字段。

使用 Sub New 将您的订单对象置于 stable 状态,准备好将其数据添加到数据库中。

Public Class CurrentOrder
    Public Property OrderID As Integer
    Public Property Items As New List(Of String)
    Public Property CustName As String
    Public Property Table As Integer
    Public Property Cost As Decimal 'How much the restaurant will have to pay to make the meal
    Public Property Price As Decimal 'How much the customer will pay for this order

    Public Sub New(ID As Integer, Itms As List(Of String), Name As String, TBL As Integer, Cst As Decimal, Prc As Decimal)
        OrderID = ID
        Items = Itms
        CustName = Name
        Table = TBL
        Cost = Cst
        Price = Prc
    End Sub
End Class

CurrentOrder class 与 DataAccess class 完全分开。

Public Class DataAccess

    Private ConStr As String = "Data Source = Database.db"

    Public Sub SaveOrderAndDetails(O As CurrentOrder)
        Dim OrderInsert = "INSERT INTO Orders (OrderID, CustName, Table, Cost, Price) VALUES (@OrderID, @CustName, @Table, @Cost, @Price)"
        Using Connection As New SQLiteConnection(ConStr)
            Using CMD As New SQLiteCommand(OrderInsert, Connection)
                CMD.Parameters.Add("@OrderID", DbType.Int32).Value = O.OrderID
                CMD.Parameters.Add("@CustName", DbType.String).Value = O.CustName
                CMD.Parameters.Add("@Table", DbType.Int32).Value = O.Table
                CMD.Parameters.Add("@Cost", DbType.Decimal).Value = O.Cost
                CMD.Parameters.Add("@Price", DbType.Decimal).Value = O.Price
                Connection.Open()
                CMD.ExecuteNonQuery()
            End Using
            Dim DetailsInsert = "Insert Into OrderDetails (OrderID, Item) Values (@OrderId, @Item)"
            Using cmd As New SQLiteCommand(DetailsInsert, Connection)
                cmd.Parameters.Add("@OrderId", DbType.Int32).Value = O.OrderID
                cmd.Parameters.Add("@Item", DbType.String)
                For Each s In O.Items
                    cmd.Parameters("@Item").Value = s
                    cmd.ExecuteNonQuery()
                Next
            End Using
        End Using
    End Sub

    Public Function GetOrderByID(id As Integer) As DataTable
        Dim dt As New DataTable
        Dim SqlCommand = "SELECT * FROM Orders WHERE OrderID = @ID"
        Using cn As New SQLiteConnection(ConStr),
                cmd As New SQLiteCommand(SqlCommand, cn)
            cmd.Parameters.Add("@ID", DbType.Int32).Value = id
            cn.Open()
            Using reader = cmd.ExecuteReader
                dt.Load(reader)
            End Using
        End Using
        Return dt
    End Function

    Public Function GetOrderDetailByID(id As Integer) As DataTable
        Dim dt As New DataTable
        Dim sql = "Select Item From OrderDetails Where OrderID = @ID"
        Using cn As New SQLiteConnection(ConStr),
                cmd As New SQLiteCommand(sql, cn)
            cmd.Parameters.Add("@ID", DbType.Int32).Value = id
            cn.Open()
            Using reader = cmd.ExecuteReader
                dt.Load(reader)
            End Using
        End Using
        Return dt
    End Function
End Class

最后,在用户界面中使用 classes,在本例中为 windows 表单。

Private Sub Button1_Click() Handles Button1.Click
    Dim lst As New List(Of String)
    lst.Add("Bacon")
    lst.Add("Eggs")
    Dim newOrder As New CurrentOrder(7, lst, "John", 4, 12.03D, 22D)
    Dim DA As New DataAccess
    DA.SaveOrderAndDetails(newOrder)
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim DA As New DataAccess
    Dim dt = DA.GetOrderByID(7)
    'Fill various text boxes with the DataTable fields
    Dim dt2 = DA.GetOrderDetailByID(7)
    DataGridView1.DataSource = dt2
End Sub