如何更正命令生成器中的语法错误? [复制]
Posted
技术标签:
【中文标题】如何更正命令生成器中的语法错误? [复制]【英文标题】:How do I correct a syntax error in command builder? [duplicate] 【发布时间】:2021-12-25 23:32:14 【问题描述】:我正在尝试使用此例程来更新我的自动日志表访问权限。每次运行它时,INSERT 命令都会出现语法错误。现在,当我从命令生成器查看 INSERT 命令时,我可以看到缺少的值被问号替换,但我不明白为什么。这是我的代码:
Function Autolog(ByRef LogEntry As String, ByVal Userid As Integer)
Dim Table_ As String = "Table1"
Dim sql As String = "Select * from autolog"
Dim MDBConnString_ As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Freightmasterbe\Freightmaster.accdb;"
Dim cnn As OleDbConnection = New OleDbConnection(MDBConnString_)
Dim DS As New DataSet
Dim Da As OleDbDataAdapter
Dim StrHOstName As String
Da = New OleDb.OleDbDataAdapter(sql, cnn)
Da.Fill(DS, "Rst")
' cnn.Close()
Dim cb As New OleDb.OleDbCommandBuilder(Da)
Dim DSNewRow As DataRow
DSNewRow = DS.Tables("Rst").NewRow()
DSNewRow.Item("UserID") = Userid
DSNewRow.Item("Action") = LogEntry
DSNewRow.Item("RemoteComputerName") = My.Computer.Name
StrHOstName = System.Net.Dns.GetHostName()
DSNewRow.Item("RemoteIP") = System.Net.Dns.GetHostEntry(StrHOstName).AddressList(0).ToString()
DS.Tables("RST").Rows.Add(DSNewRow)
' Da.ContinueUpdateOnError = True
Da.Update(DS, "RST")
Beep()
End Function
这是我查询命令生成器插入命令时得到的结果
立即窗口
CanRaiseEventsInternal: True
CommandText: "INSERT INTO autolog (UserID, Action, TimeStamp, RemoteComputerName, RemoteIP) VALUES (?, ?, ?, ?, ?)"
CommandTimeout: 30
CommandType: Text 1
Connection: System.Data.OleDb.OleDbConnection
Connection (DbCommand): System.Data.OleDb.OleDbConnection
Container: Nothing
DbConnection: System.Data.OleDb.OleDbConnection
DbParameterCollection: System.Data.OleDb.OleDbParameterCollection
DbTransaction: Nothing
DesignMode: False
DesignTimeVisible: True
Events: System.ComponentModel.EventHandlerList
ObjectID: 4
Parameters: System.Data.OleDb.OleDbParameterCollection
Parameters (DbCommand): System.Data.OleDb.OleDbParameterCollection
Site: Nothing
Transaction: Nothing
Transaction (DbCommand): Nothing
UpdatedRowSource: None 0
【问题讨论】:
问号是正确的。它们是参数化查询的占位符,用于保护您的代码免受 SQL 注入错误和攻击。 【参考方案1】:根据这个post,Action
是一个Access database engine reserved word。因此,您需要使用QuotePrefix 和QuoteSuffix,如下面的代码所示。此外,任何具有Dispose
方法的对象都应使用using statement 或调用Dispose
。
如果您希望使用OleDbCommandBuilder 在您的 Access 数据库中插入一行:
创建表(名称:Autolog)
CREATE TABLE Autolog(ID AUTOINCREMENT not null primary key,
[UserID] varchar(25),
[Action] varchar(125),
[RemoteComputerName] varchar(50),
[RemoteIP] varchar(50));
然后,尝试以下(已经过测试):
Private _connectionStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Freightmasterbe\Freightmaster.accdb;"
Public Function TblAutologInsert(ByVal LogEntry As String, ByVal UserId As Integer) As Integer
Dim dt As DataTable = New DataTable()
Dim remoteComputerName As String = My.Computer.Name
Dim strHostName As String = System.Net.Dns.GetHostName()
Dim remoteIP = System.Net.Dns.GetHostEntry(strHostName).AddressList(0).ToString()
Using cnn As OleDbConnection = New OleDbConnection(_connectionStr)
'open
cnn.Open()
Using da As OleDbDataAdapter = New OleDbDataAdapter("SELECT * from Autolog order by Id", cnn)
'get data from database
da.Fill(dt)
Using cb As OleDbCommandBuilder = New OleDbCommandBuilder(da)
'needed if database column name contains either spaces or is a reserved word
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
'new row
Dim row As DataRow = dt.NewRow()
'set values
row.Item("UserID") = UserId
row.Item("Action") = LogEntry
row.Item("RemoteComputerName") = remoteComputerName
row.Item("RemoteIP") = remoteIP
'add row to DataTable
dt.Rows.Add(row)
'get insert command
da.InsertCommand = cb.GetInsertCommand(True)
'Debug.WriteLine("da.InsertCommand.CommandText: " & da.InsertCommand.CommandText)
'update database and return number of rows affected
Return da.Update(dt)
End Using
End Using
End Using
End Function
用法:
Dim rowsAffected As Integer = 0
'insert test data
rowsAffected += HelperAccess.TblAutologInsert("test 1", 1)
rowsAffected += HelperAccess.TblAutologInsert("test 2", 2)
rowsAffected += HelperAccess.TblAutologInsert("test 3", 3)
Debug.WriteLine("rowsAffected: " & rowsAffected.ToString())
这是一些通过“Id”更新记录的代码。
Public Function TblAutologUpdate(LogEntry As String, UserId As Integer, id As Integer) As Integer
Dim dt As DataTable = New DataTable()
Dim remoteComputerName As String = My.Computer.Name
Dim strHostName As String = System.Net.Dns.GetHostName()
Dim remoteIP = System.Net.Dns.GetHostEntry(strHostName).AddressList(0).ToString()
Using cnn As OleDbConnection = New OleDbConnection(_connectionStr)
'open
cnn.Open()
Using cmd As OleDbCommand = New OleDbCommand("SELECT * from Autolog where Id = ?", cnn)
'OLEDB doesn't use named parameters in SQL. Any names specified will be discarded and replaced with '?'
'However, specifying names in the parameter 'Add' statement can be useful for debugging
'Since OLEDB uses anonymous names, the order which the parameters are added is important
'if a column is referenced more than once in the SQL, then it must be added as a parameter more than once
'parameters must be added in the order that they are specified in the SQL
'if a value is null, the value must be assigned as: DBNull.Value
'add parameters
With cmd.Parameters
.Add("!id", OleDbType.Integer).Value = id
End With
Using da As OleDbDataAdapter = New OleDbDataAdapter(cmd)
'get data from database
da.Fill(dt)
Using cb As OleDbCommandBuilder = New OleDbCommandBuilder(da)
'needed if database column name contains either spaces or is a reserved word
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
If dt.Rows.Count >= 0 Then
'set value
Dim row As DataRow = dt.Rows(0)
'set values
row.Item("UserID") = UserId
row.Item("Action") = LogEntry
row.Item("RemoteComputerName") = remoteComputerName
row.Item("RemoteIP") = remoteIP
'get update command
da.UpdateCommand = cb.GetUpdateCommand()
'update database and return number of rows affected
Return da.Update(dt)
End If
End Using
End Using
End Using
End Using
End Function
用法:
Dim rowsAffected As Integer = 0
'update
rowsAffected += HelperAccess.TblAutologUpdateById("test 2b", 2, 2)
Debug.WriteLine("rowsAffected: " & rowsAffected.ToString())
资源
OleDbConnection Class OleDbDataAdapter Class OleDbCommandBuilder Class OleDbCommand Class DbCommandBuilder.QuotePrefix Property DbCommandBuilder.QuoteSuffix Property Learn about Access reserved words and symbols Syntax error in INSERT INTO statement generated by OleDbCommandBuilder using statement (C# Reference)【讨论】:
【参考方案2】:非常感谢您的 cmets。添加前缀和后缀产生了重大影响,并且在第一个答案中使用最初发布的代码效果很好。其他回应也解释了很多。 (哦,我多么向往简单地使用 sql 语句插入数据的美好时光!
【讨论】:
如果您觉得我的回答有用,请点击旁边的^
箭头。以上是关于如何更正命令生成器中的语法错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章