• 0
ra.eremeev

Зависимость от регистра русских символов при использовании LIKE

Вопрос

Всем привет!

Собственно вопрос: как осуществить поиск по таблице, в полях которой значения в кириллице (юникод)?

Например:

SELECT * FROM Table WHERE Column1 like '%Наименование%'

будет искать только строку, содержащую 'Наименование'. Если встретиться 'наименование' - в результат не попадет

UPPER на кириллицу не работает!

В латинице поиск при использовании LIKE регистронезависимый.

Знаю, что у SQLite с этим проблемы, а решения кроме как использования неких сторонних сборок не нашел в инете.

Форум тоже просмотрел - ничего.

Не думаю, что никто не сталкивался. Поделитесь опытом, пож-та!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

14 ответов на этот вопрос

  • 0

Опыт есть.

Есть два пути. 

1) самый простой, но выполнимый только в одном случае. Если большая только первая буква и/или все меленькие. Я делаю два like через or где в первом случае первая буква в нижнем регистре, а второй в верхнем. (Делаю функцию, где перевожу все в н жний а в первую в верхний)

2) тут я не знаю как во встроенных компонентах, может быть тоже самое, но я использую от devart. Там есть встроенные функции в sql. Я создаю такую функцию внутри запроса, а во внешнем обработчике пишу ее обработку. Обычно перевожу все символы до к верхнему регистру. Т.е: select * from таблица where fUpp( column1) like fUpp(%column1%). Где fUpp и есть функция внутри запроса.

Изменено пользователем Vitaldj

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Vitaldj, спасибо за ответ!

Оба варианта понятны, но:

1. Заглавные буквы встречаются не только вначале текста (например, встречаются аббревиатуры или имена собственные)

2. хотелось бы решение именно на стандартных компонентах

Есть ли еще варианты?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
2 часа назад, ra.eremeev сказал:

Vitaldj, спасибо за ответ!

Оба варианта понятны, но:

1. Заглавные буквы встречаются не только вначале текста (например, встречаются аббревиатуры или имена собственные)

2. хотелось бы решение именно на стандартных компонентах

Есть ли еще варианты?

Мне кажется, есть и в стандартных компонентах те функции, которые я использую в devart. Может кто из форумчан подскажет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Проблема не в компоненте, не в Delphi и не в Embarcadero.

Это вопрос настройки сервера БД, конкретной таблицы и подключения к БД. А именно параметров сортировки и представления.

Подробно на английском, подробно на русском.

Если сильно не вникать, везде, где говорится о кодировке, нужно выбирать значение «Cyrillic_General_CI_AS».

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
5 минут назад, Pax Beach сказал:

Проблема не в компоненте, не в Delphi и не в Embarcadero.

Это вопрос настройки сервера БД, конкретной таблицы и подключения к БД. А именно параметров сортировки и представления.

Подробно на английском, подробно на русском.

Если сильно не вникать, везде, где говорится о кодировке, нужно выбирать значение «Cyrillic_General_CI_AS».

 

Извините, а причем тут Microsoft SQL сервер? Мы про SQlite. Это немного разные вещи)))) С MSSQL как раза нет таких проблем))

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
2 часа назад, Vitaldj сказал:

Извините, а причем тут Microsoft SQL сервер? Мы про SQlite. Это немного разные вещи)))) С MSSQL как раза нет таких проблем))

Я говорю про все диалекты SQL. Когда идет речь о том, что не работает сравнение в where или like, нужно смотреть настройки кодировки на сервере и в строке соединения.

UPD:

Прочитал, что есть проблема сортировки в SQLite. Проверил — есть, и LIKE, и ORDER BY. Прочитал ответ разработчиков — подход порадовал.

Потребуется воспользоваться функцией sqlite3_create_collation (есть в компонентах FireDAC, UniDAC, модуле RTL\System.Sqlite.pas). Я нашел пример только на C.

Может у Вас получится воспользоваться — будем рады посмотреть пример.

Изменено пользователем Pax Beach
Rusland и Евгений Корепов понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Добрый день!

В стандартных компонента есть механизм по встраиванию своих функций в 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 '%иван%'

Запрос вернет все имена содержащие иван в любом регистре.

Pax Beach, Axbor, Rusland и 2 другим понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
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
В 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 '%иван%'

Запрос вернет все имена содержащие иван в любом регистре.

Виталий, спасибо!

Принцип понял, но не понял как реализовать :(

Если не затруднит, можно пример какой-нибудь?

Где весь этот код набивать?

Простите за глупую просьбу, но, правда, не нашел в поисковиках ничего про пользовательские функции...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
4 часа назад, Кривяков Виталий сказал:

Не вопрос.

SQLITE.zip

Виталий, огромное спасибо!!! Разобрался.

Все работает!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
В 22.07.2016 в 18:05, Кривяков Виталий сказал:

Не вопрос.

SQLITE.zip

Сделал по образу и подобию.

 

Кричит:

[dcc32 Error] clueDBWrapper.pas(537): E2010 Incompatible types: 'TSQLiteFunctionInstance' and 'TSQLiteFunction'

Чую, что собака порылась в том, что в примере есть instance Form1, а у меня класс на данный момент в "свободном полёте".

Тут можно как- то выкрутиться ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Вопрос отменяется.

Как всегда документация говорит одно, код- другое, подразумевается третье.

Для 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);
Изменено пользователем MAR
Rusland понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Это просто какой- то праздник жизни !!!

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 пользователей

    Нет пользователей, просматривающих эту страницу