-
mysql 空 什么意思_MySQL的空值和NULL有什么区别?(附示例)
2021-01-18 22:14:18从本质上区别:1、空值不占空间2、null值占空间通俗的讲:空值就像是一个真空转态杯子,什么都没有,而null值就是一个装满空气的杯子,虽然看起来都是一样的,但是有着本质的区别。(推荐课程:MySQL教程)例子:创建...本篇文章给大家带来的内容是关于MySQL的空值和NULL有什么区别?(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
从本质上区别:
1、空值不占空间
2、null值占空间
通俗的讲:
空值就像是一个真空转态杯子,什么都没有,而null值就是一个装满空气的杯子,虽然看起来都是一样的,但是有着本质的区别。
(推荐课程:MySQL教程)
例子:
创建一个test表,colA是不可以存放null值的,colB是能存放null值的。CREATE TABLE `test` (
`colA` varchar(255) NOT NULL,
`colB` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入一个null值试试,会发生什么情况?INSERT INTO `test`(`colA`, `colB`) VALUES (NULL, NULL);
//出现报错,原因是colA是不能插入null值。
那么如果两个字段同时插入空值,会怎么样。INSERT INTO `test`(`colA`, `colB`) VALUES ('', '');
插入成功,说明字段即使设置为null值的时候,是可以插入空值的
---------------------------------------------------------------查询---------------------------------------------------------
现在表里有三条数据
接下来我们使用 is not null 和 <> 检索数据表里的数据
1、使用IS NOT NULL 的查询1 SELECT * FROM `test` WHERE colA IS NOT NULL
1 SELECT * FROM `test` WHERE colB IS NOT NULL
结论:使用 IS NOT NULL 查询不会过滤空值,但是会过滤掉NULL。
2、使用 <> 的查询1 SELECT * FROM `test` WHERE colA <> '';
1 SELECT * FROM `test` WHERE colA <> '';
结论:使用 <> 会过滤掉NULL和空值。
3、使用 count 查询1 SELECT COUNT(colA) FROM `test`;
1 SELECT COUNT(colB) FROM `test`;
结论:使用 count 会过滤掉 NULL 值,但是不会过滤掉空值。
总结
1、空值不占空间,NULL值占空间(占用一个字节)。
2、当字段不为NULL时,也可以插入空值。
3、当使用 IS NOT NULL 或者 IS NULL 时,只能查出字段中没有不为NULL的或者为 NULL 的,不能查出空值。
4、使用 <> 查询时,会筛选掉空值和NULL值。
5、使用 count 统计时会过滤掉 NULL 值,但是不会过滤掉空值。
-
C#中String.Empty、NULL与““三者的区别
2021-03-04 16:56:47C#中String.Empty、NULL与""三者的区别 参考网址:https://blog.csdn.net/ldy597321444/article/details/53286227 ...Null,就是没有值,也没分配地址,此处可以理解成什么都没有。 这里就是想占坑的意思 ...C#中String.Empty、NULL与""三者的区别
参考网址:https://blog.csdn.net/ldy597321444/article/details/53286227
String.Empty和""是一样的,都是空。
Null,就是没有值,也没分配地址,此处可以理解成什么都没有。这里就是想占坑的意思
-
Mysql 数据库表设计 应该注意什么?
2020-07-13 17:00:58良好的逻辑设计和物理设计是高性能的基石,在进行设计的时候应该根据系统将要... 适用小而简单的合适数据类型,除非真实数据模型中有确切的需要,否则应该尽可能地避免使用NULL值(详细见 为什么Mysql 尽量使用NULL值?良好的逻辑设计和物理设计是高性能的基石,在进行设计的时候应该根据系统将要执行的查询语句来设计表,这往往需要权衡各种因素,那么这些因素有哪些呢?我们应该重点关注什么呢?这常常苦恼着我们,良好的设计原则是普遍适用的,下面文章将介绍一些常规的思考维度提供参考
- 尽量避免过度设计,例如会导致极其复杂查询的表设计,或者有很多列的表设计(很多的意思是介于有点多和非常多之间)
- 适用小而简单的合适数据类型,除非真实数据模型中有确切的需要,否则应该尽可能地避免使用NULL值(详细见 为什么Mysql 尽量使用NULL值?)。
- 尽量适用相同的数据类型存储相似或者相关的值,尤其是要在关联条件中适用的列(不然会涉及到类型转换,消耗性能)
- 注意可变长字符串,其在临时表和排序时可能导致悲观的按最大长度分配内存。
- 尽量适用整型定义标识列。
- 避免适用Mysql 已经遗弃的特性,例如指定浮点数的精度,或者整数的显示宽度。
- 小心适用ENUM和SET。虽然他们用起来比较方便,但是不要滥用,否则有时候会变成陷阱。最好避免适用BIT。
- 范式是好的,但是反范式(大多数情况下意味着重复数据)有时也是必须的,并且带来好处(查询获取数据等更优秀,但是同样带来维护成本复杂度成本等的提升)。
附加:范式和反范式的优缺点?如果考量?
范式是什么?范式是数据库设计的一些规则,反范式就是不遵循那些规则。这里像数据库范式中的字段冗余就是反范式,也是我们工作中常用的(详细的可以查找相关的文件进行了解)。
范式化好处
- 范式化的更新操作通常比反范式化更快
- 当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据。
- 范式化的表通常更小,可以更好地放在内存里,所以执行操作更快。
- 很少有多余的数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY语句。
范式坏处
- 范式化设计查询常常需要关联表,在一些复杂的查询中,关联的代价不仅昂贵,也可能使一些索引失效。
反范式好处
- 反范式所有数据都在一张表,可以很好地避免关联。
- 不需要关联表,则对大部分查询最差的情况—–即使表没有使用索引—是全表扫描。当数据比内存大时这可能比关联要快的多。因为这样避免了随机I/O(全表扫描基本上是顺序I/O,但也不是100%的,跟引擎的实现有关)。
- 单独的表也能适用更有效的索引策略。
- 能更有效的执行这个查询
反范式坏处
- 表中冗余了数据,那么就需要更多的空间,典型的空间换时间策略
- 多份重复数据,那么在进行数据一致性维护上需要更多的操作,成本提升
因此在设计表的时候,注意空间和时间 你更需要哪一个。
-
JavaScript 中是如何比较两个元素是否 "相同" 的
2021-01-10 01:54:22到底是什么意思?举个栗子,<code>1</code> 和 <code>new Number(1)</code> 被认为是 equal,[1]</code> 和 [1]</code> 被认为是 equal(尽管它们的引用并不相同),当然ÿ... -
c语言指针深解
2008-09-26 09:34:00关于C语言的指针,相信有很多人都已经明白了它是什么意思,但是也有很多人处在迷茫之中,我们一起来看看吧 指针就是其值为内存地址的变量---------直观的理解,可以参考 变量是直接引用变量的值,而指针是间接...关于C语言的指针,相信有很多人都已经明白了它是什么意思,但是也有很多人处在迷茫之中,我们一起来看看吧
指针就是其值为内存地址的变量---------直观的理解,可以参考
变量是直接引用变量的值,而指针是间接(通过值的地址)来引用变量的值------只管理解,可以参考
指针可以被初始化为0,null,或一个地址值
也许通过实验能更加深理解:
int main()
{
int a;
int *p;//现在我们初始化a
a=47;
p=a;printf("%d/n",p);
}vs 2008:
------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(11) : warning C4047: “=”: “int *”与“int”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,1 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========输出47
---------------------------------------------------------------------------------------------------------------
其实指针变量也是变量,你可以对它赋值,这没有什么好奇怪的!
#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=47;
p=a;
c=&a;printf("%d/n",p);
printf("%p/n",c);}
------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
输出:47
0012FF60
请按任意键继续. . .--------------------------------------------------------------------------------------------------------------------------------
其中%p是格式化输出标记,他说了:“用系统实现时所定义的方式(这个系统是以哪种方式来显示指针,这里很显然是十六进制的)显示一个指针的值”
呵呵,可我们显示的是c,仅仅是一个普通的int类型,它的值是一个地址!!他以16进制的方式显示了这个地址(a的地址)的值。
#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=47;
p=a;
c=&a;printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
}------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========输出:
47
0012FF60
0000002F
呵呵,看清楚了吧,%p不是跟指针绑定的,他只是说:“以这个系统显示指针的方式来显示这个数!”,他有什么别的权利!
#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=47;
p=a;
c=&a;printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
}------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========输出:
47
0012FF60
0000002F
0012FF48
很简单,最后一行输出的是c的地址的值(我们知道了p在这个系统中就是以十六进制来显示的,所以我们用p来格式化输出),c本身的值也是一个地址(是a的地址),但是你应该知道什么是什么!
到了这里你还没有看到指针到底有什么特别之处,你所看到的指针变量的功能和普通的变量似乎没有什么区别,正象第一行输出那样,他被赋予了一个整数值然后就被输出了!!
我们需要时刻记住,一个指针变量是用来存储地址的,但是整数值也可以表示地址,所以我们将一个整数值赋予一个指针变量也没有什么不妥的地方,这就同将一个地址的整数值赋予他是一样的。也许你有兴趣看一下地址为47的这个内存单元中存储的内容,我们试试吧!
#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=0x000019b0;
p=a;
c=&a;printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
}------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========这里可以通过编译,但是却不能运行,这是为什么呢(而我们所做的改动仅仅是最后一行的输出语句,也就是说问题出在输出语句上)??能通过编译,说明了编译器并不认为我们的改动有什么错误!!!但是为什么不能运行呢??
、#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=47;
p=0x0012FF60;
c=&a;printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
}------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========正常编译,正常运行
1245024
0012FF60
0000002F
47
我们将a的地址赋予 p,这个时候我们再*p就可以正确得到了输出 值47!!
上一个例子我们不能执行呢?我们不知道内存的47单元是否有可用的值!!!!有吗?我们不知道!!!但是我们想知道,到底怎么办!!!
#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=47;
p=0x0012FF60;
*p=99;
c=&a;printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
printf("%d/n",a);
}------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(15) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========输出:
1245024
0012FF60
0000063
99
99
可见,我们通过指针改变了变量a的地址单元的值,哈哈,你也许认为我们能通过这样的方式来改变其他地址的值!!这样的想法对吗????
#include<stdio.h>
int main()
{
int a;
int *p;int c;
//现在我们初始化a
a=47;
p=0x0012FF58;
*p=99;
c=&a;printf("%x/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
printf("%d/n",a);
}------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(15) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========正常编译可以运行:
12ff58
0012FF60
0000002F
0012FF48
99
47
惊呼吧,似乎发现了新大陆,可是我们把0x0012FF58改成0x0012FF59你会看到不能运行,你会发现系统提示你a的地盘被入侵了!!!!呵呵!!!改成其他值似乎也不能解决不能运行的现象。
栈是个好东西,你不能破坏他的规矩,你要按照规矩来,你不能做超出规矩的动作!!
你必须遵循内存中栈的规则,否则你将破坏内存的分配机制,进而做出不安全的操作!!这是一中保护措施!!这里间隔2的地址是可以赋值的!!但是要记住一定得不侵犯别人的东西!!
所以呢,你如果要通过这样的方式来改变内存中的值,你必须对内存的状况透彻地了解,可是似乎我们没有这么大的能力吧!!
所以通过变量来实现这样的动作更理智和现实!!
所以呢,你可以看到指针的作用:你就是用她来保存一个变量的地址!!然后呢,你可以直接来得到那个变量的地址!!然后呢,你可以通过*P的形式,来访问或者修改这个变量的值!!而普通的变量,你就不能在之前面加上*来访问这个变量的值所代表的内存单元的值,这个是指针变量的专利产品!!
-
Java eclipse 错误:For input string
2020-07-02 20:05:392、什么意思 参考资料可知,For input string,表示数据类型转换错误。 当一个数据类型使用**toString()**方法进行转换成字符串时,转换失败就会报这个错误。 3、排除错误 找到进行数据类型需要转换的地方,仔细对照... -
《你必须知道的495个C语言问题(中文版)》.pdf
2011-05-19 12:34:055.4 NULL是什么,它是怎么定义的? 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? ... -
你必须知道的495个C语言问题.[美]Steve Summit(带详细书签).pdf 压缩版
2018-04-08 02:26:505.4 NULL是什么,它是怎么定义的? 85 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 85 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? 86 ... -
你必须知道的495个C语言问题.[美]Steve Summit(带详细书签).pdf 高清版
2018-04-08 01:22:395.4 NULL是什么,它是怎么定义的? 85 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 85 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? 86 ... -
你必须知道的495个C语言问题
2015-05-08 11:09:255.4 NULL是什么,它是怎么定义的? 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL是如何定义的? 5.6 如果NULL定义成#defineNULL((char*)0),不就可以向函数传入不加转换的NULL了吗? 5.7 我的... -
你必须知道的495个C语言问题.pdf
2013-01-20 14:30:545.4 NULL是什么,它是怎么定义的? 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? 5.7 我的... -
[你必须知道的495个C语言问题]人民邮电出版社.扫描版.pdf
2011-10-01 21:39:525.4 NULL是什么,它是怎么定义的? 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? 5.7 我的... -
你必须知道的495个C语言问题(高清版)
2010-03-31 16:24:095.4 NULL是什么,它是怎么定义的? 56 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 56 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? ... -
《你必须知道的495个C语言问题》
2010-03-20 16:41:185.4 NULL是什么,它是怎么定义的? 56 5.5 在使用非零位模式作为空指针的内部表示的机器上,NULL 是如何定义的? 56 5.6 如果NULL定义成#define NULL((char *)0) ,不就可以向函数传入不加转换的NULL 了吗? ... -
C语言FAQ 常见问题列表
2010-10-28 16:41:29o 2.4 extern 在函数声明中是什么意思? o 2.5 关键字 auto 到底有什么用途? o 2.6 我似乎不能成功定义一个链表。我试过 typedef struct { char *item; NODEPTR next; } *NODEPTR; 但是编译器报了错误信息。难道... -
-
-
"cm是什么意思单位", "cm是什么单位的名称" ] } 对于select多选类型表单,默认数据库保存值为半角逗号分隔的多个选择值。当你设置字段类型为无符号整型时,数据库会保存多个选择值的求和值(当然前提是选择值都是...
-
你必须知道的495个C语言问题(PDF)
2009-09-15 10:25:471.4 extern 在函数声明中是什么意思? . . . . . . . . . . . . . . . . . 2 1.5 关键字auto 到底有什么用途? . . . . . . . . . . . . . . . . . . . 2 1.6 我似乎不能成功定义一个链表。我试过typedef struct f ... -
-
springmybatis
2015-09-05 06:54:28MyBatis ...-- 返回list 的select 语句,注意 resultMap 的值是指向前面定义好的 --> select * from user where userName like #{userName} 在 IUserOperation 接口中增加方法:public List... -
Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--详细书签版
2013-02-04 12:43:5214.1 什么是事务 386 14.2 事务的ACID属性 387 14.3 事务隔离级别 388 14.4 多版本读一致性 390 14.5 事务控制语句 391 14.5.1 Commit(提交) 391 14.5.2 Savepoint(保存点) 391 14.5.3 Rollback(回滚) 391 ... -
Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码
2013-02-04 12:49:3314.1 什么是事务 386 14.2 事务的ACID属性 387 14.3 事务隔离级别 388 14.4 多版本读一致性 390 14.5 事务控制语句 391 14.5.1 Commit(提交) 391 14.5.2 Savepoint(保存点) 391 14.5.3 Rollback(回滚) 391 ... -
-
MySQL命令大全
2018-01-15 11:19:17上面命令参数是常用参数的一部分,详细情况可参考文档。此处的mydb是要登录的数据库的名称。 在进行开发和实际应用中,用户不应该只用root用户进行连接数据库,虽然使用root用户进行测试时很方便,但会给系统带来... -
最新名企标准通用C++面试题,
2009-05-08 17:34:16因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。 void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *...