2010-10-25 34 views
1

我正在实现一个数据库,其中几个表具有字符串数据作为候选键(例如:用户名),并将相应索引。对于这些领域我想:通过存储原始字符串大小写和小写字母来绕过数据库区分大小写问题是疯狂的吗?

  1. 不区分大小写时有人询问在琴键上表

  2. 最初写的情况下以某种方式保存下来,以便应用程序能与原来的显示数据给用户情况下所使用

我也想的数据库架构象数据库独立地,由于应用程序代码(或不应该是)不从动于一个特定的RDBMS。

另外值得注意的是绝大多数在数​​据库上完成的查询都是由应用程序代码完成的,而不是通过客户端的直接表访问。

在实现这个过程中,我遇到了很多恼人的问题。一个是,并不是所有的RDBMS都以相同的方式实现COLLATE(这是敏感度在架构层次上似乎可调的地方)。另一个问题是排序规则和区分大小写选项可以设置在多个级别(服务器,数据库,表(?),列),我不能保证应用程序会得到什么设置。还有一个问题是,COLLATE本身可能会变得毛茸茸的,因为在那里存在比简单区分大小写更多的事情(例如:unicode选项)。

为了避免所有这些令人头痛的问题,我正在考虑通过为一个数据存储两列来完全避免这个问题。一列与原始案例,另一列由应用层下降到小写。

例如:在表中的字段中的两个

user_name = "fredflintstone" (a unique index on this one) 
orig_name = "FredFlintstone" (just data... no constraints) 

的优点和这个缺点,我看到它是:

优点:

  1. 没有歧义 - 应用程序代码将管理大小写转换,并且当底层RDBMS /设置更改时,我从不需要担心单元测试“神秘地”失败。该指数

  2. 搜索将是干净,从来没有整理的功能减慢或调用,以降低()或任何(假设这样的事情慢下来的指数,这似乎是合乎逻辑的)

缺点:在加倍后的行动数据所需

  1. 额外的存储空间

  2. 这似乎有点残酷

我知道它会工作,但同时它闻起来不对。

这样做是疯了/毫无意义吗?有什么我不知道的,这使得大小写敏感问题比我目前看起来那么棘手?

+0

你想复制数据?坏... – 2010-10-25 16:26:55

+4

在'LOWER'上面选择'UPPER',因为在执行'LOWER'时某些字符不能往返于某些地区http://msdn.microsoft.com/en-us/library/bb386042.aspx – bdukes 2010-10-25 16:30:24

+0

@bdukes - 哇... thx。我不知道。 – Russ 2010-10-25 16:35:06

回答

1

由于性能方面的原因,我经常看到以这种方式复制数据。它可以让你保留原来的外壳(你很明显需要这样做,因为你并不总是能够猜出外壳应该是什么样的,你不能确定每个名字都以大写字母开头)。如果数据库不支持其他方式来做到这一点(功能索引),那么这是实用的,而不是疯狂的。您可以使用触发器保持数据的一致性。该指数

+0

“实用而不疯狂”正是我如何看待它。但它似乎应该是一个普遍的问题,我有这样的感觉,我错过了一些东西,因为我没有看到这一点,并没有看到任何这方面的例子。 – Russ 2010-10-25 16:37:41

+0

那么,有一些数据库只是不支持功能索引。你很可能不得不像这样索引数据,所以这将是唯一的选择。如果使用索引,我已经看到了使用这种类型的严重应用程序,所以我肯定会说它不是疯狂或不寻常的。在支持功能索引的地方(例如Oracle和Postgre),使用这些索引可能会更有意义。 – steinar 2010-10-31 00:38:46

1

推荐搜索查询做这样的事情:

  • SELECT * FROM Users WHERE LOWER(UserName) = LOWER('fredFlinstone')
  • 明确对何时大小写应该被忽略的查询整理提示/尊重

我会考虑的复制大小写敏感的数据太繁重。

+1

LOWER是否会杀死索引的好处? – Russ 2010-10-25 16:28:51

+1

大多数DBMS将不能使用索引来进行这样的查询,这可能是一个问题。显而易见的解决方案是基于功能的索引,但并非所有的DBMS都具有这些索引。另外,正如问题中提到的,不同COLLATE实现的问题仍然存在。 – sleske 2010-10-25 16:30:31

+1

@Russ,在Oracle中,您可以创建一个基于函数的索引,以便该列本身通过Lower() - (http://www.akadia.com/services/ora_function_based_index_2.html) – Harrison 2010-10-25 16:31:36

2

当然,这样的决定总是一种折衷,但我认为这不一定是“加倍数据”。降低字符串可以是一个非平凡的操作,特别是如果超出ASCII范围,则字符串的小写版本不仅仅是“重复”。它与原始字符串有些相关,但不超过这个。

如果您认为它是将计算结果存储在数据库中的一种模拟方式,则会变得更加自然。

查询UPPER(UserName)的选项是另一个很好的解决方案,它避免了第二列。但是,要使用它,您至少需要一个可靠的UPPER函数(特别是您可以控制它用于非ASCII字符的语言环境),并且可能需要基于函数的索引才能获得不错的性能。

1

搜索将是干净,从来没有整理的功能减慢或调用,以降低()或任何(假设这样的事情慢下来的指数,这似乎是合乎逻辑的)

没有,这不合逻辑。你可以在常量函数上有索引。

create index users_name on users(name); -- index on name 
create index users_name_lower on users(lower(name)); -- index on the function result 

你的RDBMS应该足够聪明,知道用users_name_lower当它到达这个查询:

select * from users where lower(name) = ? 

没有users_name_lower,是的,就得走表。有了功能指标,它做对了。

相关问题