【问题标题】:How to specify a "Like" on an integer column?如何在整数列上指定“喜欢”?
【发布时间】:2021-11-11 23:48:03
【问题描述】:

这个让我很困惑,我想我会把它提交给 SO 社区寻求帮助。

用户想要选择所有以某个ID开头的订单,例如:

123 将返回 123、12345、1238790 等。但是 ID 是一个 int 列。

我正在使用 nHibernate,我目前的线路是:

criteria.Add(Restrictions.Eq("Id", itemId));

但这只会返回 123。我可以执行 Restrictions.Like,但它会转换为 SQL LIKE 子句,并且不适用于 int col。

有什么想法吗?

编辑:对不起,数据库是 SQL Server 2008

【问题讨论】:

  • 非常奇怪的要求。为什么用户需要这样的东西?
  • 想一想从数学上讲,给定数字“以”123 开头的含义。
  • 这应该可以将id 转换为字符串,但这会导致性能下降,因为不会使用索引。这确实是个奇怪的要求。
  • @Oded,数据库可以根据存储在不同位置或含义不同的 ID 范围进行拆分。
  • @DanLehmann - “可能”。可能不是。

标签: sql sql-server-2008 nhibernate


【解决方案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%'

这是否真正具有商业意义,是完全不同的故事......(我同意 Oded 和 Matt Ball......)

但由于现在这是一个字符串列,您应该能够在 NHibernate 中使用您的 Restrictions.Like 方法,正如您提到的那样。

【讨论】:

  • 如何使用休眠?这就是 OP 的要求
  • @Adrian:OP 已经说过:我可以执行 Restrictions.Like,但它会转换为 SQL LIKE 子句,并且不适用于 int col。 -这将适用于这个IdAsString 列.....
  • +1 是的,假设我们谈论的是 SQL Server。操作未指定。
  • 谢谢 Marc,完全同意这是一个疯狂的要求,我会告诉他们忘记它。不过喜欢你的想法。
【解决方案2】:

用户想要选择所有以某个 ID 开头的订单, 示例:

123 将返回 123、12345、1238790 等。ID 是一个 int 列 但是。

听起来(双关语)您的设计可能存在一些问题。

首先,虽然数据元素名称“订单号”可能暗示数字,但订单号等通常是非数字的(例如,固定宽度的文本)。例如,International Standard Book Number (ISBN) 是非数字的,尤其是因为最后一个字符可以是 X。即使所有允许的字符都是数字,也不一定意味着这些值是数字。

问自己一个好问题是,对这些值应用数学运算是否有意义?例如,计算客户订单号的总和是否给出有意义的结果?如果答案是否定的,那么这些值可能不是数字。此外,给定要求,在值上使用诸如 LIKE 之类的运算符强烈表明它们确实是非数字的。

其次,ID = '123' 值与任何以相同字符开头的ID 之间似乎存在隐含关系。回到 ISBN 示例,您可以通过将 ISBN 拆分为其复合组来确定同一出版商是否出版了两本不同的书籍(取决于知道出版商的代码)。如果您的 ID 值具有相似的分组,并且您需要针对这些分组进行查询,您可能会发现将 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
    

    【讨论】:

    • 不错的康拉德,我也在考虑这个问题。
    【解决方案4】:

    由于这在 Linq(使用 NHibernate)中是可能的,因此很可能在 Criteria 中也是可能的。您只需在调用类似之前将其转换为字符串/varchar。也许有一个“转换为字符串”的投影?

    在 Linq 中,这只是:

    .Where(x => x.Id.ToString().StartsWith("123"))
    

    【讨论】:

      【解决方案5】:

      在您的类映射中,您可以定义一个使用公式填充它的字符串列。从 int 到 string 的转换是使用公式完成的,您无需更改数据库即可对其进行查询。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-16
        相关资源
        最近更新 更多