Использование SQLite ADO.Net-провайдеру необходимо напрямую указать GUID в предложении where запроса без использования параметра - PullRequest
4 голосов
/ 04 октября 2011

Есть ли в любом случае, чтобы GUID был частью самого SQL-запроса без использования параметра?

Позвольте мне объяснить, что именно я пытаюсь сделать и почему.Я работаю с существующим приложением, которое использует ADO.Net для создания и подключения к базе данных SQLite.Нынешняя структура базы данных и метод ее запроса ужасны.Я нахожусь в процессе реорганизации того, как это работает фундаментально.Однако это не то, что можно сделать быстро.Пока этот редизайн завершается, у меня возникла ситуация, когда нужно решение проблемы с пластырем.Напомним, что причина первоначальной реализации кода неясна и, похоже, была создана кем-то, у кого мало знаний о базе данных.Рефакторинг всей базы данных, чтобы не нуждаться в этой ситуации, является окончательным решением, но сейчас я просто ищу работу в рамках существующей структуры.

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

SELECT * FROM data_table WHERE guid_col IN( ?, ?, ?, ?)

Проблема возникает, когда мне нужно получить относительно большой объем информации.SQLite имеет ограничение в 1000 параметров в одном запросе.Если мне нужно передать более 1000 идентификаторов GUID для поиска, запрос просто прервется.При построении вышеупомянутой строки она перебирает список GUID для вставки вопросительных знаков и создания параметров.Мое устранение проблемы с помощью пластыря должно было состоять в том, чтобы непосредственно вставить значение GUID в то место, где в настоящее время находятся вопросительные знаки, и отказаться от параметров в запросе.В конце концов, это своего рода использование параметров для целей, для которых их не нужно использовать.

Проблема с этим «решением» заключается в том, что я не могу получить GUID для сопоставления данных в столбце, т.е. запрос всегда возвращает ноль.Я понимаю, что GUID не является нативным типом для SQLite, и под ним он фактически представлен как BLOB (да, я уверен, что мы используем BLOB, а не строковое представление).Тем не менее, я не смог заставить запрос выполняться правильно.

На данный момент я пробовал все следующее:

Я пытался вызвать ToString () для GUID, поэтому запрос выглядит как

SELECT * FROM data_table WHERE guid_col IN
   ( 'b5080d4e-37c3-4286-9c3a-413e8c367f36', 'aa0ff789-3ce9-4552-9840-5ed4d73c1e2c')

попытался вызвать ToString ("N") для GUID, чтобы запрос выглядел как

SELECT * FROM data_table WHERE guid_col IN
  ( 'b5080d4e37c342869c3a413e8c367f36', 'aa0ff7893ce9455298405ed4d73c1e2c')

Я пытался вызвать ToString ("B") для GUID, чтобы запрос выглядел как

SELECT * FROM data_table WHERE guid_col IN
  ( '{b5080d4e-37c3-4286-9c3a-413e8c367f36}',
    '{aa0ff789-3ce9-4552-9840-5ed4d73c1e2c}')

Я пытался вызвать ToByteArray () для GUID и поместить результат в запрос путем добавления каждого байта в строку, вызывающую ToString ("X") для каждого байта, чтобы запрос выглядел как

SELECT* FROM data_table WHERE guid_col IN ('4ED8B5C33786429C3A413E8C367F36', '89F7FAAE93C524598405ED4D73C1E2C')

При чтении документации SQLite я читаю следующие «литералы BLOB с предшествующими символами» и строковыми литералами «x», содержащими шестнадцатеричные или шестнадцатеричные символы:"символ. Если я пытаюсь применить это к моему запросу, чтобы он выглядел как

SELECT * FROM data_table WHERE guid_col IN
    ( x'4ED8B5C33786429C3A413E8C367F36', x'89F7FAAE93C524598405ED4D73C1E2C')

, я получаю сообщение об ошибке, говорящее, что" x "не является распознанным символом.

Возможно липолучить GUID в строку запросабез использования параметра?

Ответы [ 2 ]

3 голосов
/ 30 ноября 2011

Я предлагаю вам использовать временную таблицу для чего-то подобного. Например ...

PRAGMA temp_store = MEMORY;

CREATE TEMP TABLE tbl_guids (guid_col text);

INSERT INTO tbl_guids VALUES ('b5080d4e-37c3-4286-9c3a-413e8c367f36');
INSERT INTO tbl_guids VALUES ('aa0ff789-3ce9-4552-9840-5ed4d73c1e2c');
... more inserts ...

SELECT * FROM data_table WHERE guid_col IN ( SELECT guid_col FROM tbl_guids);

DROP TABLE tbl_guids;

Обязательно оберните транзакцию вокруг всех операторов INSERT INTO. Это поможет с производительностью на тонну. Также SQLite позволяет временным таблицам полностью существовать в памяти , устанавливая PRAGMA temp_store = MEMORY

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

0 голосов
/ 30 мая 2012

Вы можете передавать GUID в виде строк, если вы установили «BinaryGuid = False» в строке подключения.Если это сделано, «ToString ()» должно работать нормально.

...