mysql 登錄命令: mysql -uroot -pbank 這句話的意思是用root用戶登錄,密碼是bank。 mysql -uroot -p bank 這句話的意思是用root用戶登錄,bank是進入後切換到bank這個資料庫,此時按下回車會提示輸入密碼。進入後不用use bank 來切換到b ...
mysql 登錄命令:
mysql -uroot -pbank 這句話的意思是用root用戶登錄,密碼是bank。
mysql -uroot -p bank 這句話的意思是用root用戶登錄,bank是進入後切換到bank這個資料庫,此時按下回車會提示輸入密碼。進入後不用use bank 來切換到bank資料庫,自動就是bank資料庫。
mysql -uroot -pbank <=等價於=> mysql -u root -pbank 也就是說-uroot 等價於 -u root 。不論中間是否有空格隔開都一樣。代表用root這個用戶進行登錄。
查看當前時間:
mysql> select now() from dual;
+---------------------+
| now() |
+---------------------+
| 2017-10-25 22:05:38 |
+---------------------+
1 row in set (0.03 sec)
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2017-10-25 22:05:47 |
+---------------------+
1 row in set (0.00 sec)
之所以要使用from dual是為了相容oracle資料庫,如果只是MySQL的話,可以省略from dual;因為某些資料庫伺服器規定查詢語句中必須包含from字句,併在其中至少指明一個表名。
MySQL字元型數據
字元型數據分為定長或者變長兩類,不同點在於固定長度的字元串使用空格向右填充,以保證占用同樣的位元組數;變長字元串不需要向右填充,並且所有位元組數可變。當定義一個字元串類型時,必須要指定能存放的字元串最大長度。例如,需要存儲最大不超過20個位元組的字元串,可以用下列方式:
char(20) /* fixed-length */
varchar(20) /* variable-length */
char最大可以設置為255個位元組,varchar則可以最多保存65535個位元組。要存儲比65535更長的字元串則要使用文本類型了。
文本數據
如果需要存儲的數據超過64KB(varchar的上限),就需要使用文本類型。
文本類型 最大能存儲的位元組數(B)
tinytext 255
text 65535
mediumtext 16777215
longtext 4294967295
觀察可以發現,其實是用規律的,255 = 2^8 -1 ; 65535 = 2^16 -1 ; 16777215 = 2^24 -1 ; 4294967295 = 2^32 -1 ;
註意事項:
1.如果被裝載到文本列中的數據超出了該類型的最大長度,數據會被截斷。
2.在向文本列裝載數據時,不會消除數據的尾部空格。而char類型會。
3.使用文本列進行排序、分組的時候,只會使用前1024個字元
4.這些不同的文本類型只是針對MySQL,sql Server對於大的字元型數據只提供text類型,而db2和oracle使用的數據類型是Clob。
5.現在MySQL允許varchar列最大容納65535個位元組了(在MysQL4中為255個字元),也就是和text一樣大了,所以一般情況不會用到tinytext、text了,超過65535用mediumtext或者longtext;少於65535則使用varchar。
6.Oracle中,char能容納2000個位元組,varchar2能容納4000個,sql Server中char和varchar都能容納8000個位元組。
MySQL中的浮點數
浮點數是用來表示實數的一種方法,它用 M(尾數) * B( 基數)的E(指數)次方來表示實數,相對於定點數來說,在長度一定的情況下,具有表示數據範圍大的特點。但同時也存在誤差問題。 浮點數有多種實現方法,電腦中浮點數的實現大都遵從 IEEE754 標準,IEEE754 規定了單精度浮點數和雙精度浮點數兩種規格:
單精度浮點數用4位元組(32bit)表示浮點數,格式是: 1位符號位 8位表示指數 23位表示尾數
雙精度浮點數用8位元組(64bit)表示浮點數,格式是: 1位符號位 11位表示指數 52位表示尾數
IEEE754標準還對尾數的格式做了規範:d.dddddd...,小數點左面只有1位且不能為零,電腦內部是二進位,因此,尾數小數點左面部分總是1。顯然,這個1可以省去,以提高尾數的精度。
下圖是IEEE754的浮點數標準圖:
由上圖可知,單精度浮點數的尾數雖然只有23位,但是由於第一位一定是1,所以其實是用24bit表示的;
雙精度浮點數的尾數雖然只有52位,但是由於第一位一定是1,所以其實是用53bit表示的;
IEEE754標準中,一個規格化32位的浮點數x的真值表示為:
x=(−1)S×(1.M)×2^e e=E−127其中尾數域表示的值是1.M。因為規格化的浮點數的尾數域最左位總是1,故這一位不予存儲,而認為隱藏在小數點的左邊。
8 位的階碼e指數為可以表達 0 到 255 之間的 256 個指數值。但是,指數可以為正數,也可以為負數。為了處理負指數的情況,實際的指數值按要求需要加上一個偏差(Bias)值作為保存在指數域中的值,單精度數的偏差值為 127;偏差的引入使得對於單精度數,實際可以表達的指數值的範圍就變成 -127(0 - 偏差值127) 到 128 (255 - 偏差值127)之間(包含兩端)。在本文中,最小指數和最大指數分別用 emin 和 emax 來表達。實際的指數值 -127(保存為全0)以及 +128(保存為全 1)保留用作特殊值的處理。
(1)最大正數
單精度浮點數最大正數值的符號位S=0,階碼E=254,指數e=254-127=127,尾數M=111 1111 1111 1111 1111 1111,其機器碼為:0 11111110 111 1111 1111 1111 1111 1111。
那麼最大正數值:
PosMax=(−1)S×1.M×2^e=+(1.11111111111111111111111)×2^127 ≈ 3.402823e+38 (2)最小正數 最小正數符號位S=0,階碼E=1,指數e=1-127=-126,尾數M=0,其機器碼為0 00000001 000 0000 0000 0000 0000 0000。 那麼最小正數為: PosMin=(−1)S×1.M×2e=+(1.0)×2−126 ≈ 1.175494e−38 當使用浮點類型時,可以指定其精度(小數點左邊右邊所允許的數字總位數)和有效位(小數點右邊所允許的數字位數)。比如float(5,2)代表的是小數點左邊3位,小數點右邊2位。因此,如果添加11.275會被四捨五入到11.28。最大支持添加的數字是999.99,當添加比999.99大的數字的時候,就會報錯。 註意,float也可以聲明為unsigned類型,但是這聲明只會禁止列中存放負數,並沒有改變該列存儲數據的範圍。 MySQL中的整數類型 類型 帶符號的範圍 無符號的範圍 tinyint -128~127 0~255 smallint -32768~32767 0~65535 mediumint -8388608~8388607 0~16777215 int -2147483648~2147483647 0~4294967295 bigint -9223372036854755808 0~18446744073709551615 ~ 9223372036854755807 當使用tinyint時,分配1位元組;使用smallint時,分配2位元組;使用mediumint時,分配3位元組;使用int時,分配4位元組;使用bigint,分配8位元組。 選擇類型時,只需要確保能夠容納預期的最大數字即可,這樣可以避免不必要的浪費。 MySQL的時間類型 類型 預設格式 允許的值 date YYYY-MM-DD 1000-01-01~9999-12-31 datetime YYYY-MM-DD HH:MI:SS 1000-01-01~9999-12-31 23:59:59 timestamp YYYY-MM-DD HH:MI:SS 1000-01-01~9999-12-31 23:59:59 year YYYY 1901~2155 time HHH:MI:SS -838:59:59~838:59:59 如上表,如果需要向預設格式為YYYY-MM-DD的日期列插入日期2017年1月23日,必須使用字元串'2017-01-23'。 timestamp類型和datetime類型一樣(包括了年月日 時分秒),但是Mysql伺服器可以支持在向表中添加或者修改數據行時,自動為timestamp類型列產生當前的日期和時間。 GMT和UTC時間 GMT時間就是著名的格林威治標準時間,其他所有地區都可以使用與GMT的差距的小時數來表示,比如GMT +8代表中國北京的時間。 UTC時間是剋服了GMT時間的一些缺陷後,用原子鐘提供的時間,比GMT更加準一些,其實還是以格林威治作為標準的。北京的時間可以表示為UTC +8 簡單地理解他倆,GMT舊一些,不太準;UTC新一些,用的技術更加高級,更加準。其他區別可以忽略不計。 現在電腦中都用了更加準確的utc時間,所以MySQL中可以使用utc_timestamp()來獲取。mysql> select utc_timestamp();
+---------------------+
| utc_timestamp() |
+---------------------+
| 2017-10-26 02:42:02 |
+---------------------+
1 row in set (0.02 sec)
可以看到返回的格式是YYYY-MM-DD HH:MI:SS。Sql Server可以用getutcdate()函數獲取。
查看全局時區和會話時區
mysql> SELECT @@global.time_zone,@@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+
1 row in set (0.00 sec)
可以看到,結果值為system,這表示伺服器根據資料庫所在地使用相應的時區設置。 假如你坐在中國,遠程一臺紐約的mysql伺服器,可以通過執行下麵的指令暫時改變當前會話的時區設置: SET time_zone = '+08:00';
mysql> select @@global.time_zone,@@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM | +08:00 |
+--------------------+---------------------+
1 row in set (0.00 sec)
此時會話中顯示的所有日期都符合北京時間。
如果需要向datetime或者timestamp列中添加一條2017年1月23日下午15:00的數據,可以使用下列的字元串:
‘2017-01-23 15:00:00’
'2017/01/23 15,00,00'
'2017,01,23 15,00,00'
'20170123150000'
以上的字元串都可以產生日期,但是會比較死板,必須要有固定的格式,缺一不可。
產生日期的函數
如果你現在手上的數據不是像上邊一樣的格式,而是其他類型的字元串,比如‘September 17, 2008’ 或者'September 2008 , 17' 等等更加隨意的排列方式,那麼怎麼辦呢,要不要一個一個轉化成上邊的那種格式呢,顯然,MySQL也考慮到了這種情況,所以提供了一個str_to_date()函數,可以將這種類型的數據不用修改成上邊那種格式就能直接插入到資料庫中。是不是很方便呢,來看看怎麼用的。 UPDATE TABLE1 SET birth_date = STR_TO_DATE('September 17 , 2008' , '%M %d , %Y') WHERE cust_id = 9999; 或者 UPDATE TABLE1 SET birth_date = STR_TO_DATE('September 2008 , 17' , '%M %Y , %d') WHERE cust_id = 9999; 這樣就可以插入到資料庫了,當然,此時在資料庫中保存的格式就變成 2008-09-17 00:00:00 這種格式的了. 用這個str_to_date()函數的時候,需要查閱下邊的表,來知道%M 代表什麼?%Y代表什麼? 就像C語言中%d代表整數,%f代表浮點數一樣,多用就自然記住了。 日期格式表 格式部件 描述 %M 月名稱(January,February,March.....) %m 月序號(01 ~ 12) %d 日序號(01 ~ 31) %j 日在一年中的序號(001 ~ 366) %W 星期名稱(Sunday , Monday,Tuesday....) %Y 4位數表示的年份(2011,2012 , 2013.....) %y 兩位數代表的年份(11,12,13......) %H 小時(00 ~ 23) %h 小時(01 ~ 12) %p A.M. 或者 P.M. %i 分鐘(00 ~ 59 ) %s 秒鐘(00 ~ 59 ) %f 微秒(000000 ~ 999999 ) 註意: 1.str_to_date()函數將根據格式字元串的內容自動決定返回datetime,date 或者 time 類性值。舉例來說,如果格式字元串只包含%H %i或者 %s,那麼將返回time值。 2.Oracle資料庫,to_date()函數和mysql的str_to_date()函數具有同樣的功能。 3.可以使用select current_date()返回當前date,使用select current_time()返回當前time,使用select current_timestamp()返回當前timestamp/datetime。 操作時間數據的幾個函數 1.date_add()函數 2.last_day()函數 3.convert_tz()函數 4.dayname()函數5.extract()函數 6.datediff()函數
下麵依次來看一下這幾個函數。
1.date_add()函數 MySQL的date_add()函數可以為指定的日期增加任意一段時間間隔(如天、月、年),並產生另外一個日期。 #在現在的時間基礎上添加5天。
mysql> select date_add(current_timestamp(),interval 5 day);
+----------------------------------------------+
| date_add(current_timestamp(),interval 5 day) |
+----------------------------------------------+
| 2017-10-31 11:58:00 |
+----------------------------------------------+
1 row in set (0.00 sec)
#在現在的時間的基礎上增加3小時25分鐘0秒
mysql> select date_add(current_timestamp(),interval '3:25:00' hour_second);
+--------------------------------------------------------------+
| date_add(current_timestamp(),interval '3:25:00' hour_second) |
+--------------------------------------------------------------+
| 2017-10-26 15:23:53 |
+--------------------------------------------------------------+
1 row in set (0.00 sec)
#在現在的時間的基礎上增加了1年12月
mysql> select date_add(current_timestamp(),interval '1-12' year_month);
+----------------------------------------------------------+
| date_add(current_timestamp(),interval '1-12' year_month) |
+----------------------------------------------------------+
| 2019-10-26 11:59:23 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select date_add(current_timestamp(),interval '5:10' minute_second);
+-------------------------------------------------------------+
| date_add(current_timestamp(),interval '5:10' minute_second) |
+-------------------------------------------------------------+
| 2017-10-26 12:07:59 |
+-------------------------------------------------------------+
1 row in set (0.02 sec)
常用的時間間隔類型表
間隔名稱 描述
second 秒數
minute 分鐘數
hour 小時數
day 天數
month 月份數
year 年份
minute_second 分鐘數和秒數,中間用“:”隔開
hour_second 小時數、分鐘數、秒數,中間用“:”隔開
year_month 年份和月份,中間用“-”隔開
2.last_day()函數
要獲取當前時刻的月底是哪一天,可以使用last_day()函數,這個函數的作用就是簡單地返回傳入的日期的月末日期。
mysql> select last_day(current_timestamp());
+-------------------------------+
| last_day(current_timestamp()) |
+-------------------------------+
| 2017-10-31 |
+-------------------------------+
1 row in set (0.00 sec)
可以像上邊一樣傳入datetime類型的值,也可以傳入date的類型值,都一樣會返回date類型的值。
3.convert_tz()函數
該函數能夠將某個時區的datetime類型的值轉化為另外一個時區的對應時間。在Oracle中,這個函數叫new_time()函數。
mysql> select convert_tz('2014-09-28','US/Eastern','UTC');
+---------------------------------------------+
| convert_tz('2014-09-28','US/Eastern','UTC') |
+---------------------------------------------+
| NULL |
+---------------------------------------------+
1 row in set (0.00 sec)
可以看到此時的返回值為null,是因為我的電腦上沒有安裝mysql的時區數據,就是說,系統現在不認識US/Eastern 這個地區,UTC地區也不認識。所以返回了一個空值。
4.dayname()函數
dayname()函數可以直接返回傳入的日期那天是星期幾。
mysql> select dayname('2008-09-18');
+-----------------------+
| dayname('2008-09-18') |
+-----------------------+
| Thursday |
+-----------------------+
1 row in set (0.00 sec)
比如上面的例子中,返回了2008年9月18日那天,是星期四。
除了dayname,還有monthname()函數,同理可以返回傳入日期代表的月份的名稱。比如下麵的例子:
mysql> select monthname('2008-09-18');
+-------------------------+
| monthname('2008-09-18') |
+-------------------------+
| September |
+-------------------------+
1 row in set (0.00 sec)
很簡單就能理解,不多說了。
5.extract()函數
該函數用於從日期或者時間中提取出某一部分內容。
mysql> select extract(hour_second from '2008-09-18 22:19:05');
+-------------------------------------------------+
| extract(hour_second from '2008-09-18 22:19:05') |
+-------------------------------------------------+
| 221905 |
+-------------------------------------------------+
1 row in set (0.02 sec)
mysql> select extract(year_month from '2008-09-18 22:19:05');
+------------------------------------------------+
| extract(year_month from '2008-09-18 22:19:05') |
+------------------------------------------------+
| 200809 |
+------------------------------------------------+
1 row in set (0.00 sec)
mysql> select extract(minute from '2008-09-18 22:19:05');
+--------------------------------------------+
| extract(minute from '2008-09-18 22:19:05') |
+--------------------------------------------+
| 19 |
+--------------------------------------------+
1 row in set (0.00 sec)
6.datediff()函數
該函數用於傳入兩個時間,求出他們之間的時間間隔。
比如
mysql> select datediff('2009-08-28','2009-08-24');
+-------------------------------------+
| datediff('2009-08-28','2009-08-24') |
+-------------------------------------+
| 4 |
+-------------------------------------+
1 row in set (0.00 sec)
可以看到該日期不包含最後一天,即24,25,26,27.不過,也有可能是25,26,27,28,總之是包含其中一天,不包含兩天。
註意點:
datediff函數會忽略參數中的時間值,就算我把前一個日期設置為一天的最後一秒,後一個日期設置為一天的第一秒,也不會影響計算結果。
比如:
mysql> select datediff('2009-08-28 23:59:59','2009-08-24 00:00:01');
+-------------------------------------------------------+
| datediff('2009-08-28 23:59:59','2009-08-24 00:00:01') |
+-------------------------------------------------------+
| 4 |
+-------------------------------------------------------+
1 row in set (0.00 sec)
可以發現,該函數並沒有關註時間,而是選擇直接忽略了。
假如交換一下第一個參數和第二個參數的話,就會發現日期的值變成了負數。
MySQL的查詢語句
1.select子句
query字句表
字句名稱 使用目的
select 確定結果集中應該包含哪些列
from 指明所要提取數據的表,以及這些表示如何連接的
where 過濾掉不需要的數據
group by 用於對具有相同列值的行進行分組
having 過濾掉不需要的組
order by 按一個或多個列,對最後結構集中的行進行排序
從最簡單的例子開始:
(1)選擇一個 表中所有的數據
(2)選擇其中的某一列或者多列
如果資料庫限制了只能返回from字句後面各個表所包含的列,就顯得相當乏味了。幸運的是,我們可以在select字句中加上一些“調料”,例如
1.字元,比如數字或字元串
2.表達式,比如transaction.amount*-1
3.調用內建函數,比如round(transaction.amount,2);
4.用戶自定義的函數調用。
(4)展示對於剛纔的Department表,在查詢中添加一些調料,比如使用自定義的列名、字元、表達式、內建函數調用:
(5)調用更多的內建函數
可以看到三個內建函數分別返回不同的值,version代表的是資料庫版本,user代表的是當前登錄的用戶名稱,database代表的是現在正在使用的資料庫的名稱。
現在先在department表中先插入一個同名的公寓,插入語句和插入後結果如下:
(6)去除重覆的行
如果此時只選擇name列的話,會有四個值,但是有兩個Loans重覆的,我需要獨一無二的,重覆值不論出現多少次,我都只取一次,那麼就需要使用到distinct關鍵字了。
註意此處使用的distinct,添加這個關鍵詞對小數據量沒啥影響,但是如果數據量大了之後,性能影響較大。原因是要產生無重覆的結果集需要首先對數據排序,這對於大的結果集來說是相當耗時的。因此不要為了確保去除重覆行而隨意地使用distinct,而是應該先瞭解所使用的數據是否可能包含重覆行,以減少對distinct的不必要的使用。
2.from子句
from子句定義了查詢中所使用的表,以及連接這些表的方式。
當使用術語“表”時,往往想到的是實實在在存在的表格,就像上面的Department表。其實from子句後邊不僅僅可以跟這種實體表(用create table創建),還可以從臨時表(子查詢返回的表)以及虛擬表(使用create view 子句所創建的視圖)中返回數據。
(1)從子查詢返回的表中查詢數據
上圖中會先執行括弧中的select,然後會在記憶體中生成一個虛的表,這個虛的表叫d。然後再執行外層的select,從這個虛的表中選擇相應的dept_id列和name列。
假如這個虛擬表在選擇的時候給一個別名的話,外層也就只能通過這個別名來選擇。比如:
可以看到,內部選擇的時候,給dept_id出了個別名,叫做id,給name出了一個別名,叫做department_name。外層再選擇的時候,就得通過這個新的別名去虛表d中選擇了。
(2)從視圖中返回數據
下麵先定義一個查詢Department表的視圖,在Department表的基礎上多了一列當前操作時候的時間,並將dept_id重命名為id,將name重命名為department_name。
然後從這個視圖返回所有的數據:
可以發現,從視圖選擇數據成功了。
3. where子句
現在假如我有一個員工表,主要有4個欄位,emp_id(員工id)、fname(姓)、lname(名字)、start_date(入職時間)。
讓我們一起解決一些問題:
(1)如何獲得員工id為99號的員工的所有信息?
(2)如何獲得id 大於等於20,小於等於40的員工信息?(請用兩種不同方式分別實現)
(3)如何獲得11,45,99,124號員工的信息?(用兩種方式實現)
(4)如何獲得除了11,45,99,124號員工外,其他員工的信息?(用兩種方式實現)
(5)如何獲得入職時間在2011年10月1日前的,並且姓 ‘李’的所有員工?(用三種方式實現)
(6)如何獲取所有emp_id的末尾為1的所有記錄,比如emp_id為1,11,21,31.。。。101,121,。。。1001,1011,。。。。。(用三種方式來實現)
(7)如何獲取101,111,121,131,141,151,161,171,181,191這幾個員工的記錄?(分別用通配和正則來實現)
上面的這些問題基本涵蓋了where語句中的所有知識點,大家可以先試試看,按照題目的描述和括弧中的條件來實現。
思考後,再查看下麵的答案。
答案:
(1)select * from employee where emp_id = 99;
(2)select * from employee where emp_id between 20 and 40;
select * from employee where emp_id >=20 and emp_id <=40;
(3)select * from employee where emp_id = 11 or emp_id = 45 or emp_id = 99 or emp_id = 124;
select * from employee where emp_id in (11,45,99,124);
(4)select * from employee where emp_id !=11 and emp_id !=45 and emp_id != 99 and emp_id !=124;
select * from employee where emp_id not in (11,45,99,124);
(5)select * from employee where start_date<'2011-10-01' and fname = '李';
select * from (select * from employee where fname = '李' ) d where d.start_date < '2011-10-01';
select * from employee where emp_id in (select emp_id from employee where fname = '李' ) and start_date < '2011-10-01';
(6)select * from employee where emp_id like '%1';
select * from employee where emp_id regexp '.*1$';
select * from employee where right(emp_id,1) = 1;
(7)select * from employee where emp_id like '1_1;'
select * from employee where emp_id regexp '1.1';