LSB71 Ответов: 3

Условие C # SQL где с датой


<pre lang="text">
Hello,
I have some concerns in an SQL request.
A la base j’ai une base de donnes Sqlite avec des dates au format texte comme ceci (21/02/2020).
J’affiche mes résultat dans un Datagridview avec cette requête :
Basically I have a Sqlite database with dates in text format like this (02/12/2020).
I display my results in a Datagridview with this query:

string SQL_Tbl_P4_Cmde = "SELECT * FROM Tble_Commande INNER JOIN Tble_Demande ON" + 
                        " (Tble_Demande.dmd_ID = Tble_Commande.cmd_ID) WHERE Tble_Commande.Annee = '" + Annee_en_Cour + "'" +  
                    "AND (Reference LIKE '%" + Txt_P4_recherche_Ref.Text + "%' OR Reference IS NULL)" +
                    "AND (Designations LIKE '%" + Txt_P4_recherche_Article.Text + "%' OR Designations IS NULL)" +
"AND (Date_prise_compte_cmds LIKE '% + Txt_P4_recherche_Date.Text + "%' OR Date_prise_compte_cmds IS NULL)" +

                    "AND (Lieu_livraison LIKE '%" + Cbo_P4_recherche_lieu.Text + "%' OR Lieu_livraison IS NULL)" +
                    "AND (Imputation LIKE '%" + Cbo_P4_recherche_Imput.Text + "%' OR Imputation IS NULL)" +
                    "AND (Type_cmds LIKE '%" + Cbo_P4_recherche_TypeCmds.Text + "%' OR Type_cmds IS NULL)";

Recently I changed the date format of my columns like this (2020-02-12)
I encountered problems with this line of code:

"AND (Date_prise_compte_cmds LIKE '% + Txt_P4_recherche_Date.Text + "%' OR Date_prise_compte_cmds IS NULL)" +

I modified by this new line like this:
(To find the error I replaced my textbox with a concrete date.)

"AND (Date_prise_compte_cmds LIKE '2020-02-12%' OR Date_prise_compte_cmds IS NULL)" +

This is the problem, if I note the complete date as ('2020-02-12%') it does not work.

Si je note la date comme ('2020-02-1%' ) ça fonctionne un peu !
Here is the error message :
The index was out of range. It must not be negative and must be less than the size of the collection.
Parameter name: index

Who can help me ?
Thank you



Что я уже пробовал:

"AND (Date_prise_compte_cmds LIKE '2020-02-12%' OR Date_prise_compte_cmds IS NULL)" +

phil.o

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

LSB71

Как я должен хранить их в своей базе данных Sqlite?

Richard MacCutchan

Используйте один из типов дат для SQLite, как описано в документации.

3 Ответов

Рейтинг:
19

phil.o

Хорошо, SQLite. Вы должны были пометить его так, так как он не имеет истинного типа datetime.
Базы данных SQLite дата &усилителя; времени - как для обработки даты и времени в SQLite[^]

Смотрите Решение 1 и используйте параметризованные запросы; никогда не создавайте SQL-скрипты путем объединения строк, OriginalGriff прекрасно объяснил почему.

Используя ваш пример, это дало бы

using (SQLiteCommand command = m_conn.CreateCommand())
{
   command.CommandType = CommandType.Text;
   command.CommandText =
      "SELECT * FROM Tble_Commande INNER JOIN Tble_Demande ON" + 
      " (Tble_Demande.dmd_ID = Tble_Commande.cmd_ID)" +
      " WHERE Tble_Commande.Annee = ?" +  
      " AND (Reference IS NULL OR Reference LIKE ?)" +
      " AND (Designations IS NULL OR Designations LIKE ?)" +
      " AND (Date_prise_compte_cmds IS NULL OR date(Date_prise_compte_cmds) = ?)" +
      " AND (Lieu_livraison IS NULL OR Lieu_livraison LIKE ?)" +
      " AND (Imputation IS NULL OR Imputation LIKE ?)" +
      " AND (Type_cmds IS NULL OR Type_cmds LIKE ?)";
   SQLiteParameter param;

   param = new SQLiteParameter();
   param.Value = Annee_en_Cour;
   command.Parameters.Add(param);

   param = new SQLiteParameter();
   param.Value = $"%{Txt_P4_recherche_Ref.Text}%";
   command.Parameters.Add(param);

   param = new SQLiteParameter();
   param.Value = $"%{Txt_P4_recherche_Article.Text}%";
   command.Parameters.Add(param);

   param = new SQLiteParameter();
   param.Value = Txt_P4_recherche_Date.Text;
   command.Parameters.Add(param);

   param = new SQLiteParameter();
   param.Value = $"%{Cbo_P4_recherche_lieu.Text}%";
   command.Parameters.Add(param);

   param = new SQLiteParameter();
   param.Value = $"%{Cbo_P4_recherche_Imput.Text}%";
   command.Parameters.Add(param);

   param = new SQLiteParameter();
   param.Value = $"%{Cbo_P4_recherche_TypeCmds.Text}%";
   command.Parameters.Add(param);

   // ...
} 
Обратите внимание на использование дата()[^] функция для выбора только части даты сохраненного значения. Вы должны убедиться, что дата в текстовом поле имеет формат гггг-ММ-ДД; возможно, будет целесообразно использовать DateTimePicker вместо текстового поля и правильно отформатировать его значение при назначении параметра.


LSB71

Огромное спасибо,
Я буду работать над этим вопросом и улучшать свой код ... спасибо всем.

phil.o

Пожалуйста.

Maciej Los

5ed!

Рейтинг:
0

OriginalGriff

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

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:

SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Поэтому всегда используйте параметризованные запросы! Или будьте готовы часто восстанавливать свою БД из резервной копии. Вы ведь регулярно делаете резервные копии, не так ли?

Затем, когда ваше приложение будет исправлено, начните думать о коде, который у вас есть, и о том, почему ваши даты вообще хранятся в виде строк ...


Рейтинг:
0

Richard MacCutchan

"AND (Date_prise_compte_cmds LIKE '% + Txt_P4_recherche_Date.Text + "%' OR Date_prise_compte_cmds IS NULL)" +

Вы должны изменить порядок этой команды так, чтобы она сначала проверяла Date_prise_compte_cmds IS NULL В противном случае первая часть выражения может вызвать исключение, если это поле равно null.