mysql> create table t1(id tinyint); # 默認有符號,即數字前有正負號
mysql> create table t1(id tinyint unsigned);
若是寬度小於設定的寬度(這裏寬度爲4),則自動填充0,須要注意的是,這只是最後顯示的結果,在MySQL中實際存儲的仍是1html
用zerofill測試整數類型的顯示寬度python
mysql> create table t7(x int(3) zerofill); mysql> insert into t7 values -> (1), -> (11), -> (111), -> (1111); mysql> select * from t7; +------+ | x | +------+ | 001 | | 011 | | 111 | | 1111 | #超過寬度限制仍然能夠存 +------+
注意:對於整型來講,數據類型後面的寬度並非存儲長度限制,而是顯示限制,假如:int(8),那麼顯示時不夠8位則用0來填充,夠8位則正常顯示,經過zerofill來測試,存儲長度仍是int的4個字節長度。默認的顯示寬度就是可以存儲的最大的數據的長度,好比:int無符號類型,那麼默認的顯示寬度就是int(10),有符號的就是int(11),由於多了一個符號,因此咱們沒有必要指定整數類型的數據,不必指定寬度,由於默認的就可以將你存的原始數據徹底顯示mysql
int的存儲寬度是4個Bytes,即32個bit,即2**32sql
無符號最大值爲:4294967296-1數據庫
有符號最大值:2147483648-1windows
有符號和無符號的最大數字須要的顯示寬度均爲10,而針對有符號的最小值則須要11位才能顯示徹底,因此int類型默認的顯示寬度爲11是很是合理的服務器
最後:整形類型,其實沒有必要指定顯示寬度,使用默認的就oksession
查sql_mode併發
select @@sql_mode select @@global.sql_mode
sql_mode 經常使用來解決下面這幾類問題less
sql_mode經常使用值以下
簡單介紹詳情:https://www.cnblogs.com/clschao/articles/9962347.html
NO_ENGINE_SUBSTITUTION 寬鬆版——若是須要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常 STRICT_TRANS_TABLES 嚴格版——在該模式下,若是一個值不能插入到一個事務表中,則中斷當前的操做,對非事務表不作限制 NO_ZERO_IN_DATE: 在嚴格模式下,不容許日期和月份爲零
注意:MySQL5.6和MySQL5.7默認的sql_mode模式參數是不同的
若是設置的是寬鬆模式,那麼咱們在插入數據的時候,即使是給了一個錯誤的數據,也可能會被接受,而且不報錯,例如:我在建立一個表時,該表中有一個字段爲name,給name設置的字段類型時char(10),若是我在插入數據的時候,其中name這個字段對應的有一條數據的長度超過了10,例如'1234567890abc',超過了設定的字段長度10,那麼不會報錯,而且取前十個字符存上,也就是說你這個數據被存爲了'1234567890',而'abc'就沒有了,可是咱們知道,咱們給的這條數據是錯誤的,由於超過了字段長度,可是並無報錯,而且mysql自行處理並接受了,這就是寬鬆模式的效果,其實在開發、測試、生產等環境中,咱們應該採用的是嚴格模式,出現這種錯誤,應該報錯纔對,因此MySQL5.7版本就將sql_mode默認值改成了嚴格模式,而且咱們即使是用的MySQL5.6,也應該自行將其改成嚴格模式,而你記着,MySQL等等的這些數據庫,都是想把關於數據的全部操做都本身包攬下來,包括數據的校驗,其實好多時候,咱們應該在本身開發的項目程序級別將這些校驗給作了,雖然寫項目的時候麻煩了一些步驟,可是這樣作以後,咱們在進行數據庫遷移或者在項目的遷移時,就會方便不少,這個看大家自行來衡量。mysql除了數據校驗以外,你慢慢的學習過程當中會發現,它可以作的事情還有不少不少,將你程序中作的好多事情都包攬了。
改成嚴格模式後可能會存在的問題
若設置模式中包含了NO_ZERO_DATE,那麼MySQL數據庫不容許插入零日期,插入零日期會拋出錯誤而不是警告。例如表中含字段TIMESTAMP列(若是未聲明爲NULL或顯示DEFAULT子句)將自動分配DEFAULT '0000-00-00 00:00:00'(零時間戳),也或者是本測試的表day列默認容許插入零日期 '0000-00-00' COMMENT '日期';這些顯然是不知足sql_mode中的NO_ZERO_DATE而報錯。
模式設置和修改方法
方法一
先執行select @@sql_mode,複製查詢出來的值並將其中的NO_ZERO_IN_DATE,NO_ZERO_DATE刪除,而後執行set sql_mode = '修改後的值'或者set session sql_mode='修改後的值';,例如:set session sql_mode='STRICT_TRANS_TABLES';改成嚴格模式 此方法只在當前會話中生效,關閉當前會話就不生效了。
方法二
先執行select @@global.sql_mode,複製查詢出來的值並將其中的NO_ZERO_IN_DATE,NO_ZERO_DATE刪除,而後執行set global sql_mode = '修改後的值'。 此方法在當前服務中生效,從新啓動MySQL服務後失效
方法三
在mysql的安裝目錄下,或my.cnf文件(windows系統是my.ini文件),新增 sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION, 添加my.cnf以下: [mysqld] sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER 而後重啓mysql。 此方法永久生效.固然生產環境上是禁止重啓MySQL服務的,因此採用方式二加方式三來解決線上的問題,那麼即使是有一天真的重啓了MySQL服務,也會永久生效了。
注意:float只能精準8位,從整數開始從左往右
測試 mysql> create table t3(id float(60,30)); Query OK, 0 rows affected (1.70 sec) mysql> create table t4(id double(60,30)); Query OK, 0 rows affected (0.88 sec) mysql> create table t5(id decimal(60,30)); Query OK, 0 rows affected (0.96 sec) mysql> insert into t3 values(1.1111111111111111111111); Query OK, 1 row affected (0.13 sec) mysql> insert into t4 values(1.1111111111111111111111); Query OK, 1 row affected (0.22 sec) mysql> insert into t5 values(1.1111111111111111111111); Query OK, 1 row affected (0.09 sec) mysql> select * from t3; mysql> select * from t4; mysql> select * from t5;
能夠存儲二進制數或者十六進制數
詳情請看:https://www.cnblogs.com/clschao/articles/9959559.html
YYYY(範圍:1901~2155) ——2018
YYYY-MM-DD (範圍:1000-01-01~9999-12-31) ——2018-01-01
HH:MM:SS ——12:09:32
YYYY-MM-DD HH:MM:SS(範圍:1000-01-01 00:00:00~9999-12-31 23:59:59 )——2018-01-01 12:09:32
測試
mysql> create table t6(d1 year ,d2 date,d3 datetime); Query OK, 0 rows affected (1.75 sec) mysql> insert into t6 values(now(),now(),now()); Query OK, 1 row affected, 1 warning (0.12 sec) mysql> select * from t6;
詳情:https://www.cnblogs.com/clschao/articles/9959559.html
針對char類型,mysql在存儲的時候會將不足規定長度的數據使用後面(右邊補全)補充空格的形式進行補全,而後存放到硬盤中,可是在讀取或者使用的時候會自動去掉它給你補全的空格內容,由於這些空格並非咱們本身存儲的數據,因此對咱們使用者來講是無用的。
char和varchar性能對比
以char(5)和varchar(5)來比較,加入我要存三我的名:sb,ssb1,ssbb2 char: 優勢:簡單粗暴,無論你是多長的數據,我就按照規定的長度來存,5個5個的存,三我的名就會相似這種存儲:sb ssb1 ssbb2,中間是空格補全,取數據的時候5個5個的取,簡單粗暴速度快 缺點:貌似浪費空間,而且咱們未來存儲的數據的長度可能會良莠不齊 varchar: varchar類型不定長存儲數據,更爲精簡和節省空間 例如存上面三我的名的時候相似因而這樣的:sbssb1ssbb2,連着的,若是這樣存,請問這三我的名你還怎麼取出來,你知道取多長能取出第一個嗎?(超哥,我能看出來啊,那我只想說:滾犢子!) 不知道從哪開始從哪結束,遇到這樣的問題,你會想到怎麼解決呢?還記的嗎?想一想?socket?tcp?struct?把數據長度做爲消息頭。 因此,varchar在存數據的時候,會在每一個數據前面加上一個頭,這個頭是1-2個bytes的數據,這個數據指的是後面跟着的這個數據的長度,1bytes能表示2**8=256,兩個bytes表示2**16=65536,能表示0-65535的數字,因此varchar在存儲的時候是這樣的:1bytes+sb+1bytes+ssb1+1bytes+ssbb2,因此存的時候會比較麻煩,致使效率比char慢,取的時候也慢,先拿長度,再取數據。 優勢:節省了一些硬盤空間,一個acsii碼的字符用一個bytes長度就能表示,可是也並不必定比char省,看一下官網給出的一個表格對比數據,當你存的數據正好是你規定的字段長度的時候,varchar反而佔用的空間比char要多。 Value CHAR(4) Storage Required VARCHAR(4) Storage Required '' ' ' 4 bytes '' 1 byte 'ab' 'ab ' 4 bytes 'ab' 3 bytes 'abcd' 'abcd' 4 bytes 'abcd' 5 bytes 'abcdefgh' 'abcd' 4 bytes 'abcd' 5 bytes 缺點:存取速度都慢 總結: 因此須要根據業務需求來選擇用哪一種類型來存 其實在多數的用戶量少的工做場景中char和varchar效率差異不是很大,最起碼給用戶的感知不是很大,而且其實軟件級別的慢遠比不上硬件級別的慢,因此大家公司的運維發現項目慢的時候會加內存、換nb的硬盤,項目的效率提高的會不少,可是咱們做爲專業人士,咱們應該提出來這樣的技術點來提升效率。 可是對於InnoDB數據表,內部的行存儲格式沒有區分固定長度和可變長度列(全部數據行都使用指向數據列值的頭指針),所以在本質上,使用固定長度的CHAR列不必定比使用可變長度VARCHAR列性能要好。於是,主要的性能因素是數據行使用的存儲總量。因爲CHAR平均佔用的空間多於VARCHAR,所以使用VARCHAR來最小化須要處理的數據行的存儲總量和磁盤I/O是比較好的。 因此啊,兩個選哪一個均可以,若是是大型併發項目,追求高性能的時候,須要結合大家服務器的硬件環境來進行測試,看一下char和varchar哪一個更好,這也能算一個優化的點吧~~~~
測試:
枚舉類型(enum) An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.) 示例: CREATE TABLE shirts ( name VARCHAR(40), size ENUM('x-small', 'small', 'medium', 'large', 'x-large') ); INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small'); 集合類型(set) 不能爲數字,能夠變爲字符串 A SET column can have a maximum of 64 distinct members. 示例: CREATE TABLE myset (col SET('a', 'b', 'c', 'd')); INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
詳情請看:https://www.cnblogs.com/clschao/articles/9968396.html
create table t1(name char(10) not null);
create table t1(name char(10) not null default 'xx');
create table t1(name char(10) unique);
create table t1(id int primary key);
create table t1(id int primary key auto_increment); 前面必須是個key
在多的表裏面添加一個字段,並給這個字段加foreign key,好比: 出版社對於書籍是多對一的關係 一、先建立出版社表 publish表 二、建立書籍表,外鍵寫法: create table book( id int primary key, name char(10), pid int, foreign key(pid) references publish(id) ); 三、先給出版社插入數據
學生表(student)和客戶表(customer) 在數據少的表添加字段,若是同樣多隨便哪一個表都行 create table student( id int primary key, name char(10), cid int unique, foreign key(cid) references customer(id) );
在學生表獲取到qq
做者表和書籍表 須要藉助第三張表來完整二者的關係記錄 第三張表最後建立 create table authortobook( id int primary key, aurhor_id int, book_id int, foreign key(author_id) references author1(id), foreign key(book_id) references book1(id) )
查找代碼: