Member 11045819 Ответов: 4

System.data.sqlclient.sqlexception: "неправильный синтаксис рядом с "o". " кто-нибудь знает, что это за проблема?


private void LoadData_Click(object sender, EventArgs e)
{
   using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["cn"].ConnectionString))
   {
      if (db.State == ConnectionState.Closed)
         db.Open();
      string query = "select o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDate" +
         "from Orders o inner join Customers c on o.CustomerID = c.CustomerID" +
         $" Where o.OrderDate between convert(varchar(25),'{dtFromDate.EditValue}',103) and convert(varchar(25),'{dtToDate.EditValue}',103)";
      ordersBindingSource.DataSource = db.Query(query, commandType: CommandType.Text);
   }

пожалуйста, помогите мне..? System.data.sqlclient.sqlexception: "неправильный синтаксис рядом с "o". " кто-нибудь знает, что это за проблема?

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

private void LoadData_Click(object sender, EventArgs e)
{
   using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["cn"].ConnectionString))
   {
      if (db.State == ConnectionState.Closed)
         db.Open();
      string query = "select o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDate" +
         "from Orders o inner join Customers c on o.CustomerID = c.CustomerID" +
         $" Where o.OrderDate between convert(varchar(25),'{dtFromDate.EditValue}',103) and convert(varchar(25),'{dtToDate.EditValue}',103)";
      ordersBindingSource.DataSource = db.Query(query, commandType: CommandType.Text);
   }

4 Ответов

Рейтинг:
2

Wendelius

Чтобы добавить незначительную деталь к предыдущим ответам. Одна из проблем с которой вы столкнулись заключается в том что после конкатенации у вас нет места до этого FROM.

Взгляните на это

string query = "select o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDate" +
         "from Orders o inner join Customers c o

В целом, лично я предпочитаю использовать дословные строки, которые позволяют красиво форматировать SQL-операторы. Иначе говоря
string query = @"
SELECT o.OrderID, 
       c.CustomerID, 
       c.ContactName, 
       c.Address, 
       c.PostalCode, 
       c.City, 
       c.Phone, 
       o.OrderDate
FROM Orders o 
INNER JOIN Customers c ON o.CustomerID = c.CustomerID ......

Для получения дополнительной информации взгляните на @ - Ссылка На C# | Microsoft Docs[^]


Рейтинг:
1

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;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

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

В этом конкретном случае он не будет рисковать тем, что ваша БД будет удалена, - он сделает что-то гораздо хуже. Это может привести к тому, что ваши данные будут неточными, или смешанными неточными с точными, или потерпят неудачу в конце месяца и т. д.
Вы указываете строковый формат европейской даты - и это нормально (ish) до тех пор, пока система баз данных не будет изменена, обновлена или реконфигурирована. Если используемая локаль даты не соответствует европейскому формату даты, то вы начнете получать реальные проблемы - и новая установка ПК / нового SQL Server будет по умолчанию использовать американские даты, и ваши проблемы начнутся ...
Просто используйте параметры и передайте фактическое значение вместо текстовой строки, и все это исчезнет.

И посмотрите на свой код:
string query = "select o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDate" +
"from Orders o inner join Customers c on o.CustomerID = c.CustomerID" +
Давайте вырежем шлак, чтобы вы могли видеть, в чем проблема:
string query = "... , o.OrderDate" +
"from Orders o ..." +
Соедините их вместе, и строка, переданная в SQL, будет:
"... , o.OrderDatefrom Orders o ..."

Тебе нужно место внутри.


Рейтинг:
0

F-ES Sitecore

Посмотрите на значение "query", какой SQL он содержит? Возможно

select o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDatefrom Orders o


это неверно, вы пропускаете пробел перед "от".

string query = "select o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDate" +
            " from Orders o inner join Customers c on o.CustomerID = c.CustomerID" +


Рейтинг:
0

MadMyche

Несколько предложений для этого и для дальнейшего развития.

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

2. Переменные - Лучшая практика говорит значения, переданные должны быть фактические значения типа datetime в SQL-таблицу, а также значения, переданные.

3. Вместо "string дополнение", рекомендуется использовать класс StringBuilder. Это делает код немного чище; и при использовании метода AppendLine есть пробел в запросе, если вы забыли пробел в конце строки.

Это даст вам изменения что-то вроде этого, чтобы построить свой SQL-оператор

StringBuilder qb = new StringBuilder();
qb.AppendLine("SELECT o.OrderID, c.CustomerID, c.ContactName, c.Address, c.PostalCode, c.City, c.Phone, o.OrderDate ");
qb.AppendLine("FROM   Orders o INNER JOIN Customers c ON o.CustomerID = c.CustomerID ");
qb.AppendLine("WHERE  o.OrderDate BETWEEN @DateFrom AND @DateTo ");

SqlCommand cmd = new SqlCommand(qb.ToString(), db);
// cmd.CommandType = CommandType.Text   // NOT NEEDED- this is default
cmd.Parameters.AddWithValue("@DateFrom", dtFromDate.EditValue); // VERIFY Type
cmd.Parameters.AddWithValue("@DateTo", dtToDate.EditValue);     // VERIFY Type

Далее по строке; вы можете переместить фактический запрос в свою базу данных, возможно, в виде представления или в виде хранимой процедуры(предпочтительно). Вам все равно понадобятся параметры, но вы найдете код, необходимый в C#, чтобы иметь несколько меньше строк, но параметры можно было бы сохранить как есть.

С помощью этого запроса, определяющего представление, ваш код изменится на
string query = "SELECT * FROM vw_OrdersCustomers WHERE OrderDate BETWEEN @DateFrom AND @DateTo";

SqlCommand cmd = new SqlCommand(query, db);
cmd.Parameters.AddWithValue("@DateFrom", dtFromDate.EditValue);
cmd.Parameters.AddWithValue("@DateTo", dtToDate.EditValue);
И как хранимая процедура это будет выглядеть следующим образом; обратите внимание, что теперь вам нужно будет определить CommandType
string query = "dbo.OrdersCustomers_SelectByDateRange";

SqlCommand cmd = new SqlCommand(query, db);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@DateFrom", dtFromDate.EditValue);
cmd.Parameters.AddWithValue("@DateTo", dtToDate.EditValue);mmandType.Text);