Member 12708425 Ответов: 1

Поиск по дате в базе данных SQL


У меня есть один код c#, который принимает ввод от пользователя в текстовом поле.Есть 2 тестовых поля для ввода даты от и до.Пользователю необходимо ввести дату в формате ДД/ММ/гггг и выполнить поиск событий, произошедших за этот промежуток времени.Но я обнаружил, что поиск не является правильным.Я предполагаю, что это связано с форматом поля времени в моей базе данных, который дается мне каким-то внешним приложением в таблице SQL, из которой я выполняю поиск.

Мой код таков
using (SqlCommand cmd2 = new SqlCommand("SELECT " + "SELECT * FROM [FAULT_SUMMARY] where STRIGGERTIME between '" + textBox1.Text + "' AND '" + textBox2.Text + "' AND [STATION_NAME] like '%" + textBox3.Text + "%'"))


Поле в базе данных имеет вид Var char и выглядит следующим образом
13/10/2016 12:25:06.749016
Обратите внимание, что поле STRIGGERTIME содержит фактическую дату и время с точностью до миллисекунды, и оно обязательно должно отображаться после поиска.

Может ли кто-нибудь помочь мне решить то же самое.

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

Попробовал преобразовать STRIGGERTIME из verchar в формат даты и времени в том же командном запросе Sql. но не получилось.

1 Ответов

Рейтинг:
1

OriginalGriff

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

Преобразуйте вводимые пользователем данные в значение DateTime с помощью DateTime.Попробуйте проанализировать и сообщить о любой ошибке:

DateTime dtStart;
if (!DateTime.tryParse(textBox1.text, out dtStart))
   {
   ... report a problem to the user ...
   return;
   }
Сделайте то же самое с конечным значением, а затем передайте значения в SQL в качестве параметров:
using (SqlCommand cmd = new SqlCommand("SELECT * FROM [FAULT_SUMMARY] WHERE STRIGGERTIME BETWEEN @ST AND @END AND [STATION_NAME] LIKE '%' + @SN + '%'"))
   {
   cmd.Parameters.AddWithValue("@ST", dtStart);
   cmd.Parameters.AddWithValue("@END", dtEnd);
   cmd.Parameters.AddWithValue("@SN", textBox3.text);
   ...


И еще две вещи:
1) прекратите использовать все заглавные буквы для имен столбцов: cammelCase намного более удобочитаем, как и для имен переменных C#.
2) Сделайте себе одолжение и перестаньте использовать имена Visual Studio по умолчанию для всего - вы можете помнить, что" TextBox8 " - это номер мобильного телефона сегодня, но когда вам придется изменить его через три недели, вы тогда это сделаете? Используйте описательные имена - например, "tbMobileNo" - и ваш код станет легче читать, более самодокументируемым, более легким в обслуживании-и на удивление быстрее кодировать, потому что Intellisense может добраться до" tbMobile "за три нажатия клавиш, где" TextBox8 " занимает размышление и 8 нажатий клавиш...


Member 12708425

Но если до этого мне нужно было преобразовать дату и время в поле STRIGGERTIME в базе данных SQL в формат DateTime, чтобы входные данные, заданные в текстовых полях, соответствовали должным образом.
Мое поле STRIGGERTIME содержит дату и время в приведенном ниже формате,а поле VARCHAR в SQL DB.

STRIGGERTIME
31/08/2015  14:42:00.737607
07/04/2016  13:00:31.502937
07/04/2016  13:00:31.606000
12/05/2016  16:36:36.351765
01/06/2016  16:45:33.793131
01/06/2016  16:45:34.741000
12/06/2016  15:45:32.535777
12/06/2016  15:45:32.661000
26/08/2016  10:14:09.815681

Я абсолютно новичок в программировании на C#. Не могли бы вы помочь мне в этом случае, как преобразовать поле striggertime datetime так, чтобы SQL мог правильно искать. Также, пожалуйста, расскажите, как поместить календарь в текстовые поля, чтобы пользователь мог выбрать дату оттуда сам.
Я помещаю свой код ниже.

namespace AFASSearch
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
            this.Text = "AFAS Historian Report";
           // this.BackColor = Color.FromArgb(255, 232, 232); // this should be pink-ish
            BackColor = Color.Blue;
        }
        //Initializing the connection with database name AFAS in SQL Server XXXXXX.
        SqlConnection conn = new SqlConnection("Server=XXXXXX;Database=AFAS_HISTORIAN;Integrated security=true");

 private void textBox1_TextChanged(object sender, EventArgs e)
        {
                               
        }
 private void button1_Click(object sender, EventArgs e)
        {

           if (textBox1.Text == "" || textBox2.Text == "")
            {
                conn.Open();
                MessageBox.Show("Don't leave any textbox empty.Enter date in DD/MM/YYYY format");
                conn.Close();
            }
            //else if
            else if (textBox3.Text != null)
            {
                conn.Open();
                using (SqlCommand cmd2 = new SqlCommand("SELECT * FROM [AFAS_FAULT_SUMMARY] where STRIGGERTIME between '" + textBox1.Text + "' AND '" + textBox2.Text + "' AND [SSUBSTATION_NAME] like '%" + textBox3.Text + "%'"))
                {
                    using (SqlDataAdapter da2 = new SqlDataAdapter())
                    {
                        cmd2.Connection = conn;
                        da2.SelectCommand = cmd2;
                        using (System.Data.DataTable dt2 = new System.Data.DataTable())
                        {
                            da2.Fill(dt2);
                          dt2.Columns[0].ColumnName = "DR File Name";
                          dt2.Columns[1].ColumnName = "Trigger Time"; //STRIGGERTIME
                          //To auto resize the column use the following
 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
                            //----------------------------------
                            dataGridView1.Visible = true;
                            if (dt2.Rows.Count == 0)
                            {
                                dataGridView1.Visible = false;
                                MessageBox.Show("Date entered are either in wrong format or outside the range that are in database");
                            }
                            dataGridView1.DataSource = dt2;
                            textBox1.Text = "";
                            textBox2.Text = "";
                            textBox3.Text = "";
                        }
                    }
                }
                conn.Close();
            }

       }
      }	 
	 }

OriginalGriff

Тогда вы допустили огромную дизайнерскую ошибку, которую нужно исправить как можно быстрее. Изменить что SQL столбец типа nvarchar в datetime (самый простой способ это добавить новый столбец, который имеет тип DateTime и nullable, и написать на C# программа для чтения существующего столбца, разобрать его в значение типа datetime, используя метод tryparseexact и записать значение нового столбца. Затем вы можете удалить старый столбец и изменить все программное обеспечение, которое ссылается на него.

Всегда храните данные в соответствующих типах столбцов - хранение данных в виде строк является одновременно расточительным и опасным, поскольку значения, которые вы показываете, слишком легко неверно истолковать SQL при их преобразовании. Он не знает, что они являются dd/MM/yyyy и, вероятно, по умолчанию будет MM/dd/yyyy, поскольку SQL server является американским. Таким образом, он будет выдавать исключения или давать вам неправильные значения при их преобразовании.

Не забывайте, что порядок сортировки строк основан на символах. Это означает, что если речь идет о заказе двух строковых дат, то порядок таков::
21/01/2147
21/12/1946
30/01/2017
31/01/2016
Что совершенно бесполезно!

Member 12708425

Я нашел кое-что еще. У меня есть поле в той же БД SQL, которое имеет значение времени в целочисленном виде.

1441085751
1460014930
1460014940
1463053840
1464781135
 

Итак, если я смогу преобразовать свои входные данные TtextBox1 и textBox2 в целое число, то решит ли это проблему? Я пытался сделать следующее, но безуспешно.
int i,j;                              i = Convert.ToInt32(textBox1.Text);               j = Convert.ToInt32(textBox2.Text);
и попытался передать значение в SQL-запросе.Но безуспешно.

OriginalGriff

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

Перестаньте гадать: измените свою базу данных, чтобы использовать значения даты и времени, и сделайте это правильно!

Member 12708425

Наконец, у меня есть какое-то решение относительно преобразования времени.На самом деле время, которое я получаю в SQL db, находится в формате эпохи Unix. Поэтому используйте следующее (С помощью одного из моих коллег).

public static long ConvertDateTimeTo(DateTime mydate)
        {
            //const double LongAdj = 1000.0;
            DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            return (long)((mydate - UnixEpoch).TotalSeconds);
        }