db2 varchar最大长度_char 还是 varchar 各个数据库都不同

导读:

郑松华,知数堂SQL 优化班老师 

现任 CCmediaService DBA,主要负责数据库优化相关工作

擅长SQL优化 ,数据核对

想阅读更多内容请点击订阅专栏

ad3c278b02f460ffcbe3f0ff50b057ab.png


大家好,我是知数堂SQL 优化班老师 网名:骑龟的兔子

一、需求背景

最近在做Oracle 数据库到其他数据库的 as is to be 整合项目,其中表要进行重新建模,重新定义列属性等工作,然后根据新的表结构,进行ETL ,这里就涉及到了一个,非常基础,但又容易忘掉的部分就是 char 和varchar ,虽然我们要进行换的不是MySQL,但我在MySQL 模拟了一下场景。 二、思路char和varchar 不管在Oracle 还是在MySQL 其基本是一样的,都是字符串,

但是又有些不一样,MySQL根据sql_mode定义不同,char也可以等同于varchar

如果你是Oracle DBA ,那问char 和varchar的不同 char(10)和varchar2(10)

char(10) 即使插入不够10 也占有10个 ,而varchar2(10) 就是限定了最大长度。

三、实验过程分析

下面是Oracle 环境下的实验

SQL> create table e1(n1 char(10) ,n2 varchar2(10));
Table created.
SQL> insert into e1 select concat('a',row_number() over(order by EMPNO) ) rn , concat('a',row_number() over(order by EMPNO) ) rn2 from emp ;

数据也非常简单,下面是两个字段的长度

SQL> select length(n1) ,n1,length(n2),n2 from e1 ;
LENGTH(N1) N1 LENGTH(N2) N2
---------- ---------- ---------- ----------
10 a1 2 a1
10 a2 2 a2
10 a3 2 a3
10 a4 2 a4
10 a5 2 a5
10 a6 2 a6
10 a7 2 a7
10 a8 2 a8
10 a9 2 a9
10 a10 3 a10
10 a11 3 a11
10 a12 3 a12
10 a13 3 a13
10 a14 3 a14

在这种情况下,分别运行了如下SQL

SQL> select length(n1) ,n1,length(n2),n2 from e1 where n1='a1';
LENGTH(N1) N1 LENGTH(N2) N2
---------- ---------- ---------- ----------
10 a1 2 a1
SQL> select length(n1) ,n1,length(n2),n2 from e1 where n2='a1';
LENGTH(N1) N1 LENGTH(N2) N2
---------- ---------- ---------- ----------
10 a1 2 a1

到现在为止,一切没有问题,那请看下面的SQL


SQL> select n1 ,(select b.n1 from e1 b where b.n1 = a.n2 ) from e1 a ;
N1 (SELECTB.N
---------- ----------
a1
a2
a3
a4
a5
a6
a7
a8
a9
a10
a11
a12
a13
a14
14 rows selected.

可以看到子查询部分为NULL了!!但是,我们从上面的SQL中可以看到里面的值是一样的

SQL> select n1 ,(select b.n1 from e1 b where trim(b.n1) = a.n2 ) b from e1 a ;
N1 B
---------- ----------
a1 a1
a2 a2
a3 a3
a4 a4
a5 a5
a6 a6
a7 a7
a8 a8
a9 a9
a10 a10
a11 a11
a12 a12
a13 a13
a14 a14
14 rows selected.

如果写成上面的SQL 添加trim 那也可以得到我们想要的结果。

如下所示,如果两个都是varchar2 或者 char 类型 就没问题

SQL> select n1 ,(select b.n1 from e1 b where b.n2 = a.n2 ) b from e1 a ;
N1 B
---------- ----------
a1 a1
a2 a2
a3 a3
a4 a4
a5 a5
a6 a6
a7 a7
a8 a8
a9 a9
a10 a10
a11 a11
a12 a12
a13 a13
a14 a14
14 rows selected.
SQL> select n1 ,(select b.n1 from e1 b where b.n1 = a.n1 ) b from e1 a ;
N1 B
---------- ----------
a1 a1
a2 a2
a3 a3
a4 a4
a5 a5
a6 a6
a7 a7
a8 a8
a9 a9
a10 a10
a11 a11
a12 a12
a13 a13
a14 a14
14 rows selected.

四、结论

从上面的实验,可以得到join 两边的数据类型一定要保持一致,以免出现不必要的错误。

很多人想,这种低级问题,我肯定不会去犯错,正常情况下大家都不会犯错误的。

但是如果要进行重新建模,进行数据整合ETL的时候,工作量大了,就难免会犯错。

MySQL 的char(10) 和varchar(10) SQL_MODE 默认情况下是一样的


SQL> create table e1(n1 char(10) ,n2 varchar(10));
Table created.
SQL> insert into e1 select concat('a',row_number() over(order by EMP_NO) ) rn , concat('a',row_number() over(order by EMP_NO) ) rn2 from employees limit 15

运行下如下SQL


root@mysql3308.sock>[employees]>select length(n1) ,n1,length(n2),n2 from e1 where n1='a1';
+------------+------+------------+------+
| length(n1) | n1 | length(n2) | n2 |
+------------+------+------------+------+
| 2 | a1 | 2 | a1 |
+------------+------+------------+------+
1 row in set (0.00 sec)
root@mysql3308.sock>[employees]>select length(n1) ,n1,length(n2),n2 from e1 where n2='a1';
+------------+------+------------+------+
| length(n1) | n1 | length(n2) | n2 |
+------------+------+------------+------+
| 2 | a1 | 2 | a1 |
+------------+------+------------+------+
1 row in set (0.00 sec)

从结果中可以看出,LENGTH 都一样!

运行的SQL 结果也是一样的


root@mysql3308.sock>[employees]>select n1 ,(select b.n1 from e1 b where b.n1 = a.n2 ) b from e1 a ;
+------+------+
| n1 | b |
+------+------+
| a1 | a1 |
| a2 | a2 |
| a3 | a3 |
| a4 | a4 |
| a5 | a5 |
| a6 | a6 |
| a7 | a7 |
| a8 | a8 |
| a9 | a9 |
| a10 | a10 |
| a11 | a11 |
| a12 | a12 |
| a13 | a13 |
| a14 | a14 |
| a15 | a15 |
+------+------+
15 rows in set (0.00 sec)
root@mysql3308.sock>[employees]>select n1 ,(select b.n1 from e1 b where trim(b.n1) = a.n2 ) b from e1 a ;
+------+------+
| n1 | b |
+------+------+
| a1 | a1 |
| a2 | a2 |
| a3 | a3 |
| a4 | a4 |
| a5 | a5 |
| a6 | a6 |
| a7 | a7 |
| a8 | a8 |
| a9 | a9 |
| a10 | a10 |
| a11 | a11 |
| a12 | a12 |
| a13 | a13 |
| a14 | a14 |
| a15 | a15 |
+------+------+
15 rows in set (0.00 sec)
root@mysql3308.sock>[employees]>select n1 ,(select b.n1 from e1 b where b.n2 = a.n2 ) b from e1 a ;
+------+------+
| n1 | b |
+------+------+
| a1 | a1 |
| a2 | a2 |
| a3 | a3 |
| a4 | a4 |
| a5 | a5 |
| a6 | a6 |
| a7 | a7 |
| a8 | a8 |
| a9 | a9 |
| a10 | a10 |
| a11 | a11 |
| a12 | a12 |
| a13 | a13 |
| a14 | a14 |
| a15 | a15 |
+------+------+
15 rows in set (0.00 sec)

但是把SQL_MODE改成如下

set session sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';

root@mysql3308.sock>[employees]>set session sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected, 1 warning (0.00 sec)
root@mysql3308.sock>[employees]>select length(n1) ,n1,length(n2),n2 from e1 ;
+------------+------------+------------+------+
| length(n1) | n1 | length(n2) | n2 |
+------------+------------+------------+------+
| 10 | a1 | 2 | a1 |
| 10 | a2 | 2 | a2 |
| 10 | a3 | 2 | a3 |
| 10 | a4 | 2 | a4 |
| 10 | a5 | 2 | a5 |
| 10 | a6 | 2 | a6 |
| 10 | a7 | 2 | a7 |
| 10 | a8 | 2 | a8 |
| 10 | a9 | 2 | a9 |
| 10 | a10 | 3 | a10 |
| 10 | a11 | 3 | a11 |
| 10 | a12 | 3 | a12 |
| 10 | a13 | 3 | a13 |
| 10 | a14 | 3 | a14 |
| 10 | a15 | 3 | a15 |
+------------+------------+------------+------+
15 rows in set (0.00 sec)
root@mysql3308.sock>[employees]>select length(n1) ,n1,length(n2),n2 from e1 where n1='a1';
Empty set (0.00 sec)
root@mysql3308.sock>[employees]>select length(n1) ,n1,length(n2),n2 from e1 where n2='a1';
+------------+------------+------------+------+
| length(n1) | n1 | length(n2) | n2 |
+------------+------------+------------+------+
| 10 | a1 | 2 | a1 |
+------------+------------+------------+------+
1 row in set (0.00 sec)
root@mysql3308.sock>[employees]>select n1 ,(select b.n1 from e1 b where b.n1 = a.n2 ) b from e1 a ;
+------------+------+
| n1 | b |
+------------+------+
| a1 | NULL |
| a2 | NULL |
| a3 | NULL |
| a4 | NULL |
| a5 | NULL |
| a6 | NULL |
| a7 | NULL |
| a8 | NULL |
| a9 | NULL |
| a10 | NULL |
| a11 | NULL |
| a12 | NULL |
| a13 | NULL |
| a14 | NULL |
| a15 | NULL |
+------------+------+
15 rows in set (0.00 sec)
root@mysql3308.sock>[employees]>select n1 ,(select b.n1 from e1 b where trim(b.n1) = a.n2 ) b from e1 a ;
+------------+------------+
| n1 | b |
+------------+------------+
| a1 | a1 |
| a2 | a2 |
| a3 | a3 |
| a4 | a4 |
| a5 | a5 |
| a6 | a6 |
| a7 | a7 |
| a8 | a8 |
| a9 | a9 |
| a10 | a10 |
| a11 | a11 |
| a12 | a12 |
| a13 | a13 |
| a14 | a14 |
| a15 | a15 |
+------------+------------+
15 rows in set (0.00 sec)

谢谢大家~ 欢迎转发

如有关于SQL优化方面疑问需要交流的,请加入QQ群(579036588),并@骑兔子的龟 就可与我联系

更多松华老师文章推荐: 有趣的SQL(一) 有趣的SQL(二)两个表没连接条件的JOIN 有趣的SQL(三)行转列,列转行和复制MySQL where 条件的这个坑你碰到过没 变化多端的SQL写法,你get到了吗? 从MySQL5.5到MySQL8.0子查询进化之路SQL 优化案例一则 SQL优化很难怎么办? 给你一个简单暴力的办法 「周四见」公开课⎢《资深DBA带你学习SQL开发和优化》

END


03b6981dbb58d404f4f1da36c549206a.png

2019.10.24(今晚) 20:30

松华老师公开课

《资深DBA带你学习SQL开发和优化》

在腾讯课堂准时发车

欢迎大家参加

扫码或点击底部

“阅读原文”

直达报名地址

9f85881fe728b23c811cef906741f0e3.png

c2d35bd0d110f409e4dc1b3d4e68154f.png 8f0f942ae71c8b17a8ce51b28edb54f2.gif

扫码加入MySQL技术Q群

(群号:579036588)

   496e70b9c489f42c4e6767f973ce3bf9.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值