Вставки SQLite - Как вставить любой текст, избегая синтаксических ошибок, используя параметризованные значения - PullRequest
0 голосов
/ 06 марта 2019

Мне любопытно узнать правильный способ вставки текстовых строк в базу данных независимо от того, какие символы содержатся в строке.Я понимаю, что если у меня есть строка, например, содержащая одинарные кавычки или любой другой символ, который зарезервирован как «специальный» символ SQL.

Проблема, с которой я сталкиваюсь, заключается в том, чтоУ меня нет контроля над возможным текстом, который вставляется в мою базу данных, поскольку текст генерируется моим приложением.

Один из примеров, когда мое приложение не может быть правильно вставлено, - это сообщение об ошибке, которое содержит одинарные кавычки.Одиночные кавычки используются операторами SQL для вставки текста, поэтому я не могу вставить текст, который также содержит одинарные кавычки (кроме использования функции ascii value char (##)).Проблема, с которой я сталкиваюсь, заключается в том, что я устанавливаю вывод моего приложения в строковую переменную, которая затем вставляется в мою базу данных, чтобы я мог регистрировать активность, будь то стандартный вывод или перехват ошибок.

Какмне просто ВСТАВИТЬ, что содержится в моей строковой переменной, избегая при этом всех специальных символов SQL?

Нужно ли мне вручную учитывать все специальные символы SQL и заменять их в моей строке перед вставкой?Это звучит как попадание или промах, и я надеюсь, что уже есть что-то, что бы приспособиться к этой ситуации.

Пример псевдокода для объяснения:

Допустим, произошла ошибка вприложение и оно должно быть зарегистрировано.Строка ошибки может быть следующей:

Строка ошибки: «Ошибка в функции возвести в нуль параметр функцииStStStats ()« 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');

В заключение - поскольку я не имею никакого контроля над текстом, который может быть создан моим приложением, как мне учесть все возможные символы, которые могут сломать мойinsert?

Код, в котором мое текущее приложение сталкивается с этой проблемой, написано на 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

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Эта проблема очень похожа на проблему предотвращения уязвимостей SQL-инъекций в вашем коде. Запросы очень легко разбить, и, хотя ваши запросы разбиваются таким образом, что это безвредно и раздражает, они могут быть доведены до уровней, когда определенные входные данные могут полностью уничтожить вашу базу данных!

Один из лучших способов добиться этого - использовать параметризованные запросы. Этот подход довольно прост; сначала вы пишете запрос с «заполнителями» для параметров, которые вы отправите. Когда вы будете готовы в своей программе, вы можете «привязать» эти параметры к заполнителям.

Это будет выглядеть примерно так:

Dim command = New SqlCommand("INSERT INTO outputLog(outputLogText) VALUES  (@stringToInsert)", connection);
.
.
.
code
.
.
.
command.Parameters.AddWithValue("@stringToInsert", errorMessage)
.
.
.
execute query

В приведенном выше примере вы видите, что @stringToInsert - это заполнитель, связанный только позднее. Неважно, что содержит переменная errorMessage, так как это не приведет к тому, что запрос будет функционировать таким образом, что ввод приведет к его потенциальному разрыву.

На это есть много ресурсов:

https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.prepare?view=netframework-4.7.2

1 голос
/ 06 марта 2019

Объекты базы данных, такие как соединения, должны быть не только закрыты, но и удалены.Использование блока гарантирует, что это произойдет даже в случае ошибки.

Значение .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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...