我很想知道一种正确的方法,可以将文本字符串插入数据库中,而不管字符串中包含什么字符。我的意思是,如果我有一个字符串,例如包含单引号或保留为“特殊” SQL字符的任何其他字符。
我要处理的具体问题是,我无法控制可能插入到数据库中的“文本”,因为文本是由应用程序生成的。
当错误消息恰好包含单引号时,我的应用程序无法正确插入的一个示例。 SQL语句当然会使用单引号插入文本,因此我无法插入也包含单引号的文本(除了使用ascii值char(##)函数外)。我要解决的问题是,我将应用程序的输出设置为字符串变量,然后将其插入数据库中,以便可以记录活动(无论是标准输出还是捕获错误)。
如何在避免所有SQL特殊字符的同时简单地插入字符串变量中包含的内容?
我是否需要手动说明所有SQL特殊字符并在插入之前将其替换为字符串?听起来像是命中注定,但我希望已经有一些东西可以适应这种情况。
通过示例伪代码来说明要点:
比方说,应用内发生了错误,需要将其记录下来。错误字符串可能是:
错误字符串:“函数calculateStats()参数'pBoolStatCheck'中的错误为空”
现在,我在应用程序中分配给我的字符串变量,并建立SQL插入字符串。
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
答案 0 :(得分:2)
此问题与防止代码中的SQL注入漏洞的问题非常相似。查询非常容易中断,尽管您的中断以无害且烦人的方式中断,但是可以将这些查询带到某些输入可以完全破坏数据库的水平!
解决此问题的最佳方法之一是使用参数化查询。这种方法非常简单。您首先使用“占位符”编写查询,以获取要发送的参数。准备好程序后,可以将这些参数“绑定”到占位符。
类似于以下内容:
Dim command = New SqlCommand("INSERT INTO outputLog(outputLogText) VALUES (@stringToInsert)", connection);
.
.
.
code
.
.
.
command.Parameters.AddWithValue("@stringToInsert", errorMessage)
.
.
.
execute query
在上面,您看到@stringToInsert
是占位符,仅在以后绑定。变量errorMessage
所包含的内容无关紧要,因为它不会导致查询以输入导致其潜在中断的方式起作用。
关于此的资源很多:
答案 1 :(得分:1)
诸如连接之类的数据库对象不仅需要关闭,而且还需要处置。 using块将确保即使发生错误也将发生这种情况。
由于多种原因,.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个。
在执行之前的最后一分钟打开连接。
如果将OleDb与Access一起使用,则需要确保以与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