ra.eremeev Опубликовано 16 июля, 2016 Поделиться Опубликовано 16 июля, 2016 Всем привет! Собственно вопрос: как осуществить поиск по таблице, в полях которой значения в кириллице (юникод)? Например: SELECT * FROM Table WHERE Column1 like '%Наименование%' будет искать только строку, содержащую 'Наименование'. Если встретиться 'наименование' - в результат не попадет UPPER на кириллицу не работает! В латинице поиск при использовании LIKE регистронезависимый. Знаю, что у SQLite с этим проблемы, а решения кроме как использования неких сторонних сборок не нашел в инете. Форум тоже просмотрел - ничего. Не думаю, что никто не сталкивался. Поделитесь опытом, пож-та! Цитата Ссылка на комментарий
0 Vitaldj Опубликовано 16 июля, 2016 Поделиться Опубликовано 16 июля, 2016 (изменено) Опыт есть. Есть два пути. 1) самый простой, но выполнимый только в одном случае. Если большая только первая буква и/или все меленькие. Я делаю два like через or где в первом случае первая буква в нижнем регистре, а второй в верхнем. (Делаю функцию, где перевожу все в н жний а в первую в верхний) 2) тут я не знаю как во встроенных компонентах, может быть тоже самое, но я использую от devart. Там есть встроенные функции в sql. Я создаю такую функцию внутри запроса, а во внешнем обработчике пишу ее обработку. Обычно перевожу все символы до к верхнему регистру. Т.е: select * from таблица where fUpp( column1) like fUpp(%column1%). Где fUpp и есть функция внутри запроса. Изменено 16 июля, 2016 пользователем Vitaldj Цитата Ссылка на комментарий
0 ra.eremeev Опубликовано 17 июля, 2016 Автор Поделиться Опубликовано 17 июля, 2016 Vitaldj, спасибо за ответ! Оба варианта понятны, но: 1. Заглавные буквы встречаются не только вначале текста (например, встречаются аббревиатуры или имена собственные) 2. хотелось бы решение именно на стандартных компонентах Есть ли еще варианты? Цитата Ссылка на комментарий
0 Vitaldj Опубликовано 17 июля, 2016 Поделиться Опубликовано 17 июля, 2016 2 часа назад, ra.eremeev сказал: Vitaldj, спасибо за ответ! Оба варианта понятны, но: 1. Заглавные буквы встречаются не только вначале текста (например, встречаются аббревиатуры или имена собственные) 2. хотелось бы решение именно на стандартных компонентах Есть ли еще варианты? Мне кажется, есть и в стандартных компонентах те функции, которые я использую в devart. Может кто из форумчан подскажет? Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 18 июля, 2016 Поделиться Опубликовано 18 июля, 2016 Проблема не в компоненте, не в Delphi и не в Embarcadero. Это вопрос настройки сервера БД, конкретной таблицы и подключения к БД. А именно параметров сортировки и представления. Подробно на английском, подробно на русском. Если сильно не вникать, везде, где говорится о кодировке, нужно выбирать значение «Cyrillic_General_CI_AS». Цитата Ссылка на комментарий
0 Vitaldj Опубликовано 18 июля, 2016 Поделиться Опубликовано 18 июля, 2016 5 минут назад, Pax Beach сказал: Проблема не в компоненте, не в Delphi и не в Embarcadero. Это вопрос настройки сервера БД, конкретной таблицы и подключения к БД. А именно параметров сортировки и представления. Подробно на английском, подробно на русском. Если сильно не вникать, везде, где говорится о кодировке, нужно выбирать значение «Cyrillic_General_CI_AS». Извините, а причем тут Microsoft SQL сервер? Мы про SQlite. Это немного разные вещи)))) С MSSQL как раза нет таких проблем)) Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 18 июля, 2016 Поделиться Опубликовано 18 июля, 2016 (изменено) 2 часа назад, Vitaldj сказал: Извините, а причем тут Microsoft SQL сервер? Мы про SQlite. Это немного разные вещи)))) С MSSQL как раза нет таких проблем)) Я говорю про все диалекты SQL. Когда идет речь о том, что не работает сравнение в where или like, нужно смотреть настройки кодировки на сервере и в строке соединения. UPD: Прочитал, что есть проблема сортировки в SQLite. Проверил — есть, и LIKE, и ORDER BY. Прочитал ответ разработчиков — подход порадовал. Потребуется воспользоваться функцией sqlite3_create_collation (есть в компонентах FireDAC, UniDAC, модуле RTL\System.Sqlite.pas). Я нашел пример только на C. Может у Вас получится воспользоваться — будем рады посмотреть пример. Изменено 18 июля, 2016 пользователем Pax Beach Rusland и Евгений Корепов 2 Цитата Ссылка на комментарий
0 Кривяков Виталий Опубликовано 18 июля, 2016 Поделиться Опубликовано 18 июля, 2016 Добрый день! В стандартных компонента есть механизм по встраиванию своих функций в SQLite. ... // создаю встроенную функцию ru_lower F1 := TFDSQLiteFunction.Create(nil); F1.DriverLink := WC1; F1.FunctionName := 'ru_lower'; F1.ArgumentsCount := 1; F1.OnCalculate := ru_lower; ... procedure TORMmanager.ru_lower(AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs; AOutput: TSQLiteOutput; var AUserData: TObject); begin AOutput.AsString := AInputs[0].AsString.ToLower; end; SQL: select name from users where ru_lower(name) like '%иван%' Запрос вернет все имена содержащие иван в любом регистре. Евгений Корепов, Rusland, Maximus и 3 других 6 Цитата Ссылка на комментарий
0 Vitaldj Опубликовано 18 июля, 2016 Поделиться Опубликовано 18 июля, 2016 20 минут назад, Кривяков Виталий сказал: Добрый день! В стандартных компонента есть механизм по встраиванию своих функций в SQLite. ... // создаю встроенную функцию ru_lower F1 := TFDSQLiteFunction.Create(nil); F1.DriverLink := WC1; F1.FunctionName := 'ru_lower'; F1.ArgumentsCount := 1; F1.OnCalculate := ru_lower; ... procedure TORMmanager.ru_lower(AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs; AOutput: TSQLiteOutput; var AUserData: TObject); begin AOutput.AsString := AInputs[0].AsString.ToLower; end; SQL: select name from users where ru_lower(name) like '%иван%' Запрос вернет все имена содержащие иван в любом регистре. Вот как раз об этом я и говорил! Только повторюсь, использую devart, там такой же принцип))). Цитата Ссылка на комментарий
0 ra.eremeev Опубликовано 19 июля, 2016 Автор Поделиться Опубликовано 19 июля, 2016 В 18.07.2016 в 15:40, Кривяков Виталий сказал: Добрый день! В стандартных компонента есть механизм по встраиванию своих функций в SQLite. ... // создаю встроенную функцию ru_lower F1 := TFDSQLiteFunction.Create(nil); F1.DriverLink := WC1; F1.FunctionName := 'ru_lower'; F1.ArgumentsCount := 1; F1.OnCalculate := ru_lower; ... procedure TORMmanager.ru_lower(AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs; AOutput: TSQLiteOutput; var AUserData: TObject); begin AOutput.AsString := AInputs[0].AsString.ToLower; end; SQL: select name from users where ru_lower(name) like '%иван%' Запрос вернет все имена содержащие иван в любом регистре. Виталий, спасибо! Принцип понял, но не понял как реализовать Если не затруднит, можно пример какой-нибудь? Где весь этот код набивать? Простите за глупую просьбу, но, правда, не нашел в поисковиках ничего про пользовательские функции... Цитата Ссылка на комментарий
1 Кривяков Виталий Опубликовано 22 июля, 2016 Поделиться Опубликовано 22 июля, 2016 Не вопрос. SQLITE.zip Crusader99, Andrey Efimov, Maximus и 3 других 6 Цитата Ссылка на комментарий
0 ra.eremeev Опубликовано 22 июля, 2016 Автор Поделиться Опубликовано 22 июля, 2016 4 часа назад, Кривяков Виталий сказал: Не вопрос. SQLITE.zip Виталий, огромное спасибо!!! Разобрался. Все работает! Цитата Ссылка на комментарий
0 MAR Опубликовано 11 сентября, 2017 Поделиться Опубликовано 11 сентября, 2017 В 22.07.2016 в 18:05, Кривяков Виталий сказал: Не вопрос. SQLITE.zip Сделал по образу и подобию. Кричит: [dcc32 Error] clueDBWrapper.pas(537): E2010 Incompatible types: 'TSQLiteFunctionInstance' and 'TSQLiteFunction' Чую, что собака порылась в том, что в примере есть instance Form1, а у меня класс на данный момент в "свободном полёте". Тут можно как- то выкрутиться ? Цитата Ссылка на комментарий
0 MAR Опубликовано 11 сентября, 2017 Поделиться Опубликовано 11 сентября, 2017 (изменено) Вопрос отменяется. Как всегда документация говорит одно, код- другое, подразумевается третье. Для Tokyo актуален заголовок // запуск встроенной функции регистрации соединения Procedure onCalculateConnectionRegister(AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs; AOutput: TSQLiteOutput; var AUserData: TObject); В примере невнимательно посмотрел. ))) Хотя в официозе в примере: http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/FireDAC.SQLite_Sample procedure TfrmGettingStarted.sqlFunctionCalculate(AFunc: TSQLiteFunction; AInputs: TSQLiteInputs; AOutput: TSQLiteOutput; var AUserData: TObject); Изменено 11 сентября, 2017 пользователем MAR Rusland 1 Цитата Ссылка на комментарий
0 MAR Опубликовано 11 сентября, 2017 Поделиться Опубликовано 11 сентября, 2017 Это просто какой- то праздник жизни !!! Tokyo заявляет, что no such function: .... // предок inherited Create(); // сохраняем себе БД db := @base; // соединение с драйвером drvLink := TFDPhysSQLiteDriverLink.Create(Nil); // создаём функцию для регистрации соединения sqlRegisterConnection := TFDSQLiteFunction.Create(Nil); // задаём имя sqlRegisterConnection.FunctionName := 'rConn'; // количество аргументов sqlRegisterConnection.ArgumentsCount := 2; // присваиваем обработчик sqlRegisterConnection.OnCalculate := onCalculateConnectionRegister; // активность функции sqlRegisterConnection.Active := True; А потом жду- не дождусь вызова onCalculateConnectionRegister... Отваливает в Exception при Open SQL запроса... Типа SELECT rConn(1,1) LIMIT 1; Error (0): [FireDAC][Phys][SQLite] ERROR: no such function: rConn Цитата Ссылка на комментарий
0 Galaxar Опубликовано 30 октября, 2018 Поделиться Опубликовано 30 октября, 2018 (изменено) В 18.07.2016 в 15:40, Кривяков Виталий сказал: Добрый день! В стандартных компонента есть механизм по встраиванию своих функций в SQLite. ... // создаю встроенную функцию ru_lower F1 := TFDSQLiteFunction.Create(nil); F1.DriverLink := WC1; F1.FunctionName := 'ru_lower'; F1.ArgumentsCount := 1; F1.OnCalculate := ru_lower; ... procedure TORMmanager.ru_lower(AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs; AOutput: TSQLiteOutput; var AUserData: TObject); begin AOutput.AsString := AInputs[0].AsString.ToLower; end; SQL: select name from users where ru_lower(name) like '%иван%' Запрос вернет все имена содержащие иван в любом регистре. А можно чуть подробней про свои функции в компонентах FireDAC. Как именно использовать ваш код? Все, разобрался. Изменено 30 октября, 2018 пользователем Galaxar Цитата Ссылка на комментарий
-3 Dstaryh Опубликовано 23 февраля, 2019 Поделиться Опубликовано 23 февраля, 2019 Предлагаю простой вариант перевода edit1.text в верхний регистр для последующего поиска по СУБД из введенных данных в edit1, работает хоть с кириллицей, хоть с латиницей! правда через дополнительный memo, свойства которого в инспекторе ставим CharCase = ecUpperCase, Visible = false, и в обработчиках событий OnChangeTracking обоих компонентов пишем процедуры: procedure TForm1.Edit1ChangeTracking(Sender: TObject); begin Memo1.Text:= AnsiUpperCase(edit1.Text); end; procedure TForm1.Memo1ChangeTracking(Sender: TObject); begin edit1.Text:=memo1.Text; FDQuery1.Close; FDQuery1.SQL.Text:='SELECT * FROM <имя таблицы> WHERE <имя поля> like '+QuotedStr('%'+Edit1.Text+'%'); FDQuery1.Open; end; Цитата Ссылка на комментарий
0 IVGSoft Опубликовано 25 февраля, 2019 Поделиться Опубликовано 25 февраля, 2019 В 23.02.2019 в 13:01, Dstaryh сказал: Предлагаю простой вариант перевода edit1.text в верхний регистр для последующего поиска по СУБД из введенных данных в edit1, работает хоть с кириллицей, хоть с латиницей! правда через дополнительный memo, свойства которого в инспекторе ставим CharCase = ecUpperCase, Visible = false, и в обработчиках событий OnChangeTracking обоих компонентов пишем процедуры: procedure TForm1.Edit1ChangeTracking(Sender: TObject); begin Memo1.Text:= AnsiUpperCase(edit1.Text); end; procedure TForm1.Memo1ChangeTracking(Sender: TObject); begin edit1.Text:=memo1.Text; FDQuery1.Close; FDQuery1.SQL.Text:='SELECT * FROM <имя таблицы> WHERE <имя поля> like '+QuotedStr('%'+Edit1.Text+'%'); FDQuery1.Open; end; Вы, наверное, не правильно поняли проблему. Перевести строку в аппер для подсовывания в запрос не проблема. Проблема в том, что SQLite не умеет преобразовывать кирилицу в аппер (или лоуер)! Цитата Ссылка на комментарий
0 #WAMACO Опубликовано 25 февраля, 2019 Поделиться Опубликовано 25 февраля, 2019 12 часов назад, IVGSoft сказал: Вы, наверное, не правильно поняли проблему. Перевести строку в аппер для подсовывания в запрос не проблема. Проблема в том, что SQLite не умеет преобразовывать кирилицу в аппер (или лоуер)! LiteDAC и UniDAC умеет решать эту проблему. без плясок с бубном. из коробки Цитата Ссылка на комментарий
0 Barbanel Опубликовано 26 февраля, 2019 Поделиться Опубликовано 26 февраля, 2019 16 часов назад, #WAMACO сказал: LiteDAC и UniDAC умеет решать эту проблему Юзаем UniDAC. Столкнулись недавно с тем, что некоторые символы юникода не преобразовываются в аппер/ловер кейс (ни на мобильных, ни на виндовс). Если точнее, то вот эти -> ü, ö, ä Насколько я понял, это особенности именно SQLite, а не компонентов. Расскажите плиз, как вы победили эту проблему? Буду очень признателен. Цитата Ссылка на комментарий
0 #WAMACO Опубликовано 26 февраля, 2019 Поделиться Опубликовано 26 февраля, 2019 6 минут назад, Barbanel сказал: Юзаем UniDAC. Столкнулись недавно с тем, что некоторые символы юникода не преобразовываются в аппер/ловер кейс (ни на мобильных, ни на виндовс). Если точнее, то вот эти -> ü, ö, ä Насколько я понял, это особенности именно SQLite, а не компонентов. Расскажите плиз, как вы победили эту проблему? Буду очень признателен. Какая версия Unidac у вас? это поправили буквально в последних выпусках Цитата Ссылка на комментарий
0 Barbanel Опубликовано 26 февраля, 2019 Поделиться Опубликовано 26 февраля, 2019 (изменено) 11 минут назад, #WAMACO сказал: Какая версия Unidac у вас? 7.4.12 Попробую на досуге собрать тестовый проект и проверить еще раз. Изменено 26 февраля, 2019 пользователем Barbanel Цитата Ссылка на комментарий
0 Елена Опубликовано 17 сентября, 2021 Поделиться Опубликовано 17 сентября, 2021 В 26.02.2019 в 18:33, #WAMACO сказал: Какая версия Unidac у вас? это поправили буквально в последних выпусках подскажите, как эта проблема решается в Unidac? Цитата Ссылка на комментарий
0 Vitaldj Опубликовано 17 сентября, 2021 Поделиться Опубликовано 17 сентября, 2021 34 минуты назад, Елена сказал: подскажите, как эта проблема решается в Unidac? Не совсем понял (вверху в постах), какое отношение имеют к кириллице символы ü, ö, ä . Я использую liteDac, скорее всего в UniDac так же: Я кидаю на форму компонент TLiteUserFunction , в его событии OnExecute создаю следующий код: procedure TDataModule2.LiteUserFunc_upcaseExecute(Sender: TObject; Params: TDAParams; var ResultValue: Variant); begin ResultValue := AnsiUpperCase(TLiteUserFunction(Sender).Params.ParamByName('Value').AsString); end; А далее прямо в SQL коде, вставляю эту внешнюю функцию. Вот как пример: select [mnn] from [vrem_for_grupp] where LiteUserFunc_upcase([mnn]) = ('''+trim(mn.ToUpper)+ ''') И получается, параметры, которые передаю во внутрь я перевожу в верхний регистр прямо при передачи (в примере это mn.toUpper ), а внутри SQL, эти параметры в верхний регистр переводит внутренняя(внешняя) функция, в данном случае LiteUserFunc_upcase. Цитата Ссылка на комментарий
0 Елена Опубликовано 17 сентября, 2021 Поделиться Опубликовано 17 сентября, 2021 23 минуты назад, Vitaldj сказал: Не совсем понял (вверху в постах), какое отношение имеют к кириллице символы ü, ö, ä . Я использую liteDac, скорее всего в UniDac так же: Я кидаю на форму компонент TLiteUserFunction , в его событии OnExecute создаю следующий код: procedure TDataModule2.LiteUserFunc_upcaseExecute(Sender: TObject; Params: TDAParams; var ResultValue: Variant); begin ResultValue := AnsiUpperCase(TLiteUserFunction(Sender).Params.ParamByName('Value').AsString); end; А далее прямо в SQL коде, вставляю эту внешнюю функцию. Вот как пример: select [mnn] from [vrem_for_grupp] where LiteUserFunc_upcase([mnn]) = ('''+trim(mn.ToUpper)+ ''') И получается, параметры, которые передаю во внутрь я перевожу в верхний регистр прямо при передачи (в примере это mn.toUpper ), а внутри SQL, эти параметры в верхний регистр переводит внутренняя(внешняя) функция, в данном случае LiteUserFunc_upcase. спасибо за наводку, но вот действительно в UniDac нет таких компонентов. Нашла, что есть TLiteUtils.RegisterFunction, где последним параметром идет TLiteFunction, но как ее правильно использовать я пока не могу понять((( Цитата Ссылка на комментарий
0 neon Опубликовано 26 сентября, 2022 Поделиться Опубликовано 26 сентября, 2022 Доброго времени суток. Иной раз "лучше поздно, чем никогда". Тоже недавно столкнулся с этой проблемой (некорректная работа UPPER в SQLite). При поиске наткнулся на эту статью: https://habr.com/ru/sandbox/98493/ Автор, к сожалению, неизвестен. Но на ее основе удалось сформировать несколько функций в среде Delphi. Если кому-то поможет - буду рад. См. здесь:https://roamer55.ru/main_programming/delphi/delphi_10_2_vcl/d10_funcs_db/d10_funcs_db_sqlite/d10_funcs_db_sqlite_upper/ Цитата Ссылка на комментарий
Вопрос
ra.eremeev
Всем привет!
Собственно вопрос: как осуществить поиск по таблице, в полях которой значения в кириллице (юникод)?
Например:
SELECT * FROM Table WHERE Column1 like '%Наименование%'
будет искать только строку, содержащую 'Наименование'. Если встретиться 'наименование' - в результат не попадет
UPPER на кириллицу не работает!
В латинице поиск при использовании LIKE регистронезависимый.
Знаю, что у SQLite с этим проблемы, а решения кроме как использования неких сторонних сборок не нашел в инете.
Форум тоже просмотрел - ничего.
Не думаю, что никто не сталкивался. Поделитесь опытом, пож-та!
Ссылка на комментарий
25 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.