关于null值的小知识

关于null值的小知识
数据库中的逻辑关系是三元的,true,false,null。null 可以理解为神秘莫测的,不知道的,无法确定的。今天要一层一层的剥去null 值的神秘外衣。。。额,貌似这样有些猥琐。言归正传下面来梳理下关于null的知识。
一、null 值参与算数运算的结果为null,不过对于字符串的连接运算就不同了。
SQL> select 5+2-3 as result1,
  2         5+2-3+null as result2,
  3         3*5*null as result3
  4  from dual;
   RESULT1    RESULT2    RESULT3
---------- ---------- ----------
         4
SQL> select 'hello'||null||' oracle' from dual;
'HELLO'||NUL
------------
hello oracle
二、在聚集函数中avg,sum,min,max 等在求值的时候会忽略null值,但是count(*)  不会忽略null 值。先造出一个空值来count(cloumn_name) 也是会忽略null 值的。
SQL> update employees
  2  set salary = null
  3  where employee_id = 100;
1 row updated.
SQL> select count(*) as row_count,count(salary),
  2  avg(salary) as avg_salary,sum(salary) as sum_salary,
  3  min(salary) as min_salary,max(salary) as max_salary
  4  from employees;
 ROW_COUNT COUNT(SALARY) AVG_SALARY SUM_SALARY MIN_SALARY MAX_SALARY
---------- ------------- ---------- ---------- ---------- ----------
       107           106 6296.22642     667400       2100      17000
三、在where 子句中使用null值。在where 中不能使用等于号指定null 值条件。应该使用is null或者is not null.下面查询salary 值为null 的员工的姓名。
SQL> select last_name,first_name     
  2  from employees
  3  where salary = null;
no rows selected
SQL> select last_name,first_name
  2  from employees
  3  where salary is null;
LAST_NAME                 FIRST_NAME
------------------------- --------------------
King                      Steven
四、group by 子句中的null 值。先创建一个测试用的表testing02.
在group by 子句中不会忽略null 值,也会对null 进行分组。
SQL> create table testing02 (id number(6),name varchar2(20));
Table created.
SQL> insert into testing02 values(100,'testing');
1 row created.
SQL> insert into testing02 values(101,null);
1 row created.
SQL> commit;
Commit complet
SQL> select count(*) as row_count,name
  2  from testing02
  3  group by name;
 ROW_COUNT NAME
---------- --------------------
         1
         1 testing
五、在order by 中的null 值。通过在order by 中指定nulls first,nulls last 来实现让带有null 值的列排在前面或者后面,不要太依赖select 语句查询的默认输出。
SQL> select * from testing02;
        ID NAME
---------- --------------------
       100 testing
       101
SQL> select * from testing02
  2  order by name nulls first;
        ID NAME
---------- --------------------
       101
       100 testing
SQL> select * from testing02
  2  order by name nulls last;
        ID NAME
---------- --------------------
       100 testing
       101
六、在聚合运算union,union all,minus,intersect  中不会忽略null 值null 值将作为相等的值来对待此时可以认为null 等于 null.
7、null 值的插入。往表中的某一列插入一个null 值可以使用很多的方法,很多时候这取决于习惯。
SQL> insert into testing02 values(102,'');
1 row created.
SQL> insert into testing02 values(103,null);
1 row created.
SQL> insert into testing02 (id) values(103);
1 row created.
要注意的是下面这条语句不会插入null 值,而是插入字符串null.
SQL> insert into testing02 values(102,'null');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from testing02 
  2  where id > 101;
        ID NAME
---------- --------------------
       102
       103
       103
       102 null


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26110315/viewspace-722162/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26110315/viewspace-722162/

<think>好的,我现在需要回答用户关于SQL中NULL在表关联时的发生情景及影响的问题。用户已经提供了之前的对话和一些参考资料,我需要仔细分析这些信息,并结合自己的知识来构建一个全面且准确的回答。 首先,用户的问题集中在NULL在表关联时的发生情景和影响。根据之前的对话,用户可能已经了解笛卡尔积的概念,现在想深入探讨NULL在连接操作中的行为。我需要确保回答覆盖以下几个方面: 1. **NULL在连接条件中的处理方式**:不同数据库NULL的处理可能不同,但通常NULL与任何的比较结果都是未知(UNKNOWN),导致这些行被排除在连接结果之外。 2. **具体发生情景**:比如在INNER JOIN、LEFT JOIN等不同类型的连接中,NULL如何影响结果集。 3. **实际影响**:比如数据丢失、查询结果不符合预期、性能问题等。 4. **解决方案和最佳实践**:如何避免或处理NULL带来的问题,例如使用COALESCE函数或调整查询逻辑。 接下来,我需要参考用户提供的引用内容,看看是否有相关的信息可以利用。例如,引用[1]提到在NOT IN子查询中出现NULL会导致整个查询没有结果,这说明NULL在子查询中的处理可能影响主查询的结果。引用[3]讨论了使用NOT EXISTS和NOT IN时的性能差异,这可能涉及到NULL处理的不同方式。引用[5]中的SQL查询使用了IFNULL函数来处理可能的NULL,这可以作为处理NULL的一个实例。 同时,用户之前的回答中提到了笛卡尔积的发生场景,但当前问题转向NULL,因此需要区分两者的不同。不过,可能需要提到在连接条件中使用NULL可能导致意外的笛卡尔积,但根据引用[4],更多是连接条件缺失导致的笛卡尔积,而非NULL本身。 接下来需要组织回答的结构,确保逻辑清晰,分点说明。可能需要分为发生情景和影响两部分,每个部分下再细分具体情况。同时,加入示例代码和解决方案部分,帮助用户更好地理解。 需要注意用户提供的引用中有提到不同数据库NULL的处理可能不同,例如MySQL和SQLite在建表时的约束差异(引用[2]),但问题主要集中在查询时的关联操作,因此可能需要简要提及数据库差异,但主要关注通用情况。 另外,用户示例中的SQL语句(如引用[5])展示了如何处理NULL,这可以作为解决方案的一部分,例如使用IFNULL或COALESCE函数来替代NULL,确保连接条件有效。 最后,需要确保回答符合用户之前设定的格式要求:使用中文,行内公式用$...$,独立公式用$$...$$,代码块使用正确语法,并自然地添加引用标记。同时,生成相关问题,但根据用户指示,这次可能不需要,因为用户的问题已经明确。 总结思考步骤: 1. 确定用户的核心问题:NULL在表关联时的发生情景和影响。 2. 收集相关资料和引用内容,提取相关点。 3. 结构化回答,分情景和影响两部分,每部分细分具体情况。 4. 提供解决方案和最佳实践,引用示例中的处理方法。 5. 确保格式正确,引用标记适当,语言清晰。</think>#### SQL中NULL在表关联时的发生情景及影响 --- ### 一、NULL在表关联中的发生情景 #### 1. **连接条件包含可为空的字段** 当表关联的键(如`JOIN ON`子句中的字段)包含`NULL`时,可能导致匹配失败。 **示例**: ```sql SELECT * FROM employees e LEFT JOIN departments d ON e.department_id = d.id; ``` - 若`e.department_id`存在`NULL`,则这些记录无法与`d.id`匹配,但仍会保留在左连接结果中(`d`表字段为`NULL`)[^3]。 - 若`d.id`存在`NULL`,则右表无法匹配左表记录(除非左表字段也为`NULL`)。 #### 2. **使用`IN`或`NOT IN`子查询时子查询返回NULL** 在子查询中返回`NULL`会导致逻辑异常: - **`IN`子查询**:`NULL`不参与比较,结果不受影响。 - **`NOT IN`子查询**:若子查询结果包含`NULL`,则主查询会返回空结果集(因为`NOT IN (NULL)`等价于`!= NULL`,而`NULL`比较结果始终为`UNKNOWN`)[^1]。 **示例**: ```sql SELECT * FROM t WHERE t.col NOT IN (SELECT tt.col FROM tt); -- 若子查询返回NULL,则整个查询无结果 ``` #### 3. **外键关联中允许NULL** 若外键字段允许`NULL`,则关联时可能出现“未关联”的记录: ```sql SELECT * FROM orders o LEFT JOIN customers c ON o.customer_id = c.id; ``` - 若`o.customer_id`为`NULL`,则订单记录对应的客户信息字段均为`NULL`[^5]。 --- ### 二、NULL对表关联的影响 #### 1. **数据丢失或失真** - **内连接(`INNER JOIN`)**:若连接键为`NULL`,相关行会被完全排除在结果集外。 - **统计偏差**:聚合函数(如`COUNT`、`SUM`)可能因`NULL`导致统计结果不准确。例如,`COUNT(column)`会忽略`NULL`,而`COUNT(*)`不会。 #### 2. **逻辑错误风险** - **条件筛选失效**:`WHERE column = NULL` 永远返回假,正确写法应为 `WHERE column IS NULL`。 - **关联条件意外失效**:若连接键包含`NULL`,可能导致部分数据未被正确关联[^3]。 #### 3. **性能问题** - **索引失效**:大多数数据库的索引不包含`NULL`,若查询依赖`NULL`匹配,可能无法利用索引优化,导致全表扫描[^4]。 - **执行计划复杂化**:优化器可能因`NULL`的存在选择低效的执行路径。 --- ### 三、解决方案与最佳实践 #### 1. **显式处理NULL** - 使用`COALESCE`或`IFNULL`替换`NULL`: ```sql SELECT * FROM employees e LEFT JOIN departments d ON COALESCE(e.department_id, -1) = COALESCE(d.id, -1); -- 将NULL替换为默认-1,强制匹配 ``` #### 2. **避免子查询中的NULL污染** - 在子查询中排除`NULL`: ```sql SELECT * FROM t WHERE t.col NOT IN (SELECT tt.col FROM tt WHERE tt.col IS NOT NULL); ``` #### 3. **约束设计** - 若业务逻辑不允许空关联,应在表设计中为外键字段添加`NOT NULL`约束[^2]: ```sql ALTER TABLE orders MODIFY customer_id INT NOT NULL; ``` #### 4. **使用`NOT EXISTS`替代`NOT IN`** - `NOT EXISTS`对`NULL`更安全,且通常性能更优[^3]: ```sql SELECT * FROM test1 a WHERE NOT EXISTS (SELECT 1 FROM test2 b WHERE a.val = b.val); ``` --- ### 四、不同数据库的差异 - **MySQL**:允许外键字段为`NULL`,且不强制约束(除非显式定义`NOT NULL`)[^2]。 - **SQLite**:严格校验外键约束,建表时若引用无效字段会直接报错。 - **Oracle/SQL Server**:默认外键关联会忽略`NULL`,需通过触发器或约束额外控制。 --- ### 示例场景 **需求**:统计所有主管发展的用户数(包括直接发展和通过代理员间接发展)。 **处理NULL的SQL**: ```sql SELECT IFNULL(c.distri_user_id, c.user_id) AS userId, -- 代理员上级ID为空时,取自身ID COUNT(*) AS userCount FROM sys_user b JOIN sys_user c ON b.recommender_user_id = c.user_id WHERE c.distri_user_id IS NOT NULL OR c.new_flag = 30 GROUP BY userId ORDER BY userCount DESC LIMIT 30; ``` - **关键点**:`IFNULL`处理代理员与主管的层级关系,避免因`NULL`导致的分组错误[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值