Как передать несколько параметров в предложение sqlite IN и защитить от внедрения SQL? - PullRequest
1 голос
/ 19 сентября 2019

Я использую Библиотека Microsoft.Data.Sqlite соответствующие API-интерфейсы sqlite в проекте UWP.

Я обнаружил, что если я использую условие IN в своем параметризованном операторе SQL, этоне возвращает правильный результат.

Например, если оператор SQL выглядит следующим образом:

sqliteCommand.CommandText = @"delete from [test_table] where col1 in(@para1,@para2)";
sqliteCommand.Parameters.Add(new SqliteParameter("@para1", '1'));
sqliteCommand.Parameters.Add(new SqliteParameter("@para2", '2'));
sqliteCommand.ExecuteNonQuery();

Он не будет удалять строки, когда 'col1' равен '1'или '2'.

Если я изменил SQL на это:

sqliteCommand.CommandText = @"delete from [test_table] where col1 in(@para1,@para2)";
sqliteCommand.Parameters.Add(new SqliteParameter("@para1", "1"));   
sqliteCommand.Parameters.Add(new SqliteParameter("@para2", "2"));

Это сработало.

Если я изменил SQL на это:

sqliteCommand.CommandText = @"delete from [test_table] where col1 in ('1', '2')";
sqliteCommand.ExecuteNonQuery();

При этом это также сработало.

Но, если я изменил SQL на это:

delete from [test_table] where col1 in(@para1)   
sqliteCommand.Parameters.Add(new SqliteParameter("@para1", "'1','2'"));
//or sqliteCommand.Parameters.Add(new SqliteParameter("@para1", "1,2"));

В этом случае это не сработало.

Я думаю, что Microsoft нужно исследовать эту проблему.

Версия библиотеки Microsoft.Data.Sqlite - 2.2.6.

Ниже приведена демонстрационная версия всего кода:

SqliteConnection sqliteConnection = new SqliteConnection("Filename=test.db");
sqliteConnection.Open();

SqliteDataReader sqliteDataReader;

string sql = @"CREATE TABLE IF NOT EXISTS [test_table] ( col1 VARCHAR(1), col2 VARCHAR(1), col3 VARCHAR(4));";

SqliteCommand sqliteCommand = new SqliteCommand(sql, sqliteConnection);
sqliteCommand.ExecuteNonQuery();

sql = @"INSERT INTO [test_table] (col1, col2, col3) VALUES('1', '1', '0001')";
sqliteCommand.CommandText = sql;

sqliteCommand.ExecuteNonQuery();

sql = @"INSERT INTO [test_table] (col1, col2, col3) VALUES('2', '2', '0002')";
sqliteCommand.CommandText = sql;
sqliteCommand.ExecuteNonQuery();

sql = @"INSERT INTO [test_table] (col1, col2, col3) VALUES('3', '3', '0003')";
sqliteCommand.CommandText = sql;
sqliteCommand.ExecuteNonQuery();

sqliteCommand.CommandText = @"delete from [test_table] where col1 in(@para1,@para2)";

//sqliteCommand.CommandText = @"delete from [test_table] where col1 in('1','2')";

sqliteCommand.Parameters.Add(new SqliteParameter("@para1", '1'));
sqliteCommand.Parameters.Add(new SqliteParameter("@para2", '2'));

sqliteCommand.ExecuteNonQuery();

sqliteCommand.CommandText = @"select * from [test_table]";
sqliteDataReader = sqliteCommand.ExecuteReader();

1 Ответ

0 голосов
/ 19 сентября 2019

Прямой ответ

Чтобы разрешить удаление переменного числа записей с помощью IN, используйте этот код:

// Example data
var valuesToDelete = new List<string> { "1", "2", "4" };

sqliteCommand.CommandText = @"delete from [test_table] where col1 in(" + string.Join(",", Enumerable.Range(0, valuesToDelete.Count).Select(z => "@para" + z)) + ")";

for (var i = 0; i < valuesToDelete.Count; i++)
{
    sqliteCommand.Parameters.Add(new SqliteParameter("@para" + i, valuesToDelete[i]));
}

sqliteCommand.ExecuteNonQuery();

string.Join используется для настройки правчисло параметров в SQL, и цикл for предназначен для заполнения этих параметров.Это позволяет использовать несколько значений внутри IN и защищено от SQL-инъекции.

Фон

Причина, по которой:

sqliteCommand.CommandText = @"delete from [test_table] where col1 in(@para1,@para2)";
sqliteCommand.Parameters.Add(new SqliteParameter("@para1", "1"));
sqliteCommand.Parameters.Add(new SqliteParameter("@para2", "2"));
sqliteCommand.ExecuteNonQuery();

работает, но:

sqliteCommand.CommandText = @"delete from [test_table] where col1 in(@para1,@para2)";
sqliteCommand.Parameters.Add(new SqliteParameter("@para1", '1'));
sqliteCommand.Parameters.Add(new SqliteParameter("@para2", '2'));
sqliteCommand.ExecuteNonQuery();

не означает, что с последним вы случайно передали параметры как char вместо string.

Последний может чувствую правильно, так как ' нормально работает в SQL.Но SQL и C # различны - ' может использоваться вокруг строки в SQL, но не в C # (C # использует ' для char и " для `строки).

Таким образом, при передаче строковых параметров в - обязательно передайте их как string (используя "), а не char.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...