#sql #sql-server-2008 #nhibernate
#sql #sql-server-2008 #nhibernate
Вопрос:
Это поставило меня в тупик, и я подумал, что обращусь за помощью к сообществу SO.
Пользователь хочет выбрать все заказы, которые начинаются с определенного идентификатора, например:
123 вернет 123, 12345, 1238790 и т.д. Однако ID — это столбец int.
Я использую NHibernate, и моя строка в настоящее время:
criteria.Add(Restrictions.Eq("Id", itemId));
но это вернет мне только 123. Я могу сделать ограничения.Like, но это преобразуется в предложение SQL LIKE, и это не будет работать с int col.
Есть идеи?
РЕДАКТИРОВАТЬ: Извините, БД — это SQL Server 2008
Комментарии:
1. Очень странное требование. Зачем пользователю такая вещь?
2. Подумайте о том, что это означает, с математической точки зрения, для заданного числа «начать с»
123
.3. Это должно быть выполнимым приведением
id
к строке, но это приведет к снижению производительности, поскольку индекс не будет использоваться. Это действительно странное требование.4. @Oded, БД может быть разделена на диапазоны идентификаторов, хранящихся в разных местах или означающих разные вещи.
5. @DanLehmann — «может быть». Вероятно, нет.
Ответ №1:
К сожалению, вы не указали, какую базу данных вы используете (SQL — это просто язык запросов ….), Но если вы используете SQL Server (продукт Microsoft RDBMS), то вы можете создать вычисляемый столбец типа VARCHAR(15)
для хранения вашего строкового представления INT
, а затем просто выполнить поиск поэто….
ALTER TABLE dbo.YourTable
ADD IdAsString AS CAST(Id AS VARCHAR(15)) PERSISTED -- PERSISTED might not work - depending on your version of SQL Server
SELECT (list of columns)
FROM dbo.YourTable
WHERE IdAsString LIKE '123%'
Действительно ли это имеет смысл для бизнеса, это совершенно другая история….. (Я согласен с Одедом и Мэттом Боллом …)
Но поскольку теперь это строковый столбец, вы должны иметь возможность использовать свой Restrictions.Like
подход в NHibernate, как вы упомянули.
Комментарии:
1. Как это будет использовать hibernate? Это то, о чем спрашивает OP
2. @Adrian: OP уже сказал: я могу сделать ограничения. Like, но это преобразуется в предложение SQL LIKE, и это не будет работать с int col. — это будет работать с этим
IdAsString
столбцом…..3. 1 Да, это было бы, предполагая, что мы говорим о SQL Server. Op не указал.
4. Спасибо, Марк, полностью согласен, что это сумасшедшее требование, я собираюсь сказать им, чтобы они забыли об этом. Хотя ваша идея мне нравится.
Ответ №2:
Пользователь хочет выбрать все заказы, которые начинаются с определенного идентификатора, например:
123 вернет 123, 12345, 1238790 и т.д. Однако ID — это столбец int.
Похоже (каламбур), у вас может быть несколько проблем с вашим дизайном.
Во-первых, хотя имя элемента данных «порядковый номер» может указывать на числовое значение, порядковые номера и тому подобное обычно являются нечисловыми (например, текст фиксированной ширины). Например, международный стандартный номер книги (ISBN) является нечисловым, не в последнюю очередь потому, что конечный символ может быть X
. Даже если все допустимые символы являются цифрами, из этого не обязательно следует, что значения являются числовыми.
Хороший вопрос, который нужно задать себе: имеет ли смысл применять математические операции к этим значениям? Например, дает ли вычисление суммы номеров заказов клиента значимый результат? Если ответ отрицательный, то значения, вероятно, не числовые. Кроме того, учитывая требование использовать оператор, такой как LIKE
для значений, является убедительным признаком того, что они действительно нечисловые.
Во-вторых, похоже, что существует подразумеваемая связь между значением ID = '123'
и любым ID
, начинающимся с одних и тех же символов. Чтобы вернуться к примеру ISBN, вы можете определить, были ли две разные книги опубликованы одним и тем же издателем (при условии знания кодов издателя), разделив ISBN на его составные группы. Если ваши значения идентификатора имеют похожие группировки, и вам нужно выполнить запрос по этим группировкам, вам может быть проще сохранить 123
вложенный элемент отдельно от остальной части идентификатора и объединить части только для отображения.
Ответ №3:
Я не знаю точно, как это сделать в NHibernate, но поскольку промежуточные элементы имеют ограниченный размер, вы можете просто добавить ограничение для проверки возможных диапазонов
Версии SQL выглядят так
With cte as (
select top 10000000 row_number() over(order by t1.number) as N
from master..spt_values t1
cross join master..spt_values t2)
SELECT * FROM cte
WHERE
n = 123
or n between 1230 and 1239
or n between 12300 and 12399
or n between 123000 and 123999
or n between 1230000 and 1239999
Комментарии:
1. Хороший Конрад, я тоже думал об этом.
Ответ №4:
Поскольку это возможно в Linq (с NHibernate), это, скорее всего, также возможно с критериями. Вам просто нужно преобразовать его в string / varchar перед вызовом like . Может быть, есть проекция «преобразовать в строку»?
В Linq это было бы просто:
.Where(x => x.Id.ToString().StartsWith("123"))
Ответ №5:
в вашем сопоставлении для класса вы можете определить строковый столбец, который использует формулу для его заполнения. преобразование из int в string выполняется с использованием формулы, и вы можете запросить ее без необходимости изменять свою базу данных.