我很想知道将文本字符串插入数据库的正确方法,无论字符串中包含哪些字符。我得到的是,如果我有一个字符串,例如包含单引号或任何其他保留为“特殊”SQL字符的字符。
我正在处理的问题是,我无法控制插入到我的数据库中的可能“文本”,因为它们是由我的应用程序生成的。
我的应用程序无法正确插入的一个示例是当出现包含单引号的错误消息时。单引号由SQL语句使用当然插入文本,因此我不能插入也包含单引号的文本(在使用ascii值char(##)函数之外)。我正在处理的问题是我将应用程序的输出设置为字符串变量然后插入到我的数据库中,这样我就可以记录活动,无论是标准输出还是捕获错误。
如何简单地插入我的字符串变量中包含的内容,同时避免使用所有SQL特殊字符?
我是否需要手动考虑所有SQL特殊字符并在插入之前将其替换为我的字符串?这听起来像是一个打击或错过,我希望已经建立了一些东西来适应这种情况。
示例Pseudo Code以获得指向:
假设应用程序内发生错误,需要记录。错误字符串可能是:
错误字符串:“函数calculateStats()参数中的错误'pBoolStatCheck'为空”
现在我在我的app中分配我的字符串变量并构建SQL Insert字符串。
var insertString = "Error in function calculateStats() parameter 'pBoolStatCheck' is Null"
INSERT INTO outputLog(outputLogText)
VALUES ('insertString'); --This will Fail
--Fails due to the variable 'insertString' containing single quotes.
INSERT INTO outputLog(outputLogText)
VALUES ('Error in function calculateStats() parameter 'pBoolStatCheck' is Null');
最后 - 由于我无法控制我的应用程序可能创建的文本,如何解释可能会破坏插入的所有可能字符?
我当前的应用程序遇到此问题的代码是用Visual Basic编写的。我正在使用的数据库是SQLite。
基于此帖收到的答案的最终解决方案:
Public Sub saveOutputLog(pTextOutput, pTextColor, pNumNewLines, plogType, pMethodSub)
Dim strTableName As String = "outputLog"
Dim sqlInsert As String = "INSERT INTO " & strTableName & "(" &
"outputLog, logColor, numNewLines, logType, method" &
") VALUES (@outputLog, @logColor, @numNewLines, @logType, @method);"
Try
'Open the Database
outputLogDBConn.Open()
'Create/Use a command object via the connection object to insert data into the outputLog table
Using cmd = outputLogDBConn.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = sqlInsert
cmd.Parameters.AddWithValue("@outputLog", pTextOutput)
cmd.Parameters.AddWithValue("@logColor", pTextColor)
cmd.Parameters.AddWithValue("@numNewLines", pNumNewLines)
cmd.Parameters.AddWithValue("@logType", plogType)
cmd.Parameters.AddWithValue("@method", pMethodSub)
'Execute the command using above Insert and added Parameters.
cmd.ExecuteNonQuery()
End Using 'Using outputLogDBComm
outputLogDBConn.Close()
Catch ex As Exception
outputLogDBConn.Close()
End Try
End Sub
此问题与防止代码中的SQL注入漏洞的问题非常相似。查询非常容易破解,虽然您的查询以无害且烦人的方式打破,但这些可以达到某些输入可以完全破坏您的数据库的水平!
解决此问题的最佳方法之一是使用参数化查询。这种方法很简单;您首先使用'占位符'为您将要发送的参数编写查询。一旦准备好您的程序,您就可以将这些参数“绑定”到占位符。
它看起来像下面这样:
Dim command = New SqlCommand("INSERT INTO outputLog(outputLogText) VALUES (@stringToInsert)", connection);
.
.
.
code
.
.
.
command.Parameters.AddWithValue("@stringToInsert", errorMessage)
.
.
.
execute query
在上面你看到@stringToInsert
是占位符,它只在以后绑定。变量errorMessage
包含什么并不重要,因为它不会导致查询以输入导致它可能破坏的方式运行。
这有很多资源:
像连接这样的数据库对象不仅需要关闭,还需要处理。使用块将确保即使出现错误也会发生这种情况。
由于多种原因,.Add
比.AddWithValue
更好。见https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/和http://www.dbdelta.com/addwithvalue-is-evil/
.Add
的参数是参数的名称,数据库中的数据类型以及可选的字段大小。您需要检查数据库中的最后2个。
执行前最后一刻打开连接。
如果您正在使用带有Access的OleDb,则需要确保参数的添加顺序与它们在sql语句中的显示顺序相同。
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("INSERT INTO outputLog(outputLogText) VALUES (@outputLogText);", cn)
cmd.Parameters.Add("@outputLogText", SqlDbType.VarChar, 100).Value = TextBox1.Text
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Using