NULL值处理细节

NULL值处理细节

  • 2020年8月24日
  • 4分钟阅读

本主题描述使用’null’值的细节,以及在编写条件时应如何对待它们。

考虑以下示例。该员工持久化类暴露了两个属性-名字经理名称是指定员工姓名的字符串属性。如果当前对象不代表经理,经理是引用Employee对象的引用属性。如果当前雇员是经理,则该属性包含空引用。

public class Employee : XPObject {
    public string Name {
        get { return fName; }
        set { SetPropertyValue(nameof(Name), ref fName, value); }
    }
    string fName;

    public Employee Manager {
        get { return fManager; }
        set { SetPropertyValue(nameof(Manager), ref fManager, value); }
    }
    Employee fManager;

}

假设一个数据库包含六个Employee对象。

NullHandling_dbImage

您将获得一项任务,以检索不在指定经理的指导下工作的所有员工(包括经理)。假设这位经理是麦克。您可以尝试使用这样的条件来解决您的任务。

XPCollection<Employee> team = new XPCollection<Employee>();
Employee manager = 
    Session.DefaultSession.FindObject<Employee>(CriteriaOperator.Parse("[Name] = 'Mike'"));
team.Criteria = CriteriaOperator.Parse("Manager.Oid <> ? And Oid <> ?", manager.Oid, manager.Oid);
int count = team.Count; // Returns 2 (Nathan and Bob)

该代码应返回所有不在Mike监督下工作的员工,Mike本人除外。在我们的示例中,应为John,Nathan和Bob。但是,您看到的结果集合仅包含Nathan和Bob。这是因为约翰没有分配经理。在SQL中,您无法将值与“ null”进行比较。这样的比较不会产生布尔值,而是会产生“未知”值,从而导致结果集为空。由于John没有管理员,因此相应的数据库列为’null’。上面演示的标准试图将“ null”与Mike的标识符进行比较。这样的比较无法正确评估,因此,John从结果集合中省略了。

在编写这样的条件时,您需要显式检查引用属性值是否不是’null’。此外,您不能通过编写“ Manager == NULL”来执行此操作,因为这也将与无法正确评估的“ null”进行比较。要检查值是否为“ null”,必须使用SQL“ is null”谓词。在XPO上下文中,这转换为使用IsNull函数运算符。下面的代码片段演示了可以按预期运行的重写条件。

XPCollection<Employee> team = new XPCollection<Employee>();
Employee manager = 
    Session.DefaultSession.FindObject<Employee>(CriteriaOperator.Parse("[Name] = 'Mike'"));
team.Criteria = CriteriaOperator.Parse("Iif(IsNull(Manager), Oid, Manager.Oid) <> ?", manager.Oid);
int count = team.Count; // Returns 3 (John, Nathan and Bob)

unt = team.Count; // Returns 3 (John, Nathan and Bob)


演示的条件操作员检查是否设置了Manager属性值,这表示当前处理的员工引用了经理。如果是,则操作员确保所引用的管理员不是Mike。否则,操作员将检查以确保当前处理的员工不是麦克本人。
### 数据库处理 NULL 的最佳实践 在数据库设计和管理过程中,合理处理 `NULL` 对于提升数据质量、减少错误以及优化查询性能至关重要。以下是针对这一问题的一些最佳实践: #### 1. 避免过度依赖 `NULL` 虽然 `NULL` 是一种有效的表示缺失的方式,但在某些情况下,它可能导致逻辑复杂性和潜在的查询错误。因此,在设计表结构时应尽可能避免不必要的 `NULL` 字段[^1]。 如果某个字段可能频繁为空,则可以考虑将其拆分为单独的子表存储,从而减少主表中的稀疏列数量。这种做法不仅有助于提高查询效率,还能增强系统的可扩展性。 #### 2. 使用默认替代 `NULL` 当字段允许存在缺省状态时,可以通过设置合理的默认来代替 `NULL` 。例如: - 对于日期时间类型的字段,默认设为当前时间戳; - 数字型字段初始化为零或其他特定数; - 文本字符串则可以用空串 (`''`) 表达无内容的情况。 这种方法能够简化应用程序层面对特殊情况的判断逻辑,并且使数据分析更加直观易懂[^2]。 ```sql CREATE TABLE example ( id INT PRIMARY KEY, name VARCHAR(50) NOT NULL DEFAULT '', created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); ``` #### 3. 明确区分未知与不存在的区别 有时,“未提供”的含义不同于“确实不存在”。在这种情形下,仅靠单一的 `NULL` 并不足以清晰表达两者的差异。此时推荐引入额外的状态标志位或者枚举类型字段加以辅助说明[^3]。 比如在一个订单管理系统里,客户地址可能是暂时不可得(即尚未填写),也有可能根本不需要配送服务——这两种情况都表现为该属性上没有具体,但其背后的实际意义却截然不同。 #### 4. 调整SQL语句以适应含null的数据集 编写涉及可能存在 null 的条件筛选时要注意语法细节上的变化。标准的关系运算符 (=, != ,<>, etc.) 不适用于比较含有 null 的项;应该改用专门用于检测 null 存在与否的关键字 IS 或者 IS NOT 来构建相应条件表达式: ```sql SELECT * FROM users WHERE email IS NOT NULL; ``` 另外还需注意聚合函数的行为特征:大多数内置统计功能会自动忽略掉参数列表里的任何 null 实例,不过仍需确认目标dbms的具体实现规则以防万一。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值