2014-04-29 31 views
0

我创建了一个功能,用于执行我的数据错误`您必须声明标量变量“@ ....”'

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";我不明白。

+0

你认为这个错误的含义是什么?你熟悉sql服务器还是任何编程语言变量? –

+0

你是否在调用'Executer'之后设置Param值**?在片段中看起来如此。 – Plutonix

+0

所以你有一个全局变量来执行叫做cmd的命令。 (而且这足以让我发抖),但是你可以调用Excuter方法,在设置参数集之前传递一个填充参数的字符串。不要惊讶,如果sqlserver大吼你。 – Steve

回答

4

问题是,您的Excuter函数接受查询字符串并在您实际将参数添加到cmd对象之前执行它。一个快速和肮脏的解决办法是打电话Excuter,这样才简单地填充Parameters集合:

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

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

将参数添加到Executer Sub,允许您将可变数量的参数传递给您的查询。既然你不能轻易地在同一时间传递的参数名称,只是名称参数@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的使用真正的简化,比起你的方法。