ishuishika Ответов: 4

Как решить неправильный синтаксис рядом с "диском".


Привет,

Я хочу восстановить данные с помощью c#, но он показывает ошибку.

Ошибка:

Incorrect syntax near 'DISK'.

Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.


Пожалуйста, помогите мне.

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

private void button2_Click(object sender, EventArgs e)
        {

            string servername = textBox1.Text;
            string databasename = textBox3.Text;

            SqlConnection con = new SqlConnection(@"Data Source =" + servername + " ; Initial Catalog=" + databasename + "; Integrated Security =True");

            con.Open();

            string str = "USE master;";
            string str1 = "ALTER DATABASE " + databasename + " SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
            string str3 = "RESTORE DATABASE " + databasename + "FROM DISK = '" + textBox2.Text + "' WITH REPLACE ";

            SqlCommand cmd = new SqlCommand(str, con);
            SqlCommand cmd1 = new SqlCommand(str1, con);
            SqlCommand cmd3 = new SqlCommand(str3, con);

            cmd.ExecuteNonQuery();
            cmd1.ExecuteNonQuery();
            cmd3.ExecuteNonQuery();
            MessageBox.Show("DATABASE RECOVERED Successful. if you want to get the recovered data you must close the software and rerun again.");
            con.Close();
            Application.Exit();
            this.Hide();            
        }

4 Ответов

Рейтинг:
21

phil.o

Вам не хватает пробела между именем базы данных и именем пользователя. FROM пункт в str3:

string str3 = $"RESTORE DATABASE {databasename} FROM DISK = '{textBox2.Text}' WITH REPLACE ";

Обратите внимание, что построение SQL-запроса путем объединения строк, особенно когда одна из них получена из пользовательского ввода, оставляет ваш код широко открытым для атак SQL-инъекций.
Если бы кто-то вошел '; DELETE DATABASE (databasename);-- например, в textBox2 соответствующая база данных будет удалена, и единственным вариантом, который останется, будет восстановление ее из резервной копии. (Вы можете искать частые ответы по OriginalGriff об этом, который объясняет это гораздо лучше, чем я). Также рекомендуется заключать ресурсоемкие, одноразовые ресурсы, такие как SQL-команда, например, в using блок. Это также было бы верно для вашего объекта соединения.

Правка: к сожалению, вы не можете использовать параметризованный запрос с помощью RESTORE команда. Я изменил следующий блок, чтобы избежать путаницы. Однако имейте в виду трюк с использованием блока; это привычка, которую стоит поймать.
using (SqlConnection con = new SqlConnection($"Data Source={servername}; Initial Catalog={databasename}; Integrated Security=True"))
{
   con.Open();
   // ...
   string str3 = $"RESTORE DATABASE {databasename} FROM DISK = '{textBox2.Text}' WITH REPLACE ";
   using (SqlCommand cmd3 = new SqlCommand(str3, con))
   {
      cmd3.ExecuteNonQuery();
      // ...
   }
}

Но обратите внимание, что решение 1 в любом случае указывает на гораздо более чистый способ резервного копирования вашей базы данных.


ishuishika

Огромное спасибо... это решило мои проблемы.

Конечно, я буду следовать тому, что вы сказали.. :)

phil.o

Пожалуйста :)

Рейтинг:
20

Patrice T

Боюсь, вы пропустили пробел в запросе:

string str3 = "RESTORE DATABASE " + databasename + " FROM DISK = '" + textBox2.Text + "' WITH REPLACE ";
//                                                  ^ a space was missing here

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

Не решение вашего вопроса, а еще одна проблема, которая у вас есть.
Никогда не создавайте SQL-запрос путем объединения строк. Рано или поздно вы сделаете это с помощью пользовательских вводов, и это откроет дверь к уязвимости под названием "SQL-инъекция", она опасна для вашей базы данных и подвержена ошибкам.
Одна кавычка в имени - и ваша программа выйдет из строя. Если пользователь вводит имя, например "Брайан О'Коннер", может привести к сбою вашего приложения, это уязвимость SQL-инъекции, и сбой-это наименьшая из проблем, вредоносный пользовательский ввод, и он продвигается к командам SQL со всеми учетными данными.
SQL-инъекция - Википедия[^]
SQL-инъекция[^]
Атаки SQL-инъекций на примере[^]
PHP: SQL-инъекция - руководство пользователя[^]
Шпаргалка по предотвращению инъекций SQL - OWASP[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? - Обмен Стеками Информационной Безопасности[^]


Richard Deeming

К сожалению, нет способа использовать параметры с помощью RESTORE DATABASE команда.

Но если вы не доверяете пользователю, который запускает этот код, то SQL-инъекция-это наименьшая из ваших проблем! :)

ishuishika

@ Patrice T ..большое вам спасибо... После предоставления пространства он теперь работает нормально..

На самом деле я не знал, что простое пространство между " От " было решением моей проблемы.
еще раз большое вам спасибо..

Patrice T

Пожалуйста

Рейтинг:
1

OriginalGriff

Взгляните на это: Резервное копирование базы данных SQL на языке C#[^] - существуют классы специально для резервного копирования и восстановления.


Рейтинг:
1

Richard MacCutchan

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


ishuishika

Извините..

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

Еще раз извинись передо мной. Я буду отлаживать и исследовать с самого моего конца.

Спасибо.

Richard MacCutchan

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