我正在寻找一种在多个表上执行动态搜索的模式。
我无法控制遗留(以及设计不佳)的数据库表结构。
考虑类似于简历搜索的场景,其中用户可能想要对简历中的任何数据执行搜索并返回与其搜索条件匹配的简历列表。任何字段都可以随时搜索,并与一个或多个其他字段结合使用。
根据搜索的字段动态创建实际的sql查询。我发现的大多数解决方案都涉及复杂的块,但我不禁认为必须有一个更优雅的解决方案,因为这一定是一个已解决的问题。
是的,所以我开始在代码中动态构建sql的道路。似乎很神奇。如果我真的试图支持所请求的查询任何表中任何字段的任何组合的能力,那么这将是一组大量的if语句。 哆嗦
我相信我读到COALESCE仅在您的数据不包含NULL时才有效。那是对的吗?如果是这样,不要去,因为我在整个地方都有NULL值。
答案 0 :(得分:5)
据我了解(我也是一个针对可怕遗留数据库的人),没有动态WHERE子句这样的东西。它还没有解决。
就个人而言,我更喜欢在代码中生成动态搜索。使测试更方便。请注意,在代码中创建SQL查询时,请勿在用户输入中进行连接。使用你的@variables!
唯一的选择是使用COALESCE运算符。假设您有下表:
Users
-----------
Name nvarchar(20)
Nickname nvarchar(10)
并且您想要搜索名称或昵称。以下查询将执行此操作:
SELECT Name, Nickname
FROM Users
WHERE
Name = COALESCE(@name, Name) AND
Nickname = COALESCE(@nick, Nickname)
如果您不想搜索某些内容,只需传入null即可。例如,为@name传递“brian”和为@nick传入null会导致以下查询被评估:
SELECT Name, Nickname
FROM Users
WHERE
Name = 'brian' AND
Nickname = Nickname
coalesce运算符将null转换为标识评估,该标识始终为true且不影响where子句。
答案 1 :(得分:1)
搜索和规范化可能相互矛盾。所以可能首先要获得某种“视图”,它显示所有可以作为单行搜索的字段,只需一个键即可获得简历。那么你可以在它前面抛出Lucene这样的东西,为你提供这些行的全文索引,工作方式是,在这个视图中你要求它为“x”并返回给你键。这是一个很好的解决方案,并且在前两个月的IIRC中由joel亲自推荐播客。
答案 2 :(得分:1)
您需要的是SphinxSearch(对于MySQL)或Apache Lucene。
正如你在你的例子中所说,让我们想象一个由几个字段组成的简历:
因此,使用WHERE快速搜索所有这些字段中的单词会变成一个带有多个JOINS的非常长的查询。
相反,您可以更改您的参考框架,并将整个简历视为单个文档,您只想搜索所述文档。
这是像Sphinx Search这样的工具。他们为你的'文档'创建一个FULL TEXT索引,然后你可以查询sphinx,它会回到数据库中找到记录的位置。
搜索结果非常好。
不要担心这些工具不属于您的RDBMS,它会为您使用适当的模型“文档”而不是为此应用程序使用错误的“TABLES”节省很多麻烦。