Visual Studio 2019 .NET VB Web 应用程序 SQL 语法错误
Visual Studio 2019 .NET VB web application SQL syntax error
我想使用来自文本框的两个用户输入执行查询搜索,并在 Viewgrid 上显示结果,但是我想在查询中插入的参数有问题,并且出现以下错误:
ExecQuery error:
Line 1: Incorrect syntax near '.'.
Must declare the variable '@H'.
我是不是实现了一个不正确的功能,或者我是否以不正确的方式执行此操作,或者我是否只是试图错误地填充视图网格?如果有人能指出正确的方向,我将不胜感激。
这是我的 SQLControl
代码:
Public Class SQLControl
ReadOnly DBCon As New SqlConnection()
Private DBCmd As SqlCommand
'DB Data
Public DBDA As SqlDataAdapter
Public DBDT As DataTable
'Query Parameters
Public Params As New List(Of SqlParameter)
'Query Statistics
Public RecordCount As Integer
Public Exception As String
'This generates a blank sqlclient class with the deafult connection string
Public Sub New()
End Sub
'Allow connection string override
Public Sub New(connectionString As String)
DBCon = New SqlConnection(connectionString)
End Sub
'Execute Query Sub
Public Sub ExecQuery(query As String)
'Reset Query Stats
RecordCount = 0
Exception = ""
Try
DBCon.Open()
'Create DB Command
DBCmd = New SqlCommand(query, DBCon)
'Load Params Into DB Command
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
'Clear Param List
Params.Clear()
'Execute Command & Fill Dataset
DBDT = New DataTable
DBDA = New SqlDataAdapter(DBCmd)
RecordCount = DBDA.Fill(DBDT)
Catch ex As Exception
'Capture Error
Exception = "ExecQuery Error: " & vbNewLine & ex.Message
Finally
'Close Connection
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Try
End Sub
'Add Params
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New SqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
'Error Checking
Public Function HasException(Optional Report As Boolean = False) As Boolean
If String.IsNullOrEmpty(Exception) Then Return False
If Report = True Then MsgBox(Exception, MsgBoxStyle.Critical, "Exception:")
Return True
End Function
End Class
这是我执行查询的按钮:
Protected Sub ExecuteButton_Click(sender As Object, e As EventArgs) Handles ExecuteButton.Click
If StoreIDTextbox.Text.Length <= 0 Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
End If
If TransactionIDTextbox.Text.Length <= 0 Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
End If
SQL.AddParam("@H.Str_ID", Integer.Parse(StoreIDTextbox.Text))
SQL.AddParam("@H.Tran_ID", Integer.Parse(TransactionIDTextbox.Text))
SQL.ExecQuery("SELECT H.Emp_ID, H.Cust_ID, D.*
FROM Transaction_Header H
INNER JOIN LN_Detail L ON (H.Str_ID = L.Str_ID AND H.Rgst_ID = L.Rgst_ID AND H.Tran_ID = L.Tran_ID)
INNER Join LN_Discount D ON (L.Str_ID = D.Str_ID AND L.Rgst_ID = D.Rgst_ID AND L.Tran_ID = D.Tran_ID AND L.Tran_LN_Num = D.Tran_LN_Num)
WHERE H.Str_ID = @H.Str_ID AND H.Tran_ID = @H.Tran_ID")
If SQL.HasException(True) Then Exit Sub
GridView1.DataSource = SQL.DBDT
End Sub
在你的 class 中:
我已将您的数据库对象移动到使用它们的方法中,以便可以关闭和处置它们。 Using...End Using
个积木会为您做这件事。
如果您需要记录计数,可从 DataTable.Rows.Count
获得
如果您不打算在 class 中处理异常,则不要将 Try...End Try
放在那里。拥有数据访问权 class 的要点之一是将用户界面与数据源分开。在您的数据访问中显示一个消息框 class 将 link 硬编码到用户界面。您的 class 不应绑定到 Windows 中可以显示消息框的桌面应用程序。假设您想在 Web 应用程序中使用 class。您将不得不重写 class。我把 Try...End Try
放在可以显示消息框的按钮事件(用户界面代码)中。
我没有单独处理参数,因为它确实可以保护您的数据库免受 Sql 注入。然而,这不是处理 Sql 服务器参数的最佳方式。 ADO.net 必须猜测数据类型,它可能会猜错。例如,ADO.net 将字符串视为参数的值。它指定 NVarChar
作为数据类型,但数据库中的字段实际上可能是 VarChar
。现在 Sql 服务器必须暂时将字段扩展为 NVarChar
以搜索您的参数。你可以看到这是多么低效。然后考虑数值 6。它是整数还是某种类型的浮点数?
在按钮代码中,我使用 Integer.TryParse
来验证用户输入,添加 Exit Sub
以允许用户更正错误。
显然,真正的问题正如@Andrew Morton 所评论的那样。我更改了参数的名称。很多时候连接是从主键到外键,但也许您有复合键。
数据访问Class
Public Class SQLControl
Private ConStr As String = "Your connection string"
'Query Parameters
Public Params As New List(Of SqlParameter)
'This generates a blank sqlclient class with the deafult connection string
Public Sub New()
End Sub
'Allow connection string override
Public Sub New(connectionString As String)
ConStr = connectionString
End Sub
'Execute Query Sub
Public Function ExecQuery(query As String) As DataTable
'Params.Clear()
Dim DBDT = New DataTable
Using DBCon As New SqlConnection(ConStr),
DBCmd As New SqlCommand(query, DBCon)
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
Params.Clear()
DBCon.Open()
DBDT.Load(DBCmd.ExecuteReader)
End Using
Return DBDT
End Function
'Add Params
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New SqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
用户界面代码
Private Sql As New SQLControl("Your connection string")
Protected Sub ExecuteButton_Click(sender As Object, e As EventArgs) Handles ExecuteButton.Click
Dim StoreID As Integer
Dim TransID As Integer
If Not Integer.TryParse(StoreIDTextbox.Text, StoreID) Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
Exit Sub
End If
If Not Integer.TryParse(TransactionIDTextbox.Text, TransID) Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
Exit Sub
End If
Sql.AddParam("@Str_ID", StoreID)
Sql.AddParam("@Tran_ID", TransID)
Dim dt As DataTable
Try
dt = Sql.ExecQuery("SELECT H.Emp_ID, H.Cust_ID, D.*
FROM Transaction_Header H
INNER JOIN LN_Detail L ON (H.Str_ID = L.Str_ID AND H.Rgst_ID = L.Rgst_ID AND H.Tran_ID = L.Tran_ID)
INNER Join LN_Discount D ON (L.Str_ID = D.Str_ID AND L.Rgst_ID = D.Rgst_ID AND L.Tran_ID = D.Tran_ID AND L.Tran_LN_Num = D.Tran_LN_Num)
WHERE H.Str_ID = @Str_ID AND H.Tran_ID = @Tran_ID")
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
GridView1.DataSource = dt
End Sub
我想使用来自文本框的两个用户输入执行查询搜索,并在 Viewgrid 上显示结果,但是我想在查询中插入的参数有问题,并且出现以下错误:
ExecQuery error:
Line 1: Incorrect syntax near '.'.
Must declare the variable '@H'.
我是不是实现了一个不正确的功能,或者我是否以不正确的方式执行此操作,或者我是否只是试图错误地填充视图网格?如果有人能指出正确的方向,我将不胜感激。
这是我的 SQLControl
代码:
Public Class SQLControl
ReadOnly DBCon As New SqlConnection()
Private DBCmd As SqlCommand
'DB Data
Public DBDA As SqlDataAdapter
Public DBDT As DataTable
'Query Parameters
Public Params As New List(Of SqlParameter)
'Query Statistics
Public RecordCount As Integer
Public Exception As String
'This generates a blank sqlclient class with the deafult connection string
Public Sub New()
End Sub
'Allow connection string override
Public Sub New(connectionString As String)
DBCon = New SqlConnection(connectionString)
End Sub
'Execute Query Sub
Public Sub ExecQuery(query As String)
'Reset Query Stats
RecordCount = 0
Exception = ""
Try
DBCon.Open()
'Create DB Command
DBCmd = New SqlCommand(query, DBCon)
'Load Params Into DB Command
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
'Clear Param List
Params.Clear()
'Execute Command & Fill Dataset
DBDT = New DataTable
DBDA = New SqlDataAdapter(DBCmd)
RecordCount = DBDA.Fill(DBDT)
Catch ex As Exception
'Capture Error
Exception = "ExecQuery Error: " & vbNewLine & ex.Message
Finally
'Close Connection
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Try
End Sub
'Add Params
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New SqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
'Error Checking
Public Function HasException(Optional Report As Boolean = False) As Boolean
If String.IsNullOrEmpty(Exception) Then Return False
If Report = True Then MsgBox(Exception, MsgBoxStyle.Critical, "Exception:")
Return True
End Function
End Class
这是我执行查询的按钮:
Protected Sub ExecuteButton_Click(sender As Object, e As EventArgs) Handles ExecuteButton.Click
If StoreIDTextbox.Text.Length <= 0 Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
End If
If TransactionIDTextbox.Text.Length <= 0 Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
End If
SQL.AddParam("@H.Str_ID", Integer.Parse(StoreIDTextbox.Text))
SQL.AddParam("@H.Tran_ID", Integer.Parse(TransactionIDTextbox.Text))
SQL.ExecQuery("SELECT H.Emp_ID, H.Cust_ID, D.*
FROM Transaction_Header H
INNER JOIN LN_Detail L ON (H.Str_ID = L.Str_ID AND H.Rgst_ID = L.Rgst_ID AND H.Tran_ID = L.Tran_ID)
INNER Join LN_Discount D ON (L.Str_ID = D.Str_ID AND L.Rgst_ID = D.Rgst_ID AND L.Tran_ID = D.Tran_ID AND L.Tran_LN_Num = D.Tran_LN_Num)
WHERE H.Str_ID = @H.Str_ID AND H.Tran_ID = @H.Tran_ID")
If SQL.HasException(True) Then Exit Sub
GridView1.DataSource = SQL.DBDT
End Sub
在你的 class 中:
我已将您的数据库对象移动到使用它们的方法中,以便可以关闭和处置它们。 Using...End Using
个积木会为您做这件事。
如果您需要记录计数,可从 DataTable.Rows.Count
如果您不打算在 class 中处理异常,则不要将 Try...End Try
放在那里。拥有数据访问权 class 的要点之一是将用户界面与数据源分开。在您的数据访问中显示一个消息框 class 将 link 硬编码到用户界面。您的 class 不应绑定到 Windows 中可以显示消息框的桌面应用程序。假设您想在 Web 应用程序中使用 class。您将不得不重写 class。我把 Try...End Try
放在可以显示消息框的按钮事件(用户界面代码)中。
我没有单独处理参数,因为它确实可以保护您的数据库免受 Sql 注入。然而,这不是处理 Sql 服务器参数的最佳方式。 ADO.net 必须猜测数据类型,它可能会猜错。例如,ADO.net 将字符串视为参数的值。它指定 NVarChar
作为数据类型,但数据库中的字段实际上可能是 VarChar
。现在 Sql 服务器必须暂时将字段扩展为 NVarChar
以搜索您的参数。你可以看到这是多么低效。然后考虑数值 6。它是整数还是某种类型的浮点数?
在按钮代码中,我使用 Integer.TryParse
来验证用户输入,添加 Exit Sub
以允许用户更正错误。
显然,真正的问题正如@Andrew Morton 所评论的那样。我更改了参数的名称。很多时候连接是从主键到外键,但也许您有复合键。
数据访问Class
Public Class SQLControl
Private ConStr As String = "Your connection string"
'Query Parameters
Public Params As New List(Of SqlParameter)
'This generates a blank sqlclient class with the deafult connection string
Public Sub New()
End Sub
'Allow connection string override
Public Sub New(connectionString As String)
ConStr = connectionString
End Sub
'Execute Query Sub
Public Function ExecQuery(query As String) As DataTable
'Params.Clear()
Dim DBDT = New DataTable
Using DBCon As New SqlConnection(ConStr),
DBCmd As New SqlCommand(query, DBCon)
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
Params.Clear()
DBCon.Open()
DBDT.Load(DBCmd.ExecuteReader)
End Using
Return DBDT
End Function
'Add Params
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New SqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
用户界面代码
Private Sql As New SQLControl("Your connection string")
Protected Sub ExecuteButton_Click(sender As Object, e As EventArgs) Handles ExecuteButton.Click
Dim StoreID As Integer
Dim TransID As Integer
If Not Integer.TryParse(StoreIDTextbox.Text, StoreID) Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
Exit Sub
End If
If Not Integer.TryParse(TransactionIDTextbox.Text, TransID) Then
MsgBox("Invalid input. Please enter both Store ID and Transaction ID.")
Exit Sub
End If
Sql.AddParam("@Str_ID", StoreID)
Sql.AddParam("@Tran_ID", TransID)
Dim dt As DataTable
Try
dt = Sql.ExecQuery("SELECT H.Emp_ID, H.Cust_ID, D.*
FROM Transaction_Header H
INNER JOIN LN_Detail L ON (H.Str_ID = L.Str_ID AND H.Rgst_ID = L.Rgst_ID AND H.Tran_ID = L.Tran_ID)
INNER Join LN_Discount D ON (L.Str_ID = D.Str_ID AND L.Rgst_ID = D.Rgst_ID AND L.Tran_ID = D.Tran_ID AND L.Tran_LN_Num = D.Tran_LN_Num)
WHERE H.Str_ID = @Str_ID AND H.Tran_ID = @Tran_ID")
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
GridView1.DataSource = dt
End Sub