错误`你必须声明标量变量“@ ....”`

时间:2014-04-29 17:25:04

标签: sql-server vb.net

我创建了一个执行我的数据的功能

Public Function Excuter(ByVal Query As String)
    If cn.State = ConnectionState.Open Then cn.Close()

    cn.Open()
    Try

        cmd.CommandText = (Query)
        cmd.ExecuteNonQuery()
        cn.Close()
    Catch ex As Exception

        cn.Close()
        MsgBox(ex.ToString())

    End Try

End Function

这是我的插入代码

Excuter("INSERT INTO Table_PatientDetail (Patient_ID , Patient_Name , Age,Sex , Phone_Number , Address, Check_In_ID, Check_Out_ID , Service , Transfer , Patient_Result ) VALUES (@Patient_ID , @Patient_Name , @Age, @Sex , @Phone_Number , @Address, @Check_In_ID , @Check_Out_ID , @Service , @Transfer , @Patient_Result)")
cmd.Parameters.AddWithValue("@Patient_ID", .PatientIDPatientInformation.Text)
cmd.Parameters.AddWithValue("@Patient_Name", .PatientNamePatientInformation.Text)
cmd.Parameters.AddWithValue("@Age", .AgePatientInformation.Text)
cmd.Parameters.AddWithValue("@Sex", .ComboBox1.Text)
cmd.Parameters.AddWithValue("@Phone_Number", .PhoneNumPatientInformation.Text)
cmd.Parameters.AddWithValue("@Address", .AddressPatientInformation.Text)
cmd.Parameters.AddWithValue("@Check_In_ID", .CIID.Text)
cmd.Parameters.AddWithValue("@Check_Out_ID", .COID.Text)
cmd.Parameters.AddWithValue("@Service", .Cboservice.SelectedValue)
cmd.Parameters.AddWithValue("@Transfer", .TransferPatientInformation.Text)
cmd.Parameters.AddWithValue("@Patient_Result", .ComboBox3.Text)

当我测试它时,它会显示此错误Must Declare Scalar Variable"@Patient_Name";我不明白。

2 个答案:

答案 0 :(得分:4)

问题是您的Excuter函数会在您将参数实际添加到cmd对象之前获取查询字符串并执行它。一个快速而肮脏的解决方案是在调用Parameters之前简单地填充Excuter集合,如下所示:

cmd.Parameters.Clear() 'Remove any parameters left over from the previous call
cmd.Parameters.AddWithValue("@Patient_ID", .PatientIDPatientInformation.Text)
cmd.Parameters.AddWithValue("@Patient_Name", .PatientNamePatientInformation.Text)
cmd.Parameters.AddWithValue("@Age", .AgePatientInformation.Text)
cmd.Parameters.AddWithValue("@Sex", .ComboBox1.Text)
cmd.Parameters.AddWithValue("@Phone_Number", .PhoneNumPatientInformation.Text)
cmd.Parameters.AddWithValue("@Address", .AddressPatientInformation.Text)
cmd.Parameters.AddWithValue("@Check_In_ID", .CIID.Text)
cmd.Parameters.AddWithValue("@Check_Out_ID", .COID.Text)
cmd.Parameters.AddWithValue("@Service", .Cboservice.SelectedValue)
cmd.Parameters.AddWithValue("@Transfer", .TransferPatientInformation.Text)
cmd.Parameters.AddWithValue("@Patient_Result", .ComboBox3.Text)
Excuter("INSERT INTO Table_PatientDetail (Patient_ID , Patient_Name , Age,Sex , Phone_Number , Address, Check_In_ID, Check_Out_ID , Service , Transfer , Patient_Result ) VALUES (@Patient_ID , @Patient_Name , @Age, @Sex , @Phone_Number , @Address, @Check_In_ID , @Check_Out_ID , @Service , @Transfer , @Patient_Result)")

但是,因为此代码在多个调用中重用连接和命令,所以它看起来非常脆弱。例如,您每次调用时都必须记得清除Parameters集合,否则您最终会遇到非常奇怪的错误。我建议重构您的代码,以便每个数据库调用更加自包含。

答案 1 :(得分:1)

您正在调用执行查询的Executer,并且在执行查询后添加参数;但是,这太迟了。您必须在cmd.Parameters.AddWith(...)之前致电cmd.ExecuteNonQuery()

ParamArray Sub添加Executer参数,允许您将可变数量的参数传递给查询。由于您无法轻松地同时传递参数名称,只需将参数命名为@0@1@2,...

Public Sub Executer(query As String, ParamArray parameters As Object())
    Using cn = New SqlConnection(ConnectionString)
        Using cmd = New SqlCommand(query, cn)
            For i As Integer = 0 To parameters.Length - 1
                cmd.Parameters.AddWithValue("@" & i, parameters(i))
            Next
            cn.Open()
            Try
                cmd.ExecuteNonQuery()
            Catch ex As Exception
                Interaction.MsgBox(ex.ToString())
            End Try
        End Using
    End Using
End Sub

请注意Using语句会自动关闭连接。即使发生异常,它也会这样做。另请注意,我已在本地向该方法声明了连接和命令对象。这样,您就不必在多个电话中跟踪其状态。

现在你可以像这样调用执行者(我稍微缩短了查询):

Const InsertPatientDetailSql As String = _
    "INSERT INTO Table_PatientDetail (ID, Name, Age) VALUES (@0, @1, @2)"
Executer(InsertPatientDetailSql, 42, "John Doe", 35)

与您的方法相比,这是Executer使用的真正简化。