Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 通过存储原始字符串大小写和小写来绕过数据库大小写敏感问题是否疯狂?_Sql_Database_Database Agnostic - Fatal编程技术网

Sql 通过存储原始字符串大小写和小写来绕过数据库大小写敏感问题是否疯狂?

Sql 通过存储原始字符串大小写和小写来绕过数据库大小写敏感问题是否疯狂?,sql,database,database-agnostic,Sql,Database,Database Agnostic,我正在实现一个数据库,其中有几个表具有字符串数据作为候选键(例如:username),并将相应地编制索引。对于这些字段,我需要: 当有人查询表中的键时,不区分大小写 以某种方式保留最初编写的案例,以便应用程序可以使用原始案例向用户呈现数据 我还希望数据库模式尽可能独立于数据库,因为应用程序代码不是(或不应该)从属于特定的RDBMS 还值得注意的是,对数据库执行的绝大多数查询将由应用程序代码完成,而不是通过客户端直接访问表来完成 在实现这一点时,我遇到了很多恼人的问题。一个是并非所有的RDBMS都

我正在实现一个数据库,其中有几个表具有字符串数据作为候选键(例如:username),并将相应地编制索引。对于这些字段,我需要:

  • 当有人查询表中的键时,不区分大小写

  • 以某种方式保留最初编写的案例,以便应用程序可以使用原始案例向用户呈现数据

  • 我还希望数据库模式尽可能独立于数据库,因为应用程序代码不是(或不应该)从属于特定的RDBMS

    还值得注意的是,对数据库执行的绝大多数查询将由应用程序代码完成,而不是通过客户端直接访问表来完成

    在实现这一点时,我遇到了很多恼人的问题。一个是并非所有的RDBMS都以相同的方式实现COLLATE(在模式级别上,案例敏感性似乎是可调的)。另一个问题是,排序规则和区分大小写选项可以在多个级别(服务器、数据库、表(?)和列)设置,我不能向应用程序保证它将获得什么设置。然而,另一个问题是,COLLATE本身可能会变得毛茸茸的,因为它不仅仅是区分大小写(例如:unicode选项),还有很多

    为了避免所有这些麻烦,我考虑的是通过为一段数据存储两列来完全避免这个问题。一列为原始大小写,另一列由应用层降为小写

    表中的两个字段

    user_name = "fredflintstone" (a unique index on this one) orig_name = "FredFlintstone" (just data... no constraints) user_name=“fredflintstone”(此索引上的唯一索引) orig_name=“FredFlintstone”(仅数据……无约束) 在我看来,这样做的利与弊是:

    优点:

  • 没有歧义-应用程序代码将管理案例转换,我永远不需要担心当底层RDBMS/设置更改时单元测试“神秘地”失败

  • 索引上的搜索将是干净的,并且不会因为排序规则功能或对LOWER()的调用或任何东西而减慢速度(假设这样做会减慢索引的速度,这似乎是合乎逻辑的)

  • 缺点:

  • 翻倍数据所需的额外存储空间

  • 这似乎有点野蛮

  • 我知道它会起作用,但同时它闻起来不对劲


    这样做是否疯狂/毫无意义?是否有什么我不知道的事情使得区分大小写的问题没有我现在认为的那么棘手?

    建议您的搜索查询执行以下操作:

    • 从较低(用户名)=较低('fredFlinstone')的用户中选择*
    • 当应忽略/尊重区分大小写时,在查询中显式包含排序规则提示

    我会考虑重复数据敏感度太苛刻。

    建议你的搜索查询做这样的事情:

    • 从较低(用户名)=较低('fredFlinstone')的用户中选择*
    • 当应忽略/尊重区分大小写时,在查询中显式包含排序规则提示

    我认为重复数据对于病症过于繁重。

    当然,这样的决定总是折衷的,但我不认为这必然是“数据翻倍”。将字符串小写可能是一个非常重要的操作,特别是当您超出ASCII时,因此字符串的小写版本不仅仅是“重复”。它在某种程度上与原始字符串相关,但仅此而已

    如果您将其视为将计算结果存储在DB中的模拟,它会变得更自然


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

    当然,像这样的决策总是一种权衡,但我认为这不一定是“双重数据”。将字符串小写可能是一个非常重要的操作,特别是当您超出ASCII时,因此字符串的小写版本不仅仅是“重复”。它在某种程度上与原始字符串相关,但仅此而已

    如果您将其视为将计算结果存储在DB中的模拟,它会变得更自然


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

    出于性能原因,我经常看到以这种方式复制数据。它允许您保留原始的大小写(这显然是您需要的,因为您并不总是能够猜出大小写应该是什么,例如,您不能确保每个名称都以大写字母开头)。如果数据库不支持其他方法(函数索引),那么这是实用的,而不是疯狂的。您可以通过使用触发器来保持数据的一致性。

    我经常看到出于性能原因以这种方式复制数据。它允许您保留原始的大小写(这显然是您需要的,因为您并不总是能够猜出大小写应该是什么,例如,您不能确保每个名称都以大写字母开头)。如果数据库不支持其他方法(函数索引),那么这是实用的,而不是疯狂的。您可以通过使用触发器来保持数据的一致性

    索引上的搜索将是干净的,并且不会因为排序规则功能或对LOWER()的调用或任何东西而减慢速度(假设这样做会减慢索引的速度,这似乎是合乎逻辑的)

    不,那不是逻辑学
    create index users_name on users(name); -- index on name
    create index users_name_lower on users(lower(name)); -- index on the function result
    
    select * from users where lower(name) = ?