Избегайте двойных кавычек в SQL 2005/2008

2

Недавно у меня есть международная компания, которая была названа "BLA" BLAHBLAH "(двойные кавычки являются частью названия.)

Всякий раз, когда пользователь пытается найти эту компанию, путем ввода "Бла" или чего-то такого, поиск не выполняется с ошибкой синтаксиса на SQL-сервере.

Как я могу избежать этого, чтобы поиск не прерывался?

Пример SQL:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect
    FROM RussoundGeneral.dbo.Company c  
         LEFT JOIN RussoundGeneral.dbo.CompanyMax cm
                ON (cm.companyId = c.companyId and cm.maxID is not null)  
    WHERE CONTAINS ( companyName,  '"BLAH*' )
    GROUP BY c.companyID, c.companyName, c.dateAdded  
    ORDER BY c.companyName ASC
  • 0
    Образец кода SQL, пожалуйста?
Теги:
sql-server
full-text-search

8 ответов

6
Лучший ответ

К сожалению, двойные кавычки имеют особое значение внутри FTI, поэтому, даже если вы его параметризуете, движок FTI рассматривает его как разделитель фразы. Я не уверен, что есть простой способ включить двойные кавычки в поиск FTI. Скобки также являются особым символом, но могут быть заключены в кавычки для обработки в качестве условия запроса, но не для двойных кавычек AFAIK.

Обновление

Немного поиска говорит о том, что удвоение цитаты на "" может исправить ее - стоит попробовать. Лично я бы сделал это внутри БД, так как это деталь реализации TSQL.

Аналогично, "нужно удвоить до" перед тем, как перейти к FTI (полностью разделенный на экранирование TSQL),

  • 2
    Строковые операции в T-SQL невероятно медленные. Если запрос часто вызывается, ему лучше зафиксировать кавычки вне базы данных, прямо перед вызовом.
  • 0
    Удвоение цитаты ("") не работает.
Показать ещё 1 комментарий
7

Используйте параметризованный запрос, и все ваши проблемы с кавычками исчезнут.

Изменить: если вы не позволяете им вводить более одного слова в CONTAINS, дезинфицируйте параметр, удалив кавычки. Санирование ввода путем удаления кавычек может работать в любом случае независимо от поиска по нескольким словам.

3

Я сильно подозреваю, что вы строите SQL динамически - например.

// Bad code, do not use!
string sql = "SELECT * FROM Foo WHERE X LIKE '" + input + "%'";

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

Посмотрите на различные ответы на вопросы с тегом sql-injection для примеров того, как это сделать правильно.

  • 1
    Извините, но не. объединенный sql заставит вас словесно избить здесь ..... мной. Я не буду их терпеть.
1

Это немного теоретический ответ, но, возможно, это поможет. Краткая версия - это "использование параметров в запросе", но она помогает понять все подробности.

В стандартном SQL строки заключены в одинарные кавычки, а встроенные одинарные кавычки представлены двумя одинарными кавычками в строке:

SELECT * FROM SomeWhere
    WHERE SomeThing = 'He said, "Don''t do it!"';

В некоторых диалектах SQL вы можете вместо этого закрывать строки в двойных кавычках; вам нужно удвоить двойные кавычки, чтобы вставить один экземпляр двойной кавычки:

SELECT * FROM SomeWhere
    WHERE SomeThing = "He said, ""Don't do it!""';

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

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect
    FROM RussoundGeneral.dbo.Company c  
         LEFT JOIN RussoundGeneral.dbo.CompanyMax cm
                ON (cm.companyId = c.companyId and cm.maxID is not null)  
    WHERE CONTAINS ( companyName,  '"BLAH "BLAHBLAH" Ltd.' )
    GROUP BY c.companyID, c.companyName, c.dateAdded  
    ORDER BY c.companyName ASC;

Использование двойных кавычек:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect
    FROM RussoundGeneral.dbo.Company c  
         LEFT JOIN RussoundGeneral.dbo.CompanyMax cm
                ON (cm.companyId = c.companyId and cm.maxID is not null)  
    WHERE CONTAINS ( companyName,  """BLAH ""BLAHBLAH"" Ltd." )
    GROUP BY c.companyID, c.companyName, c.dateAdded  
    ORDER BY c.companyName ASC;

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

static const char sql_stmt[] =
"SELECT c.companyID, c.companyName, c.dateAdded,\n"
"       COUNT(cm.maxID) AS NumDirect\n"
"    FROM RussoundGeneral.dbo.Company c\n"
"         LEFT JOIN RussoundGeneral.dbo.CompanyMax cm\n"
"                ON (cm.companyId = c.companyId AND cm.maxID IS NOT NULL)\n"  
"    WHERE CONTAINS(companyName,  \"\"\"BLAH \"\"BLAHBLAH\"\" Ltd.\")\n"
"    GROUP BY c.companyID, c.companyName, c.dateAdded\n"
"    ORDER BY c.companyName ASC";

С другой стороны, если вы читаете данные от пользователя - например, название компании, то вам просто нужно убедиться, что прочитанное правильно указано.

Те, кто сказал "использовать параметры", являются правильными - он намного проще и надежнее и менее уязвим для SQL-инъекций (см. XKCD если вы еще этого не видите). Но если вы понимаете основы, вы можете адаптироваться к реальным требованиям вашей системы.

Заключительное примечание: в стандартном SQL двойные кавычки заключают "разделимые идентификаторы". То есть двойные кавычки окружают имя, которое должно рассматриваться как имя чего-либо в базе данных, а не как строковый литерал. В MS SQL Server [квадратные скобки] служат той же цели; то, что находится между скобками, является имя столбца или что-то внутри базы данных. Многие системы более гибкие, чем это; не все системы одинаковы в том, как они отклоняются от стандарта.

0

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

Преобразуя свои строки в HTML до ВСТАВКИ или ОБНОВЛЕНИЯ, вы избегаете всякого путаницы, связанной с управлением кавычками. В SELECT время будет легко конвертировать из HTML. В отчетное время (поскольку инструменты отчетности (такие как Crystal Reports) предлагают вариант форматирования HTML), вам даже не нужно ничего делать, чтобы отображать данные правильным образом.

Кстати, не забудьте повесить парня, который изобрел это название компании.

0

должно быть что-то вроде

string sqlCommand = "SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect FROM RussoundGeneral.dbo.Company c LEFT JOIN RussoundGeneral.dbo.CompanyMax cm ON (cm.companyId = c.companyId and cm.maxID is not null ) WHERE CONTAINS ( companyName,  '@strVal' ) group by c.companyID, c.companyName, c.dateAdded ORDER BY c.companyName ASC"
SqlCommand command = new SqlCommand(strSQLCommand, conn); 
SqlCommand.Parameters.AddWithValue("@strval", SearchTextBox.Text); 
0

Попробуйте использовать ключевое слово escape:

SELECT c.companyID, c.companyName, c.dateAdded, count(cm.maxID) as NumDirect 
FROM RussoundGeneral.dbo.Company c          
LEFT JOIN RussoundGeneral.dbo.CompanyMax cm 
ON (cm.companyId = c.companyId and cm.maxID is not null )  
WHERE CONTAINS ( companyName,  '\"BLAH*' ) escape '\'
group by c.companyID, c.companyName, c.dateAdded  ORDER BY c.companyName ASC
0

Вы пытались заменить символ символом ASCII?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню