1. 程式人生 > >MYSQL 專案中的實際運用(一)

MYSQL 專案中的實際運用(一)

目錄

5、派生表

8、臨時表

1、CAST

CAST強轉函式語法規則是:Cast(欄位名 as 轉換的型別 ),其中型別可以為:CHAR(N) ,DATE ,TIME,DATETIME ,DECIMAL,BINARY,SIGNED,UNSIGNED

一般用法:   select cast(Id aschar(64)) as Id from Building_table

2、select 1

select  1 from table  

作用一:select 1 from mytable;與select anycol(目的表集合中的任意一行) from mytable;與select * from mytable 作用上來說是沒有差別的,都是檢視是否有記錄,一般是作條件用的。select 1 from 中的1是一常量,查到的所有行的值都是它,但從效率上來說,1>anycol>*,因為不用查字典表。

作用二:select id, 'xxxx’   from table  給結果集增加臨時列,每行的列值是寫在select後的數或字元,這條sql語句中是xxxx

3、CASE  WHEN  THEN  ELSE  END

CASE  WHEN  THEN  ELSE  END

注意:其實從case到end的這段語句完全可以看作一個欄位名,後邊可以也必須加AS,給結果集中的這個欄位新增別名,不然欄位名顯示的就是從case到end的這段語句!!!!

注意:其實case語句的本質就是對每行記錄的某些欄位進行比較,然後根據結果,返回一個自定義的新值,最終這些值組成了一個新欄位,而行列轉換也不過是在這基礎上,用了分組聚合!!!!

注意:Case函式只返回第一個符合條件的值,剩下的Case部分將會被自動忽略!!!

--比如說,下面這段SQL,你永遠無法得到“第二類”這個結果 
CASE WHEN col_1 IN ( 'a', 'b') THEN '第一類' 
         WHEN col_1 IN ('a')       THEN '第二類' 
ELSE'其他' END 

用法一 :列舉一個欄位所有可能的值,然後根據這些值衍生出新的值,這些值將作為一個自定義欄位新增到結果集中

SELECT
    NAME '英雄',    
    CASE NAME
        WHEN '德萊文' THEN
            '斧子'
        WHEN '德瑪西亞-蓋倫' THEN
            '大寶劍'
        WHEN '暗夜獵手-VN' THEN
            '弩'
        ELSE
            '無'
    END '裝備'
FROM
    user_info;

這裡寫圖片描述

用法二:判斷欄位範圍,根據判斷結果的不同衍生出不同的值,這些值將作為一個自定義欄位新增到結果集中

-- when 表示式中可以使用 and 連線條件
SELECT
    NAME '英雄',
    age '年齡',
    CASE
        WHEN age < 18 THEN
            '少年'
        WHEN age < 30 THEN
            '青年'
        WHEN age >= 30
        AND age < 50 THEN
            '中年'
        ELSE
            '老年'
    END '狀態'
FROM
    user_info;

這裡寫圖片描述

用法三:使用 case when 配合 聚合函式 實現行轉列,即行資料變列欄位,可以大幅減少結果集的記錄量,更符合非程式設計師使用者的閱讀習慣,但是想要行列轉換,就必須要用聚合函式和分組!!!

舉個例子,平時資料庫想要查學生成績,結果集都是三列N行,姓名,科目,成績,有N個科目就有N行,但是上過學的都知道,平時發的成績條,哪有那麼多行,直接一行搞定,要你是使用者你覺得這兩種方式哪種看著舒服?

例項程式碼和詳細用法都在下邊三個連結裡面:

4、對錶欄位名的操作

select語句中,對錶欄位名的所有操作,其實是對欄位對應的記錄值進行操作,比如+,-,聚合函式,concat拼接函式等

關鍵點:distinct去重關鍵字,直接使用即可,例如SELECT DISTINCT stu_id

關鍵點:+號,在mysql中+號不能作為字串連線符,如果兩個字串用+連線,會自動把兩邊轉化成數字型別再進行相加操作,如果哪一邊字串不能轉為數字,哪一邊就返回0。

5、派生表

派生表和子查詢通常可互換使用。當SELECT語句的FROM子句中使用獨立子查詢時,我們將其稱為派生表。

派生表必須具有別名。

6、巢狀查詢

巢狀查詢
定義:一個內層查詢語句(select-from-where)塊可以巢狀在另外一個外層查詢塊的where子句中,其中外層查詢也稱為父查詢,主查詢。內層查詢也稱子查詢,從查詢。子查詢一般不使用order by子句,只能對最終查詢結果進行排序。

巢狀查詢的工作方式是:先處理內查詢,由內向外處理,外層查詢利用內層查詢的結果巢狀查詢不僅僅可以用於父查詢select語句使用。還可以用於insert、update、delete語句或其他子查詢中。

子查詢的語法規則:子查詢的select查詢總是使用圓括號括起來;任何可以使用表示式的地方都可以使用子查詢,只要它返回的是單個值;如果某個表只出現在子查詢中二不出現在外部查詢中,那麼該表的列就無法包含在輸出中;一般,對於子查詢生成的表都給它起個別名。

任何可以使用表示式的地方都可以使用子查詢(一般用在WHERE後),這句話是重點,可以分為兩種情況:

注意:從本質上來說,這種巢狀查詢就是每行的特定欄位值代入表示式之後,只有表示式結果為true的那行記錄才會被輸出。
一、當子查詢的返回值只有一個時,可以使用比較運算子如=、<、>、>=、<=、!=等

二、如果子查詢的返回值不止一個,而是一個集合時,則不能直接使用比較運算子:(子查詢關鍵字來啦)

any必須與=、>、>=、<、<=、<>結合起來使用,分別表示等於、大於、大於等於、小於、小於等於、不等於其中的任何一個數據。

注意:some是any的別名,用法相同,也就是說知道就行,沒卵用

all必須與=、>、>=、<、<=、<>結合是來使用,分別表示等於、大於、大於等於、小於、小於等於、不等於其中的其中的所有資料。
例如:

select s1 from t1 where s1 > any (select s1 from t2);

假設表t1中有一行包含(10),t2包含(21,14,6),則表示式為true;如果t2包含(20,10),或者表t2為空表,則表示式為false。如果表t2包含(null,null,null),則表示式為unkonwn。

all的意思是“對於子查詢返回的列中的所有值,如果比較結果為true,則返回true”
例如:

select s1 from t1 where s1 > all(select s1 from t2);

假設表t1中有一行包含(10)。如果表t2包含(-5,0,+5),則表示式為true,因為10比t2中的查出的所有三個值大。如果表t2包含(12,6,null,-100),則表示式為false,因為t2中有一個值12大於10。如果表t2包含(0,null,1),則表示式為unknown。如果t2為空表,則結果為true。

in查詢相當於多個or條件的疊加,這個比較好理解,比如下面的兩個等效查詢

select * from user where userId in (1, 2, 3);
select * from user where userId = 1 or userId = 2 or userId = 3;

not in與in相反,例如:

select * from user where userId not in (1, 2, 3);
select * from user where userId != 1 and userId != 2 and userId != 3;

總的來說,in查詢就是先將子查詢條件的記錄全都查出來,假設結果集為B,如果父表字段值在B中,就返回true,且返回其對應的那條記錄!!!!

值得一提的是,in查詢的子條件返回結果必須只有一個欄位,例如:

select * from user where userId in (select id from B);

而不能是

select * from user where userId in (select id, age from B);

exists表示存在,它常常和子查詢配合使用,例如下面的SQL語句

SELECT * FROM `user` 
    WHERE exists (SELECT * FROM `order` WHERE user.id = order.user_id)

exists用於檢查子查詢是否至少會返回一行資料,該子查詢實際上並不返回任何資料,而是返回值TrueFalse

當子查詢返回為真時,則外層查詢語句將進行查詢。
當子查詢返回為假時,外層查詢語句將不進行查詢或者查詢不出任何記錄。

7、while,if

while迴圈

#  while迴圈語法:
# while 條件 DO
#            迴圈體;
# end while;
# */
-- 例項:
create procedure sum1(a int) 
begin
    declare sum int default 0;  -- default 是指定該變數的預設值
    declare i int default 1;
while i<=a DO -- 迴圈開始
    set sum=sum+i;
    set i=i+1;
end while; -- 迴圈結束
select sum;  -- 輸出結果
end

IF ELSE 作為流程控制語句使用

IF search_condition Then
    statement_list
[ELSEIF search_condition Then]
[ELSE
    statemeny_list]
END IF;

最關鍵也是最坑爹的一點,while迴圈和if只能在儲存過程中使用!!!!!

但有一種特殊情況:

如果存在表則刪除表然後建立

drop table if exists address_book

但是也只能這麼寫,不能擴充套件加and什麼的!!!!!

8、臨時表

       臨時表主要用於對大資料量的表上作一個子集,提高查詢效率

 臨時表使用有一些限制條件

  *  不能使用rename來重新命名臨時表。但是可以alter table rename代替:

             mysql>ALTER TABLE orig_name RENAME new_name;

  *  可以複製臨時表得到一個新的臨時表,如:

                mysql>create temporary table new_table select * from old_table;

  *  但在同一個query語句中,相同的臨時表只能出現一次。如:

               可以使用:mysql> select * from temp_tb;

               但不能使用:mysql> select * from temp_tb, temp_tb as t;

               錯誤資訊:   ERROR 1137 (HY000): Can't reopen table: 'temp_tb'

        同樣相同臨時表不能在儲存函式中出現多次,如果在一個儲存函式裡,用不同的別名查詢一個臨時表多次,或者在這個儲存函式裡用不同的語句查詢,都會出現這個錯誤。

既然子查詢中不能再次開啟臨時表,那麼就使用其他臨時表 先把子查詢的資料存起來,然後再處理。

  *  但不同的臨時表可以出現在同一個query語句中,如臨時表temp_tb1, temp_tb2:

                 Mysql> select * from temp_tb1, temp_tb2;

        臨時表可以手動刪除:

                 DROP TEMPORARY TABLE IF EXISTS temp_tb;

9、讀寫操作的影響行數

讀操作的影響行數:select fount_rows();
寫操作的影響行數:select row_count();

但切記:只對一次操作有效!!也就是隻返回最後一次操作的影響的行數的值.

10、NULL相關函式

第一步,is NULL要比ISNULL()的比較

SELECT * from 表名 where 欄位名 is NULL

SELECT * from 表名 where ISNULL(欄位名)

由上面可以看出,is NULL要比ISNULL()快一點。

第二步,is NULL和IFNULL()的比較

SELECT * from 表名 where 欄位名 is NULL

SELECT * from 表名 where IFNULL(欄位名,'0') = '0';

由上面可以看出,可看出IFNULL()要比is NULL快一點。

綜上所述,查詢空值的執行速度基本上為IFNULL()>is NULL>ISNULL()。

重點:

IFNULL(expr1,expr2)的用法:

假如expr1 不為 NULL,則 IFNULL() 的返回值為 expr1;

否則其返回值為 expr2。IFNULL()的返回值是數字或是字串,具體情況取決於其所使用的語境。

1

2

3

4

5

6

7

8

9

mysql> SELECT IFNULL(1,0);

-> 1

mysql> SELECT IFNULL(NULL,10);

-> 10

mysql> SELECT IFNULL(1/0,10);

-> 10

mysql> SELECT

IFNULL(1/0,'yes');

-> 'yes'

NULLIF(expr1,expr2) 的用法:

如果expr1 = expr2 成立,那麼返回值為NULL,否則返回值為 expr1。這和CASE WHEN expr1 = expr2 
THEN NULL ELSE expr1 END相同。

1

2

3

4

5

mysql> SELECT

NULLIF(1,1);

-> NULL

mysql> SELECT NULLIF(1,2);

-> 1 

IF(exPR1,expr2,expr3) 的用法:
如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),則 IF()的返回值為expr2; 否則返回值則為 expr3。IF() 的返回值為數字值或字串值,具體情況視其所在語境而定。

 SELECT IF(1>2,2,3);

11、分組聚合

分組一般和聚合一塊出現!!!!!

分組,說白就是找相同,根據欄位值(欄位組),相同就是一組

分組聚合,在已經分好組的前提上,對每組進行操作,返回對每組操作的結果,也就是一組只有一個結果。比如,如果想知道每組裡有多少條記錄,可以用count(1)

分組查詢,如果查詢的欄位名和group by 的欄位名是一樣的,輸出結果集就是不同的各個組名(欄位名),這很好理解;但如果查詢的不光是group by的欄位名,那結果集是每組查到的第一條記錄,注意是一條,如果你想看每個分組的所有資料,建議你用order by和where。

分組排序:是先排序後分組,造成的結果是,如果查詢的不光是group by的欄位名,那結果集會因為順序不同而變化,當然,也只是每個分組裡的一條不同記錄罷了。

12、時間戳

mysql時間戳

獲得當前日期+時間(date + time)函式:now()

13、變數賦值

在MySQL儲存過程中使用SELECT …INTO語句為變數賦值:

  用來將查詢返回的一行的各個列值儲存到區域性變數中。

要求:

  查詢的結果集中只能有1行。

SELECT col_name[,...] INTO var_name[,...] table_expr

使用SELECT …INTO語句在資料庫中進行查詢,並將得到的結果賦值給變數。

  ①col_name:要從資料庫中查詢的列欄位名;

  ②var_name:變數名,列欄位名按照在列清單和變數清單中的位置對應,將查詢得到的值賦給對應位置的變數;

  ③table_expr:SELECT語句中的其餘部分,包括可選的FROM子句和WHERE子句。

14、備份表

MySQL不支援Select Into語句直接備份表結構和資料

錯誤方法: 
MYSQL不支援: 
Select * Into new_table_name from old_table_name; 這是sql server中的用法
替代方法: 
Create table new_table_name (Select * from old_table_name);

15、DATE函式

DATE_ADD() 函式向日期新增指定的時間間隔。

語法

DATE_ADD(date,INTERVAL expr type)

date 引數是合法的日期表示式。expr 引數是您希望新增的時間間隔。

type 引數可以是下列值DAY,HOUR,等等一堆

例項

假設我們有如下的表:

OrderId ProductName OrderDate
1 'Computer' 2008-12-29 16:25:46.635

現在,我們希望向 "OrderDate" 新增 2 天,這樣就可以找到付款日期。

我們使用下面的 SELECT 語句:

SELECT OrderId,DATE_ADD(OrderDate,INTERVAL 2 DAY) AS OrderPayDate
FROM Orders

結果:

OrderId OrderPayDate
1 2008-12-31 16:25:46.635