在傳統操做系統中,每一個進程有一個地址空間,並且默認就有一個控制線程python
線程顧名思義,就是一條流水線工做的過程,一條流水線必須屬於一個車間,一個車間的工做過程是一個進程mysql
車間負責把資源整合到一塊兒,是一個資源單位,而一個車間內至少有一個流水線linux
流水線的工做須要電源,電源就至關於cpu程序員
因此,進程只是用來把資源集中到一塊兒(進程只是一個資源單位,或者說資源集合),而線程纔是cpu上的執行單位。redis
多線程(即多個控制線程)的概念是,在一個進程中存在多個控制線程,多個控制線程共享該進程的地址空間,至關於一個車間內有多條流水線,都共用一個車間的資源。sql
例如,北京地鐵與上海地鐵是不一樣的進程,而北京地鐵裏的13號線是一個線程,北京地鐵全部的線路共享北京地鐵全部的資源,好比全部的乘客能夠被全部線路拉。mongodb
l 建立進程的開銷要遠大於線程?數據庫
若是咱們的軟件是一個工廠,該工廠有多條流水線,流水線工做須要電源,電源只有一個即cpu(單核cpu),一個車間就是一個進程,一個車間至少一條流水線(一個進程至少一個線程),建立一個進程,就是建立一個車間(申請空間,在該空間內建至少一條流水線),而建線程,就只是在一個車間內造一條流水線,無需申請空間,因此建立開銷小編程
l 進程之間是競爭關係,線程之間是協做關係?vim
車間直接是競爭/搶電源的關係,競爭(不一樣的進程直接是競爭關係,是不一樣的程序員寫的程序運行的,迅雷搶佔其餘進程的網速,360把其餘進程當作病毒乾死),一個車間的不一樣流水線式協同工做的關係(同一個進程的線程之間是合做關係,是同一個程序寫的程序內開啓動,迅雷內的線程是合做關係,不會本身幹本身)
多線程指的是,在一個進程中開啓多個線程,簡單的講:若是多個任務共用一塊地址空間,那麼必須在一個進程內開啓多個線程。詳細的講分爲4點:
1. 多線程共享一個進程的地址空間
2. 線程比進程更輕量級,線程比進程更容易建立可撤銷,在許多操做系統中,建立一個線程比建立一個進程要快10-100倍,在有大量線程須要動態和快速修改時,這一特性頗有用
3. 若多個線程都是cpu密集型的,那麼並不能得到性能上的加強,可是若是存在大量的計算和大量的I/O處理,擁有多個線程容許這些活動彼此重疊運行,從而會加快程序執行的速度。
4. 在多cpu系統中,爲了最大限度的利用多核,能夠開啓多個線程,比開進程開銷要小的多。(這一條並不適用於python)
進程也有死鎖與遞歸鎖。
所謂死鎖: 是指兩個或兩個以上的進程或線程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程。
遞歸鎖,在Python中爲了支持在同一線程中屢次請求同一資源,python提供了可重入鎖RLock,
這個RLock內部維護着一個Lock和一個counter變量,counter記錄了acquire的次數,從而使得資源能夠被屢次require。直到一個線程全部的acquire都被release,其餘的線程才能得到資源。上面的例子若是使用RLock代替Lock,則不會發生死鎖:
from threading import Thread,Lock,RLock import time # mutexA=Lock() # mutexB=Lock() mutexA=mutexB=RLock() #一個線程拿到鎖,counter加1,該線程內又碰到加鎖的狀況,則counter繼續加1,這期間全部其餘線程都只能等待,等待該線程釋放全部鎖,即counter遞減到0爲止 class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('%s 拿到了A鎖' %self.name) mutexB.acquire() print('%s 拿到了B鎖' % self.name) mutexB.release() #1 mutexA.release() #0 def f2(self): mutexB.acquire() print('%s 拿到了B鎖' % self.name) time.sleep(0.1) mutexA.acquire() print('%s 拿到了A鎖' % self.name) mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(10): t=MyThread() t.start()
同進程的同樣,Semaphore管理一個內置的計數器,每當調用acquire()時內置計數器-1;調用release() 時內置計數器+1;計數器不能小於0;當計數器爲0時,acquire()將阻塞線程直到其餘線程調用release()。
實例:(同時只有5個線程能夠得到semaphore,便可以限制最大鏈接數爲5):
from threading import Thread,Semaphore,current_thread import time,random sm=Semaphore(5) def task(): with sm: print('%s is laing' %current_thread().getName()) time.sleep(random.randint(1,3)) if __name__ == '__main__': for i in range(20): t=Thread(target=task) t.start()
與進程池是徹底不一樣的概念,進程池Pool(4),最大隻能產生4個進程,並且從頭至尾都只是這四個進程,不會產生新的,而信號量是產生一堆線程/進程
同進程的同樣,線程的一個關鍵特性是每一個線程都是獨立運行且狀態不可預測。若是程序中的其 他線程須要經過判斷某個線程的狀態來肯定本身下一步的操做,這時線程同步問題就會變得很是棘手。爲了解決這些問題,咱們須要使用threading庫中的Event對象。 對象包含一個可由線程設置的信號標誌,它容許線程等待某些事件的發生。在 初始狀況下,Event對象中的信號標誌被設置爲假。若是有線程等待一個Event對象, 而這個Event對象的標誌爲假,那麼這個線程將會被一直阻塞直至該標誌爲真。一個線程若是將一個Event對象的信號標誌設置爲真,它將喚醒全部等待這個Event對象的線程。若是一個線程等待一個已經被設置爲真的Event對象,那麼它將忽略這個事件, 繼續執行
event.isSet():返回event的狀態值; event.wait():若是 event.isSet()==False將阻塞線程; event.set(): 設置event的狀態值爲True,全部阻塞池的線程激活進入就緒狀態, 等待操做系統調度; event.clear():恢復event的狀態值爲False。
例如,有多個工做線程嘗試連接MySQL,咱們想要在連接前確保MySQL服務正常才讓那些工做線程去鏈接MySQL服務器,若是鏈接不成功,都會去嘗試從新鏈接。那麼咱們就能夠採用threading.Event機制來協調各個工做線程的鏈接操做
from threading import Thread,Event,current_thread import time event=Event() def check(): print('checking MySQL...') time.sleep(5) event.set() def conn(): count=1 while not event.is_set(): if count > 3: raise TimeoutError('超時') print('%s try to connect MySQL time %s' %(current_thread().getName(),count)) event.wait(1) count+=1 print('%s connected MySQL' %current_thread().getName()) if __name__ == '__main__': t1=Thread(target=check) t2=Thread(target=conn) t3=Thread(target=conn) t4=Thread(target=conn) t1.start() t2.start() t3.start() t4.start()
定時器,指定n秒後執行某操做
from threading import Timer def hello(name): print("hello, world %s " %name) t = Timer(3, hello,args=('egon',)) t.start() # after 1 seconds, "hello, world" will be printed
queue隊列 :使用import queue,用法與進程Queue同樣
import queue q=queue.Queue(3) #隊列:先進先出 q.put(1) q.put(2) q.put(3) # q.put(4) # q.put_nowait(4) # q.put(4,block=False) q.put(4,block=True,timeout=3) # print(q.get()) # print(q.get()) # print(q.get()) q=queue.LifoQueue(3) #堆棧:後進先出 q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) q=queue.PriorityQueue(3) #優先級隊列 q.put((10,'a')) q.put((-3,'b')) q.put((100,'c')) print(q.get()) print(q.get()) print(q.get())
#提交任務的兩種方式:
#同步調用:提交完任務後,就在原地等待,等待任務執行完畢,拿到任務的返回值,才能繼續下一行代碼,致使程序串行執行
#異步調用+回調機制:提交完任務後,不在原地等待,任務一旦執行完畢就會觸發回調函數的執行, 程序是併發執行
#進程的執行狀態:
#阻塞
#非阻塞
# from multiprocessing import Pool
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time,random,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(random.randint(1,3)) return n**2 def handle(res): print('handle res %s' %res) if __name__ == '__main__': #同步調用 pool=ProcessPoolExecutor(2) for i in range(5): res=pool.submit(task,i).result() # print(res) handle(res) pool.shutdown(wait=True) # pool.submit(task,33333) print('主')
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time,random,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(random.randint(1,3)) # res=n**2 # handle(res) return n**2 def handle(res): res=res.result() print('handle res %s' %res) if __name__ == '__main__': #異步調用 pool=ProcessPoolExecutor(2) for i in range(5): obj=pool.submit(task,i) obj.add_done_callback(handle) #handle(obj) pool.shutdown(wait=True) print('主')
from concurrent.futures import ThreadPoolExecutor from threading import current_thread import requests import time def get(url): print('%s GET %s' %(current_thread().getName(),url)) response=requests.get(url) time.sleep(2) if response.status_code == 200: return {'url':url,'content':response.text} def parse(res): res=res.result() print('parse:[%s] res:[%s]' %(res['url'],len(res['content']))) if __name__ == '__main__': pool=ThreadPoolExecutor(2) urls=[ 'https://www.baidu.com', 'https://www.python.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', 'https://www.openstack.org', ] for url in urls: pool.submit(get,url).add_done_callback(parse) pool.shutdown(wait=True)
單純地切換反而會下降運行效率
協程:是單線程下的併發,又稱微線程,纖程。英文名Coroutine。一句話說明什麼是線程:協程是一種用戶態的輕量級線程,即協程是由用戶程序本身控制調度的。
總結協程特色:
必須在只有一個單線程裏實現併發
修改共享數據不需加鎖
用戶程序裏本身保存多個控制流的上下文棧
附加:一個協程遇到IO操做自動切換到其它協程(如何實現檢測IO,yield、greenlet都沒法實現,就用到了gevent模塊(select機制))
import time def consumer(res): '''任務1:接收數據,處理數據''' pass def producer(): '''任務2:生產數據''' res=[] for i in range(10000000): res.append(i) return res start=time.time() #串行執行 res=producer() consumer(res) stop=time.time() print(stop-start)
import time def consumer(): '''任務1:接收數據,處理數據''' while True: print('consumer') x=yield time.sleep(100) def producer(): '''任務2:生產數據''' g=consumer() next(g) for i in range(10000000): print('producer') g.send(i) start=time.time() #基於yield保存狀態,實現兩個任務直接來回切換,即併發的效果 #PS:若是每一個任務中都加上打印,那麼明顯地看到兩個任務的打印是你一次我一次,即併發執行的. producer() stop=time.time() print(stop-start) #
若是咱們在單個線程內有20個任務,要想實如今多個任務之間切換,使用yield生成器的方式過於麻煩(須要先獲得初始化一次的生成器,而後再調用send。。。很是麻煩),而使用greenlet模塊能夠很是簡單地實現這20個任務直接的切換
安裝模塊
pip3 install greenlet
from greenlet import greenlet import time def eat(name): print('%s eat 1' %name) time.sleep(1000) g2.switch('egon') print('%s eat 2' %name) g2.switch() def play(name): print('%s play 1' % name) g1.switch() #能夠在第一次switch時傳入參數,之後都不須要 print('%s play 2' % name) g1=greenlet(eat) g2=greenlet(play)
greenlet只是提供了一種比generator更加便捷的切換方式,當切到一個任務執行時若是遇到io,那就原地阻塞,仍然是沒有解決遇到IO自動切換來提高效率的問題。
單線程裏的這20個任務的代碼一般會既有計算操做又有阻塞操做,咱們徹底能夠在執行任務1時遇到阻塞,就利用阻塞的時間去執行任務2。。。。如此,才能提升效率,這就用到了Gevent模塊。
Gevent 是一個第三方庫,能夠輕鬆經過gevent實現併發同步或異步編程,在gevent中用到的主要模式是Greenlet, 它是以C擴展模塊形式接入Python的輕量級協程。 Greenlet所有運行在主程序操做系統進程的內部,但它們被協做式地調度。
#用法
g1=gevent.spawn(func,1,,2,3,x=4,y=5)建立一個協程對象g1,spawn括號內第一個參數是函數名,如eat,後面能夠有多個參數,能夠是位置實參或關鍵字實參,都是傳給函數eat的 g2=gevent.spawn(func2) g1.join() #等待g1結束 g2.join() #等待g2結束 #或者上述兩步合做一步:gevent.joinall([g1,g2]) g1.value#拿到func1的返回值
from gevent import monkey;monkey.patch_all() import gevent import time def eat(name): print('%s eat 1' %name) # gevent.sleep(3) time.sleep(3) print('%s eat 2' %name) def play(name): print('%s play 1' % name) # gevent.sleep(2) time.sleep(3) print('%s play 2' % name) g1=gevent.spawn(eat,'egon') g2=gevent.spawn(play,'alex') # gevent.sleep(1) # g1.join() # g2.join() gevent.joinall([g1,g2])
練習
經過gevent實現單線程下的socket併發(from gevent import monkey;monkey.patch_all()必定要放到導入socket模塊以前,不然gevent沒法識別socket的阻塞)
服務端
from gevent import monkey,spawn;monkey.patch_all() from threading import current_thread from socket import * def comunicate(conn): print('子線程:%s' %current_thread().getName()) while True: try: data=conn.recv(1024) if not data:break conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(ip,port): print('主線程:%s' %current_thread().getName()) server = socket(AF_INET, SOCK_STREAM) server.bind((ip,port)) server.listen(5) while True: conn, addr = server.accept() print(addr) # comunicate(conn) # t=Thread(target=comunicate,args=(conn,)) # t.start() spawn(comunicate,conn) server.close() if __name__ == '__main__': g=spawn(server,'127.0.0.1', 8081) g.join()
客戶端
多線程併發多個客戶端
from socket import * from threading import current_thread,Thread def client(): client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8081)) while True: client.send(('%s say hello' %current_thread().getName()).encode('utf-8')) data=client.recv(1024) print(data.decode('utf-8')) client.close() if __name__ == '__main__': for i in range(500): t=Thread(target=client) t.start()
MySQL是一個關係型數據庫管理系統,由瑞典MySQL AB 公司開發,目前屬於 Oracle 旗下公司。MySQL 最流行的關係型數據庫管理系統,在 WEB 應用方面MySQL是最好的 RDBMS (Relational Database Management System,關係數據庫管理系統) 應用軟件之一。
一、數據庫服務器:計算機
二、數據庫管理軟件:MySQL
三、數據庫/庫:文件夾
四、表:文件
五、記錄:一個事物的一系列典型的特徵:egon,male,18,oldgirl
六、數據:事物的特徵,sex='male'
#mysql就是一個基於socket編寫的C/S架構的軟件
#客戶端軟件
mysql自帶:如mysql命令,mysqldump命令等
python模塊:如pymysql
#分兩大類:
關係型:如sqllite,db2,oracle,access,sql server,MySQL,注意:sql語句通用
非關係型:mongodb,redis,memcache
#能夠簡單的理解爲:
關係型數據庫須要有表結構
非關係型數據庫是key-value存儲的,沒有表結構
1、二進制rpm包安裝
yum -y install mysql-server mysql
2、源碼安裝
1.解壓tar包
cd /software tar -xzvf mysql-5.6.21-linux-glibc2.5-x86_64.tar.gz mv mysql-5.6.21-linux-glibc2.5-x86_64 mysql-5.6.21
2.添加用戶與組
groupadd mysql useradd -r -g mysql mysql chown -R mysql:mysql mysql-5.6.21
3.安裝數據庫
su mysql cd mysql-5.6.21/scripts ./mysql_install_db --user=mysql --basedir=/software/mysql-5.6.21 --datadir=/software/mysql-5.6.21/data
4.配置文件
cd /software/mysql-5.6.21/support-files cp my-default.cnf /etc/my.cnf cp mysql.server /etc/init.d/mysql vim /etc/init.d/mysql #若mysql的安裝目錄是/usr/local/mysql,則可省略此步 修改文件中的兩個變動值 basedir=/software/mysql-5.6.21 datadir=/software/mysql-5.6.21/data
5.配置環境變量
vim /etc/profile export MYSQL_HOME="/software/mysql-5.6.21" export PATH="$PATH:$MYSQL_HOME/bin" source /etc/profile
6.添加自啓動服務
chkconfig --add mysql
chkconfig mysql on
7.啓動mysql
service mysql start
8.登陸mysql及改密碼與配置遠程訪問
mysqladmin -u root password 'your_password' #修改root用戶密碼 mysql -u root -p #登陸mysql,須要輸入密碼 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_password' WITH GRANT OPTION; #容許root用戶遠程訪問 mysql>FLUSH PRIVILEGES; #刷新權限
3、源碼安裝mariadb
1. 解壓
tar zxvf mariadb-5.5.31-linux-x86_64.tar.gz
mv mariadb-5.5.31-linux-x86_64 /usr/local/mysql //必需這樣,不少腳本或可執行程序都會直接訪問這個目錄
2. 權限
groupadd mysql //增長 mysql 屬組 useradd -g mysql mysql //增長 mysql 用戶 並歸於mysql 屬組 chown mysql:mysql -Rf /usr/local/mysql // 設置 mysql 目錄的用戶及用戶組歸屬。 chmod +x -Rf /usr/local/mysql //賜予可執行權限
3. 拷貝配置文件
cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf //複製默認mysql配置 文件到/etc目錄
4. 初始化
/usr/local/mysql/scripts/mysql_install_db --user=mysql //初始化數據庫 cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql //複製mysql服務程序 到系統目錄 chkconfig mysql on //添加mysql 至系統服務並設置爲開機啓動 service mysql start //啓動mysql
5. 環境變量配置
vim /etc/profile //編輯profile,將mysql的可執行路徑加入系統PATH export PATH=/usr/local/mysql/bin:$PATH source /etc/profile //使PATH生效。
6. 帳號密碼
mysqladmin -u root password 'yourpassword' //設定root帳號及密碼 mysql -u root -p //使用root用戶登陸mysql use mysql //切換至mysql數據庫。 select user,host,password from user; //查看系統權限 drop user ''@'localhost'; //刪除不安全的帳戶 drop user root@'::1'; drop user root@127.0.0.1; select user,host,password from user; //再次查看系統權限,確保不安全的帳戶均被刪除。 flush privileges; //刷新權限
7. 一些必要的初始配置
1)修改字符集爲UTF8
vi /etc/my.cnf 在[client]下面添加 default-character-set = utf8 在[mysqld]下面添加 character_set_server = utf8
2)增長錯誤日誌
vi /etc/my.cnf 在[mysqld]下面添加: log-error = /usr/local/mysql/log/error.log general-log-file = /usr/local/mysql/log/mysql.log 3) 設置爲不區分大小寫,linux下默認會區分大小寫。 vi /etc/my.cnf 在[mysqld]下面添加: lower_case_table_name=1
修改完重啓:
service mysql restart
安裝
#一、下載:MySQL Community Server 5.7.16
http://dev.mysql.com/downloads/mysql/
#二、解壓
若是想要讓MySQL安裝在指定目錄,那麼就將解壓後的文件夾移動到指定目錄,如:C:\mysql-5.7.16-winx64
#三、添加環境變量
【右鍵計算機】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變量】--》【在第二個內容框中找到 變量名爲Path 的一行,雙擊】 --> 【將MySQL的bin目錄路徑追加到變值值中,用 ; 分割】
#四、初始化
mysqld --initialize-insecure
#五、啓動MySQL服務
mysqld # 啓動MySQL服務
#六、啓動MySQL客戶端並鏈接MySQL服務
mysql -u root -p # 鏈接MySQL服務器
將MySQL服務製做成windows服務
上一步解決了一些問題,但不夠完全,由於在執行【mysqd】啓動MySQL服務器時,當前終端會被hang住,那麼作一下設置便可解決此問題:
注意:--install前,必須用mysql啓動命令的絕對路徑
# 製做MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --install
# 移除MySQL的Windows服務,在終端執行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --remove
註冊成服務以後,之後再啓動和關閉MySQL服務時,僅需執行以下命令:
# 啓動MySQL服務
net start mysql
# 關閉MySQL服務
net stop mysql
C:\Users\Administrator> mysqladmin -uroot -p password "123"
net stop MySQL mysqld --skip-grant-tables mysql -uroot -p update mysql.user set password=password("") where user='root' and host="localhost"; flush privileges; C:\Users\Administrator>tasklist |findstr mysql mysqld.exe 6316 Console 1 454,544 K C:\Users\Administrator>taskkill /F /PID 6316 成功: 已終止 PID 爲 6316 的進程。 C:\Users\Administrator>net start MySQL MySQL 服務正在啓動 . MySQL 服務已經啓動成功。
#1. 修改配置文件
[mysqld] default-character-set=utf8 [client] default-character-set=utf8 [mysql] default-character-set=utf8 #mysql5.5以上:修改方式有所改動 [mysqld] character-set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8 [mysql] default-character-set=utf8
#2. 重啓服務
#3. 查看修改結果:
mysql> \s show variables like '%char%'
有了mysql這個數據庫軟件,就能夠將程序員從對數據的管理中解脫出來,專一於對程序邏輯的編寫
mysql服務端軟件即mysqld幫咱們管理好文件夾以及文件,前提是做爲使用者的咱們,須要下載mysql的客戶端,或者其餘模塊來鏈接到mysqld,而後使用mysql軟件規定的語法格式去提交本身命令,實現對文件夾或文件的管理。該語法即sql(Structured Query Language 即結構化查詢語言)
SQL語言主要用於存取數據、查詢數據、更新數據和管理關係數據庫系統,SQL語言由IBM開發。SQL語言分爲3種類型:
#一、DDL語句 數據庫定義語言: 數據庫、表、視圖、索引、存儲過程,例如CREATE DROP ALTER
#二、DML語句 數據庫操縱語言: 插入數據INSERT、刪除數據DELETE、更新數據UPDATE、查詢數據SELECT
#三、DCL語句 數據庫控制語言: 例如控制用戶的訪問權限GRANT、REVOKE
create database db1 charset utf8;
show databases;
show create database db1;
alter database db1 charset gbk;
drop database db1;
select database();
use db1;
create table t1(id int,name char);
show tables;
show create table t1;
desc t1;
alter table t1 add sex char; alter table t1 drop sex; alter table t1 modify name char(16); alter table t1 change name Name char(13);
drop table t1;
insert into db1.t1 values (1,'egon'), (2,'alex'), (3,'wxx');
select id,name from db1.t1; select * from db1.t1;
update t1 set name='SB' where id=2;
delete from t1 where id=2;
儲引擎即表類型,mysql根據不一樣的表類型會有不一樣的處理機制
查看引擎
show engines;
建立引擎
create table t1(id int)engine=innodb; create table t2(id int)engine=myisam; create table t3(id int)engine=memory; create table t4(id int)engine=blackhole;
create table t8(n tinyint); insert into t8 values(-1); insert into t8 values(128); insert into t8 values(-129); create table t9(n tinyint unsigned); insert into t9 values(-1),(256);
#整型的寬度表明顯示寬度
create table t11(n int(3) unsigned zerofill);
create table t12(n int unsigned zerofill);
create table t13(
id int
);
create table t13(x float(255,30)); create table t14(x double(255,30)); create table t15(x decimal(65,30)); insert into t13 values(1.111111111111111111111111111111); insert into t14 values(1.111111111111111111111111111111); insert into t15 values(1.111111111111111111111111111111);
create table student( id int, name char(16), born_year year, birth_date date, class_time time, reg_time datetime ); insert into student values (1,'egon',now(),now(),now(),now()) ; insert into student values (2,'alex','1999','1999-11-11','11:11:11',"1999-11-11 11:11:11")
char:定長
varchar:變長
#寬度表明的是字符的個數
create table t16(name char(5)); create table t17(name varchar(5)); insert into t16 values('李傑 '); #'李傑 ' insert into t17 values('李傑 '); #'李傑 ' select char_length(name) from t16; #5 select char_length(name) from t17; #3 mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH'; select * from t16 where name='李傑'; select * from t17 where name='李傑'; select * from t16 where name like '李傑'; name char(5) egon |alex |wxx | name varchar(5) 1bytes+egon|1bytes+alex|1bytes+wxx|
create table employee( id int, name char(10), sex enum('male','female','other'), hobbies set('play','eat','music','read') ); insert into employee values (1,'egon','male','music,read'); insert into employee values (2,'alex','xxxx','music,read');