第一篇 數據庫MySql

數據庫的簡介

 數據庫:存儲數據的倉庫python

數據庫管理系統軟件

常見的數據庫管理軟件:甲骨文的oracle,IBM的db2,sql server, Access,Mysql(開源,免費,跨平臺). mysql

關係型數據庫:存在磁盤上linux

非關係型數據庫:存在內存上正則表達式

數據庫系統

數據庫系統DBS(Data Base System,簡稱DBS)一般由軟件、數據庫和數據管理員組成。其軟件主要包括操做系統、各類宿主語言、實用程序以及數據庫管理系統。數據庫由數據庫管理系通通一管理,數據的插入、修改和檢索均要經過數據庫管理系統進行。數據管理員負責建立、監控和維護整個數據庫,使數據能被任何有權使用的人有效使用。sql

                        

 

mysql

一.安裝

linux版本:數據庫

1. 安裝
yum install mysql-server

2. 服務端啓動npm

mysql.server start

3. 客戶端鏈接windows

鏈接:
    mysql -h host -u user -p
 
    常見錯誤:
        ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2), it means that the MySQL server daemon (Unix) or service (Windows) is not running.
退出:
    QUIT 或者 Control+D

win版本:性能優化

1. 下載zip包服務器

http://dev.mysql.com/downloads/mysql/ 
2. 解壓
直接解壓到某個目錄下,如:E:\mysql-8.0.12-winx64

三、初始化

MySQL解壓後的 bin 目錄下有一大堆的可執行文件,初始化針對的是服務端mysqld

執行以下命令初始化數據:

C:\Users\mamingchen>E:

E:\>cd E:\mysql-8.0.12-winx64\bin

E:\mysql-8.0.12-winx64\bin>mysqld --initialize-insecure

E:\mysql-8.0.12-winx64\bin>

初始化完成後:
1. 目錄下面生成一個data文件夾
2. 建立用戶名:root ,密碼爲空

四、啓動MySQL服務

# 進入可執行文件目錄
cd E:\mysql-8.0.12-winx64\bin
 
# 執行下面的命令啓動MySQL服務
mysqld

就啓動了服務,等待客戶端去鏈接

五、啓動MySQL客戶端並鏈接MySQL服務

因爲初始化時使用的【mysqld --initialize-insecure】命令,其默認未給root帳戶設置密碼

# 因此,另行開個cmd,進入可執行文件目錄

cd E:\mysql
-5.7.16-winx64\bin # 鏈接MySQL服務器 mysql -u root -p # 提示請輸入密碼,直接回車,由於初始化的時候尚未設置密碼
以下:

到此爲止,MySQL服務端已經安裝成功而且客戶端已經能夠鏈接上,之後再操做MySQL時,只須要重複上述四、5步驟便可。可是,在四、5步驟中重複的進入可執行文件目錄比較繁瑣,如想往後操做簡便,能夠作以下操做。

a. 添加環境變量

將MySQL可執行文件添加到環境變量中,從而執行執行命令便可
【右鍵計算機】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變量】--》【在第二個內容框中找到 變量名爲Path 的一行,雙擊】 --> 【將MySQL的bin目錄路徑追加到變值值中,用 ; 分割】

如:
C:\Python\Python36-32\Scripts;C:\Python\Python36-32\;"C:\Users\mamingchen\AppData\Local\Microsoft\WindowsApps;C:\Program Files (x86)\Java\jre1.8.0_151\bin;C:\Program Files (x86)\Java\jre1.8.0_151\jre\bin";E:\Users\mamingchen\AppData\Local\Programs\Fiddler;"%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin";C:\Users\mamingchen\AppData\Roaming\npm;C:\Python\Python36-32\python.exe;E:\MongoDB\Server\4.0\bin;E:\mysql-8.0.12-winx64\bin;
如此一來,之後再啓動服務並鏈接時,僅需:
# 啓動MySQL服務,在終端輸入
C:\Users\mamingchen>mysqld
 
# 鏈接MySQL服務,在終端輸入:
C:\Users\mamingchen>mysql -u root -p
b. 將MySQL服務製做成windows服務

上一步解決了一些問題,但不夠完全,由於在執行【mysqd】啓動MySQL服務器時,當前終端會被hang住,那麼作一下設置便可解決此問題:
記住:以管理員身份運行cmd
# 製做MySQL的Windows服務,在終端執行此命令:
C:\Users\mamingchen>"E:\mysql-8.0.12-winx64\bin\mysqld" --install

# 移除MySQL的Windows服務,在終端執行此命令:
C:\Users\mamingchen>"E:\mysql-8.0.12-winx64\bin\mysqld" --remove

註冊成服務以後,之後再啓動和關閉MySQL服務時,僅需執行以下命令:

# 啓動MySQL服務
net start mysql
# 關閉MySQL服務 net stop mysql

記住:
若是是zip包,能夠本身製做Windows服務;
若是是可執行文件直接點擊安裝的, 系統會本身給你安裝Windows服務的

這裏插入一個如何刪除Windows服務

1. 運行
services.msc

2. 找到要刪除的服務 -- 屬性-- 服務名稱 

3. 複製服務名稱

4. 以管理員身份啓動cmd

5. 執行下面的命令
sc delete 服務名稱

[SC] DeleteService 成功

 二.建立用戶

1. mysql

2. mysql -uroot -p

3. show databases; -- 看有哪些表

4. use mysql;  -- 進入mysql表

5. use user;

6.  -- 建立用戶和密碼
1create user 'mmc'@'ip地址' identified by 'mmc123'; 

--解析:
1) 'mmc':表示登錄數據庫的用戶名
2) @'ip地址'
    ip地址有一下規則:
-- 表示這個用戶只能在ip爲192.168.1.1的機器上用
a.create user 'mmc'@'192.168.1.1' identified by 'mmc123'; 

-- 表示只要ip前綴爲192.168.1.的均可以使用
b.create user 'mmc'@'192.168.1.%' identified by 'mmc123'; 

-- 表示只要ip前綴爲 192.168的均可以使用
c.create user 'mmc'@'192.168.%.%' identified by 'mmc123'; 

-- 表示全部IP均可以使用
d.create user 'mmc'@'%' identified by 'mmc123'; 

三. 受權

1. 授予什麼權限給誰
-- 將db1庫下面的t1表的 查詢,插入,更新的權限授予 mmc
-- 下面的意思就是mmc用戶在全部機器上都能對db1庫下面的t1表進行查詢,插入和更新操做
grant select,insert,update on db1.t1 to 'mmc'@'%';

-- 給mmc全部權限,除了grant以外
grant all privileges on db1.t1 to 'mmc'@'%';

-- 表示mmc只能看db1庫下面的全部表
grant all privileges on db1.*  to 'mmc'@'%';

四.用戶管理

建立用戶
    create user '用戶名'@'IP地址' identified by '密碼';
刪除用戶
    drop user '用戶名'@'IP地址';
修改用戶
    rename user '用戶名'@'IP地址'; to '新用戶名'@'IP地址';;
修改密碼
    set password for '用戶名'@'IP地址' = Password('新密碼')
  
PS:用戶權限相關數據保存在mysql數據庫的user表中,因此也能夠直接對其進行操做(不建議)

五.受權管理

show grants for '用戶'@'IP地址'                  -- 查看權限
grant  權限 on 數據庫.表 to   '用戶'@'IP地址'      -- 受權
revoke 權限 on 數據庫.表 from '用戶'@'IP地址'      -- 取消權限
all privileges          除grant外的全部權限
select                  僅查權限
select,insert           查和插入權限
...
usage                   無訪問權限
alter                   使用alter table
alter routine           使用alter procedure和drop procedure
create                  使用create table
create routine          使用create procedure
create temporary tables 使用create temporary tables
create user             使用create userdrop user、rename user和revoke  all privileges
create view             使用create view
delete                  使用delete
drop                    使用drop table
execute                 使用call和存儲過程
file                    使用select into outfile 和 load data infile
grant option            使用grant 和 revoke
index                   使用index
insert                  使用insert
lock tables             使用lock table
process                 使用show full processlist
select                  使用select
show databases          使用show databases
show view               使用show view
update                  使用update
reload                  使用flush
shutdown                使用mysqladmin shutdown(關閉MySQL)
super                   􏱂􏰈使用change master、kill、logs、purge、master和set global。還容許mysqladmin􏵗􏵘􏲊􏲋調試登錄
replication client      服務器位置的訪問
replication slave       由複製從屬使用
對於目標數據庫以及內部其餘:
            數據庫名.*              數據庫中的全部
            數據庫名.表             指定數據庫中的某張表
            數據庫名.存儲過程     指定數據庫中的存儲過程
            *.*                        全部數據庫
用戶名@IP地址         用戶只能在改IP下才能訪問
用戶名@192.168.1.%   用戶只能在改IP段下才能訪問(通配符%表示任意)
用戶名@%             用戶能夠再任意IP下訪問(默認IP地址爲%)
grant all privileges on db1.tb1 TO '用戶名'@'IP'

grant select on db1.* TO '用戶名'@'IP'

grant select,insert on *.* TO '用戶名'@'IP'

revoke select on db1.tb1 from '用戶名'@'IP'
示例

特殊的:

flush privileges,將數據讀取到內存中,從而當即生效。
# 啓動免受權服務端
mysqld --skip-grant-tables

# 客戶端
mysql -u root -p

# 修改用戶名密碼
update mysql.user set authentication_string=password('666') where user='root';
flush privileges;

忘記密碼
忘記密碼

 

啓動

service mysqld start  #開啓
chkconfig mysqld on   #設置開機自啓

OR

systemctl start mariadb
systemctl enable mariadb

查看

-- ps aux |grep mysqld    #查看進程
-- netstat -an |grep 3306 #查看端口

設置密碼

-- mysqladmin -uroot password '123'   #設置初始密碼,初始密碼爲空所以-p選項沒有用
-- mysqladmin -u root -p123 password '1234' #修改root用戶密碼

登陸

-- mysql               #本地登陸,默認用戶root,空密碼,用戶爲root@127.0.0.1
-- mysql -uroot -p1234 #本地登陸,指定用戶名和密碼,用戶爲root@127.0.0.1
-- mysql -uroot -p1234 -h 192.168.31.95 #遠程登陸,用戶爲root@192.168.31.95

mysql的經常使用命令

-- 
-- 啓動mysql服務與中止mysql服務命令:
-- 
-- net start mysql
-- net stop  mysql
-- 
-- 
-- 登錄與退出命令:
-- 
--    mysql -h 服務器IP -P 端口號 -u  用戶名 -p 密碼 --prompt 命令提示符  --delimiter 指定分隔符
--    mysql -h 127.0.0.1 -P 3306 -uroot -p123
--    quit------exit----\q;
-- 
-- 
-- \s;   ------my.ini文件:[mysql] default-character-set=gbk [mysqld] character-set-server=gbk
-- 
-- prompt 命令提示符(\D:當前日期 \d:當前數據庫  \u:當前用戶)
-- 
-- \T(開始日誌) \t(結束日誌)
-- 
-- show warnings;
-- 
-- help() ? \h
-- 
-- \G;
-- 
-- select now();
-- select version();
-- select user;
-- 
-- \c 取消命令
-- 
-- delimiter 指定分隔符

忘記密碼怎麼辦?

方法1:啓動mysql時,跳過受權表

[root@controller ~]# service mysqld stop
[root@controller ~]# mysqld_safe --skip-grant-table &
[root@controller ~]# mysql
mysql> select user,host,password from mysql.user;
+----------+-----------------------+-------------------------------------------+
| user     | host                  | password                                  |
+----------+-----------------------+-------------------------------------------+
| root     | localhost             | *A4B6157319038724E3560894F7F932C8886EBFCF |
| root     | localhost.localdomain |                                           |
| root     | 127.0.0.1             |                                           |
| root     | ::1                   |                                           |
|          | localhost             |                                           |
|          | localhost.localdomain |                                           |
| root     | %                     | *23AE809DDACAF96AF0FD78ED04B6A265E05AA257 |
+----------+-----------------------+-------------------------------------------+
mysql> update mysql.user set password=password("123") where user="root" and host="localhost";
mysql> flush privileges;
mysql> exit
[root@controller ~]# service mysqld restart
[root@controller ~]# mysql -uroot -p123

方法2(刪庫):

刪除與權限相關的庫mysql,全部的受權信息都丟失,主要用於測試數據庫或者剛剛建庫不久沒有受權數據的狀況(從刪庫到跑路)
[root@controller ~]# rm -rf /var/lib/mysql/mysql
[root@controller ~]# service mysqld restart
[root@controller ~]# mysql

 

sql及其規範

sql是Structured Query Language(結構化查詢語言)的縮寫。SQL是專爲數據庫而創建的操做命令集,是一種功能齊全的數據庫語言。

在使用它時,只須要發出「作什麼」的命令,「怎麼作」是不用使用者考慮的。SQL功能強大、簡單易學、使用方便,已經成爲了數據庫操做的基礎,而且如今幾乎全部的數據庫均支持sql。

<1> 在數據庫系統中,SQL語句不區分大小寫(建議用大寫) 。但字符串常量區分大小寫。建議命令大寫,表名庫名小寫;

<2> SQL語句可單行或多行書寫,以「;」結尾。關鍵詞不能跨多行或簡寫。

<3> 用空格和縮進來提升語句的可讀性。子句一般位於獨立行,便於編輯,提升可讀性。

SELECT * FROM tb_table
            WHERE NAME="YUAN";

<4> 註釋:單行註釋:--

               多行註釋:/*......*/

<5>sql語句能夠折行操做

<6> DDL,DML和DCL,三部分共同構成了sql語句

  DDL:定義語言;

  DML:操做語言,如:增刪改查

  DCL:控制語言;如:權限控制

-- -- DML(data manipulation language):
--    它們是SELECT、UPDATE、INSERT、DELETE,就象它的名字同樣,這4條命令是用來對數據庫裏的
--    數據進行操做的語言
-- 
-- -- DDL(data definition language):
--    DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定義或改變表(TABLE)的結構,數據類型,表之間的連接和約束等初始化工做上,
    他們大多在創建表時使用
-- -- -- DCL(Data Control Language): -- 是數據庫控制功能。是用來設置或更改數據庫用戶或角色權限的語句,包括(grant,deny,revoke等) -- 語句。在默認狀態下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人員纔有權力執行DCL

 

數據庫操做(DDL)

-- 1.建立數據庫(在磁盤上建立一個對應的文件夾)
    create database [if not exists] db_name [character set xxx] 
    
-- 2.查看數據庫
    show databases;查看全部數據庫
    show create database db_name; 查看某個數據庫的建立方式

-- 3.修改數據庫
    alter database db_name [character set 編碼格式] 

-- 4.刪除數據庫
    drop database [if exists] db_name;
    
-- 5.使用數據庫
    切換數據庫 use db_name; -- 注意:進入到某個數據庫後沒辦法再退回以前狀態,但能夠經過use進行切換
    查看當前使用的數據庫 select database();

-- 6. 查看錯誤信息
  show warnings;

mysql數據類型

MySQL支持多種類型,大體能夠分爲三類:數值、日期/時間和字符串(字符)類型。

數值類型

下面的表顯示了須要的每一個整數類型的存儲和範圍。

 

日期和時間類型

表示時間值的日期和時間類型爲DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每一個時間類型有一個有效值範圍和一個"零"值,當指定不合法的MySQL不能表示的值時使用"零"值。

 

字符串類型

字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。該節描述了這些類型如何工做以及如何在查詢中使用這些類型。

 

CHAR和VARCHAR類型相似,但它們保存和檢索的方式不一樣。它們的最大長度和是否尾部空格被保留等方面也不一樣。在存儲或檢索過程當中不進行大小寫轉換。

BINARY和VARBINARY類相似於CHAR和VARCHAR,不一樣的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。

BLOB是一個二進制大對象,能夠容納可變數量的數據。有4種BLOB類型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它們只是可容納值的最大長度不一樣。

有4種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。這些對應4種BLOB類型,有相同的最大長度和存儲需求。

 

數據表操做(對錶字段的操做)

基礎操做

-- 1.建立表(相似於一個excel表)

        create table table_name(
            field1 type[完整性約束條件],
            field2 type,
            ...
            fieldn type
        )[character set xxx];

         -- 示例:建立一個員工表employee

         create table employee(
            id int primary key auto_increment ,
            name varchar(20),
            gender bit default 1,   -- gender char(1)  default 1   -----    或者 TINYINT(1) 
            birthday date,
            entry_date date,
            job varchar(20),
            salary double(4,2) unsigned,
            resume text    -- 注意,這裏做爲最後一個字段不加逗號
          );


    /* 約束:
       primary key (非空且惟一)  :可以惟一區分出當前記錄的字段稱爲主鍵!
       unique
       not null
       auto_increment 主鍵字段必須是數字類型。
       外鍵約束 foreign key  */

-- 2.查看錶信息
    desc tab_name 查看錶結構
    show columns from tab_name  查看錶結構
    show tables 查看當前數據庫中的全部的表
    show create table tab_name    查看當前數據庫表建表語句 

-- 3.修改表結構
   -- (1)增長列(字段)
      alter table tab_name add [column] 列名 類型[完整性約束條件][first|after 字段名];
      alter table user add addr varchar(20) not null unique first/after username;
      #添加多個字段
      alter table users2 
            add addr varchar(20),
            add age  int first,
            add birth varchar(20) after name;

   -- (2)修改一列類型
      alter table tab_name modify 列名 類型 [完整性約束條件][first|after 字段名];
      alter table users2 modify age tinyint default 20;
      alter table users2 modify age int  after id;
   
   -- (3)修改列名
      alter table tab_name change [column] 列名 新列名 類型 [完整性約束條件][first|after 字段名];
      alter table users2 change age Age int default 28 first;

   -- (4)刪除一列
      alter table tab_name drop [column] 列名;
      -- 思考:刪除多列呢?刪一個填一個呢?
      alter table users2 
            add salary float(6,2) unsigned not null after name,
            drop addr;    

   -- (5)修改表名
      rename table 表名 to 新表名;
   -- (6)修該表所用的字符集    
      alter table student character set utf8;

-- 4.刪除表
    drop table tab_name;

---5 添加主鍵,刪除主鍵
    alter table tab_name add primary key(字段名稱,...) 
    alter table users drop primary key;

    eg:
    mysql> create table test5(num int auto_increment);
    ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
    create table test(num int primary key auto_increment);
    -- 思考,如何刪除主鍵?
    alter table test modify id int;   -- auto_increment沒了,但這樣寫主鍵依然存在,因此還要加上下面這句
    alter table test drop primary key;-- 僅僅用這句也沒法直接刪除主鍵

-- 惟一索引
    alter table tab_name add unique [index|key] [索引名稱](字段名稱,...) 

    alter table users add unique(name)-- 索引值默認爲字段名show create table users;
    alter table users add unique key user_name(name);-- 索引值爲user_name

    -- 添加聯合索引
    alter table users add unique index name_age(name,age);#show create table users;

    -- 刪除惟一索引
    alter table tab_name drop {index|key} index_name

建立文章表

create table article(
            id int primary key auto_increment ,
            title varchar(20),
            publish_date INT,
            click_num INT,
            is_top TINYINT(1),
            content TEXT
          );
示例

完整性約束條件之主鍵約束

單字段主鍵

主鍵字段特色:非空(not null)且惟一(unique)

 create table users(
            id INT primary key,
            name varchar(20),
            city varchar(20)
          );

多字段聯合主鍵

 create table users2(
            id INT,
            name varchar(20),
            city varchar(20),
            primary key(name,id)
          );

<1> 一張表只能有一個主鍵

<2> 主鍵類型不必定非是整型

表紀錄操做(具體表裏數據的操做)

表紀錄之增,刪,改

-- 1.增長一條記錄insert

      /*insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......);*/


      create table employee_new(
                 id int primary key auto_increment,
                 name varchar(20) not null unique,
                 birthday varchar(20),
                 salary float(7,2)
                             );

       insert into employee_new (id,name,birthday,salary) values
                     (1,'yuan','1990-09-09',9000);

    -- 不寫字段,按找字段一一對應插入
insert into employee_new values (2,'alex','1989-08-08',3000);
    
    -- 按照字段插入
insert into employee_new (name,salary) values ('xialv',1000); -- 插入多條數據 insert into employee_new values (4,'alvin1','1993-04-20',3000), (5,'alvin2','1995-05-12',5000); -- set插入: 以鍵值對方式插入
    insert [into] tab_name set 字段名=值
insert into employee_new set id=12,name="alvin3"; -- 2.修改表記錄 update tab_name set field1=value1,field2=value2,......[where 語句] /* UPDATE語法能夠用新值更新原有錶行中的各列。 SET子句指示要修改哪些列和要給予哪些值。 WHERE子句指定應更新哪些行。如沒有WHERE子句,則更新全部的行。*/ update employee_new set birthday="1989-10-24" WHERE id=1; --- 將yuan的薪水在原有基礎上增長1000元。 update employee_new set salary=salary+4000 where name='yuan'; -- 3.刪除表紀錄 delete from tab_name [where ....] /* 若是不跟where語句則刪除整張表中的數據 1) delete只能用來刪除一行記錄 2) delete語句只能刪除表中的內容,不能刪除表自己,想要刪除表,用drop 3) TRUNCATE TABLE也能夠刪除表中的全部數據,此語句首先摧毀表,再從新建立要給同名的新表。此種方式刪除的數據不能在事務中恢復。
          truncate 使用場景:好比某表有幾萬條數據,delete刪除太慢,就用truncate,直接把這張表先刪掉,而後再從新建立個同名表。
*/ -- 刪除表中名稱爲’alex’的記錄。 delete from employee_new where name='alex'; -- 刪除表中全部記錄。 delete from employee_new;-- 注意auto_increment沒有被重置:alter table employee auto_increment=1; -- 使用truncate刪除表中記錄。 truncate table emp_new;

思考:

    <1>  存儲時間用varchar可不能夠呢?它與date數據類型又有什麼區別呢?

   -- 能夠的(若是隻是用來顯示,不對時間進行操做的時候就能夠用varchar)

    <2>  表中數據三條,id分別爲1,2,3,忽然插入一個id=7,那麼下次做爲主鍵的字增加的id會從幾開始增加呢?(從7開始)

 

表紀錄之查(單表查詢)

-- 查詢表達式

   SELECT *|field1,filed2 ...   FROM tab_name
                  WHERE 條件
                  GROUP BY field
                  HAVING 篩選
                  ORDER BY field
                  LIMIT 限制條數


 ---準備表

   CREATE TABLE ExamResult(

   id INT PRIMARY KEY  auto_increment,
   name VARCHAR (20),
   JS DOUBLE ,
   Django DOUBLE ,
   OpenStack DOUBLE
);


INSERT INTO ExamResult VALUES  (1,"yuan",98,98,98),
                               (2,"xialv",35,98,67),
                               (3,"alex",59,59,62),
                               (4,"wusir",88,89,82),
                               (5,"alvin",88,98,67),
                               (6,"yuan",86,100,55);


-- (1)select [distinct] *|field1,field2,......   from tab_name
            -- 其中from指定從哪張表篩選,*表示查找全部列,也能夠指定一個列
            -- 代表確指定要查找的列,distinct用來剔除重複行。

                    -- 查詢表中全部學生的信息。
                    select * from ExamResult;
                    -- 查詢表中全部學生的姓名和對應的英語成績。
                    select name,JS from ExamResult;
                    -- 過濾表中重複數據。distinct後面跟要去重的字段
                    select distinct JS ,name from ExamResult;



-- (2)select 也可使用表達式,而且可使用: 字段 as 別名或者:字段 別名

                -- 在全部學生分數上加10分特長分顯示。

                select name,JS+10,Django+10,OpenStack+10 from ExamResult;  -- 僅僅是當次顯示的時候加了分數,數據庫裏可沒存上哦。
-- 統計每一個學生的總分。 select name,JS+Django+OpenStack from ExamResult; -- 使用別名表示學生總分。 select name as 姓名,JS+Django+OpenStack as 總成績 from ExamResult; select name,JS+Django+OpenStack 總成績 from ExamResult; -- as 能夠去掉,可是要取別名,推薦加上 select name JS from ExamResult; -- what will happen?---->記得加逗號 -- (3)使用where子句,進行過濾查詢。 -- 查詢姓名爲XXX的學生成績 select * from ExamResult where name='yuan'; -- 查詢英語成績大於90分的同窗 select id,name,JS from ExamResult where JS>90; -- 查詢總分大於200分的全部同窗 select name,JS+Django+OpenStack as 總成績 from ExamResult where JS+Django+OpenStack>200 ; -- where字句中可使用: -- 比較運算符: > < >= <= <> != (<> 和 != 都表示不等於,推薦用 !=) between 80 and 100 值在10到20之間 in(80,90,100) 值是10或20或30 like 'yuan%' /* pattern能夠是%或者_, 若是是%則表示任意多字符,此例如唐僧,唐國強 若是是_則表示一個字符唐_,只有唐僧符合。兩個_則表示兩個字符:__ */ -- 邏輯運算符 在多個條件直接可使用邏輯運算符 and or not -- 練習 -- 查詢JS分數在 70-100之間的同窗。 select name ,JS from ExamResult where JS between 80 and 100; -- 查詢Django分數爲75,76,77的同窗。 select name ,Django from ExamResult where Django in (75,98,77); -- 查詢全部姓王的學生成績。 select * from ExamResult where name like '王%'; -- 查詢JS分>90,Django分>90的同窗。 select id,name from ExamResult where JS>90 and Django >90; -- 查找缺考數學的學生的姓名 select name from ExamResult where Database is null; -- (4)Order by 指定排序的列,排序的列便可是表中的列名,也能夠是select 語句後指定的別名。 -- select *|field1,field2... from tab_name order by field [Asc|Desc] -- Asc 升序、Desc 降序,其中asc爲默認值 ORDER BY 子句應位於SELECT語句的結尾。 -- 練習: -- 對JS成績排序後輸出。 select * from ExamResult order by JS; -- 對總分排序按從高到低的順序輸出 select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)) 總成績 from ExamResult order by 總成績 desc;
        select name, JS+Django+Database as 總成績 from examresult order by 總成績 desc; -- 按總成績從高到低排序
-- 對姓李的學生成績排序輸出
        -- ifnull(參數一,0):表示若是參數一的字段值爲null,就轉換成0
select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0)) 總成績 from ExamResult where name like 'a%' order by 總成績 desc; -- (5)group by 分組查詢--用的最多,最重要,也是最很差理解的一個:

CREATE TABLE order_menu( id INT PRIMARY KEY auto_increment, product_name VARCHAR (20), price FLOAT(6,2), born_date DATE, class VARCHAR (20) ); INSERT INTO order_menu (product_name,price,born_date,class) VALUES ("蘋果",20,20170612,"水果"), ("香蕉",80,20170602,"水果"), ("水壺",120,20170612,"電器"), ("被罩",70,20170612,"牀上用品"), ("音響",420,20170612,"電器"), ("牀單",55,20170612,"牀上用品"), ("草莓",34,20170612,"水果"); -- 注意,按分組條件分組後每一組只會顯示第一條記錄 -- group by字句,其後能夠接多個列名,也能夠跟having子句,對group by 的結果進行篩選。 -- 按位置字段篩選 select * from order_menu group by 5; -- 按照第5個字段分組 -- 練習:對購物表按類名分組後顯示每一組商品的價格總和 select class,SUM(price)from order_menu group by class; -- 練習:對購物表按類名分組後顯示每一組商品價格總和超過150的商品 select class,SUM(price)from order_menu group by class HAVING SUM(price)>150; /* having 和 where二者均可以對查詢結果進行進一步的過濾,差異有: <1>where語句只能用在分組以前的篩選,having能夠用在分組以後的篩選; <2>使用where語句的地方均可以用having進行替換 <3>having中能夠用聚合函數,where中就不行。 */ -- GROUP_CONCAT() 函數 SELECT id,GROUP_CONCAT(name),GROUP_CONCAT(JS) from ExamResult GROUP BY id; -- (6)聚合函數: 先不要管聚合函數要幹嗎,先把要求的內容查出來再包上聚合函數便可。 -- (通常和分組查詢配合使用) --<1> 統計表中全部記錄 -- COUNT(列名):統計行的個數 -- 統計一個班級共有多少學生?先查出全部的學生,再用count包上 select count(*) from ExamResult; -- 統計JS成績大於70的學生有多少個? select count(JS) from ExamResult where JS>70; -- 統計總分大於280的人數有多少? select count(name) from ExamResult where (ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))>280; -- 注意:count(*)統計全部行; count(字段)不統計null值. -- SUM(列名):統計知足條件的行的內容和 -- 統計一個班級JS總成績?先查出全部的JS成績,再用sum包上 select JS as JS總成績 from ExamResult; select sum(JS) as JS總成績 from ExamResult; -- 統計一個班級各科分別的總成績 select sum(JS) as JS總成績, sum(Django) as Django總成績, sum(OpenStack) as OpenStack from ExamResult; -- 統計一個班級各科的成績總和 select sum(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)) as 總成績 from ExamResult; -- 統計一個班級JS成績平均分 select sum(JS)/count(*) from ExamResult ; -- 注意:sum僅對數值起做用,不然會報錯。 -- AVG(列名): -- 求一個班級JS平均分?先查出全部的JS分,而後用avg包上。 select avg(ifnull(JS,0)) from ExamResult; -- 求一個班級總分平均分 select avg((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))) from ExamResult ; -- Max、Min -- 求班級最高分和最低分(數值範圍在統計中特別有用) select Max((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))) 最高分 from ExamResult; select Min((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))) 最低分 from ExamResult; -- 求購物表中單價最高的商品名稱及價格 ---SELECT id, MAX(price) FROM order_menu;--id和最高價商品是一個商品嗎? SELECT MAX(price) FROM order_menu; -- 注意:null 和全部的數計算都是null,因此須要用ifnull將null轉換爲0! -- -----ifnull(JS,0) -- with rollup的使用 --<2> 統計分組後的組記錄 -- (7) 重點:Select from where group by having order by -- Mysql在執行sql語句時的執行順序: -- from where select group by having order by -- 分析: select JS as JS成績 from ExamResult where JS成績 >70; ---- 不成功 select JS as JS成績 from ExamResult having JS成績 >90; --- 成功 -- (8) limit SELECT * from ExamResult limit 1; -- 只顯示查到的前3條數據 SELECT * from ExamResult limit 2,5;--跳過前兩條顯示接下來的五條紀錄 SELECT * from ExamResult limit 2,2; --- (9) 使用正則表達式查詢 SELECT * FROM employee WHERE emp_name REGEXP '^yu'; SELECT * FROM employee WHERE emp_name REGEXP 'yun$'; SELECT * FROM employee WHERE emp_name REGEXP 'm{2}'; -- 有2個m的名字

外鍵約束

建立外鍵

---  每個班主任會對應多個學生 , 而每一個學生只能對應一個班主任

----主表

CREATE TABLE ClassCharger(

       id TINYINT PRIMARY KEY auto_increment,
       name VARCHAR (20),
       age INT ,
       is_marriged boolean  -- show create table ClassCharger: tinyint(1)

);

INSERT INTO ClassCharger (name,age,is_marriged) VALUES ("冰冰",12,0),
                                                       ("丹丹",14,0),
                                                       ("歪歪",22,0),
                                                       ("姍姍",20,0),
                                                       ("小雨",21,0);


----子表: 有foreign key的就是字表

CREATE TABLE Student(

       id INT PRIMARY KEY auto_increment,
       name VARCHAR (20),
       charger_id TINYINT,     --切記:做爲外鍵必定要和關聯主鍵的數據類型保持一致
       -- [ADD CONSTRAINT charger_fk_stu]FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)

) ENGINE=INNODB;
--
charger_fk_stu 外鍵名字
 
示例:關聯外鍵
create table student2(
id int primary key auto_increment,
name varchar (20),
charger_id tinyint,
  -- student2表裏的charger_id 字段的外鍵是classcharger表裏的id字段
  -- 要對student2表裏charger_id字段綁定外鍵,於 classcharger 表裏的id字段相關聯
foreign key (charger_id) references classcharger(id)
)ENGINE=INNODB;

INSERT INTO Student(name,charger_id) VALUES ("alvin1",2), ("alvin2",4), ("alvin3",1), ("alvin4",3), ("alvin5",1), ("alvin6",3), ("alvin7",2); DELETE FROM ClassCharger WHERE name="冰冰"; INSERT student (name,charger_id) VALUES ("yuan",1); -- 刪除竟然成功,但是 alvin3顯示仍是有班主任id=1的冰冰的; -----------增長外鍵和刪除外鍵--------- ALTER TABLE student ADD CONSTRAINT abc -- 給外鍵起個名字叫 abc FOREIGN KEY(charger_id) -- 指定哪一個字段做爲外鍵 REFERENCES classcharger(id); -- 關聯到哪張表的哪一個字段 -- 刪除外鍵 ALTER TABLE student DROP FOREIGN KEY abc;

 INNODB支持的ON語句

--外鍵約束對子表的含義:   若是在父表中找不到候選鍵,則不容許在子表上進行insert/update

--外鍵約束對父表的含義:   在父表上進行update/delete以更新或刪除在子表中有一條或多條對應匹配行的候選鍵時,父表的行爲取決於:在定義子表的外鍵時指定的
on update/on delete子句 -----------------innodb支持的四種方式--------------------------------------- -----cascade方式 在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄 -----外鍵的級聯刪除:若是父表中的記錄被刪除,則子表中對應的記錄自動被刪除-------- FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE CASCADE --級聯刪除 示例:
create table student3(
id int primary key auto_increment,
name varchar (20),
charger_id tinyint,
foreign key (charger_id) references classcharger(id) on delete cascade
) ENGINE = INNODB;
------set null方式: 在父表上update/delete記錄時,將子表上匹配記錄的列設爲null;

------要注意子表的外鍵列不能爲not null
FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE SET NULL

示例:
能夠將student3裏的外鍵刪除,而後改爲set null
-- 先刪除外鍵
alter table
student3 drop froeign key 外鍵名字;
-- 將外鍵改成set null
alter table student3 add constraint s3_fk_ss foreign key (charger_id) references classcharger (id) on delete set null;
------Restrict方式 :拒絕對父表進行刪除更新操做(瞭解)

------No action方式 在mysql中同Restrict,若是子表中有匹配的記錄,則不容許對父表對應候選鍵
   -- 進行update/delete操做(瞭解)

 

多表查詢

準備表

-- 準備兩張表
-- company.employee
-- company.department

      create table employee(
      emp_id int auto_increment primary key not null,
      emp_name varchar(50),
      age int,
      dept_id int
      );

      insert into employee(emp_name,age,dept_id) values
        ('A',19,200),
        ('B',26,201),
        ('C',30,201),
        ('D',24,202),
        ('E',20,200),
        ('F',38,204);


    create table department(
       dept_id int,
       dept_name varchar(100)
      );

    insert into department values
      (200,'人事部'),
      (201,'技術部'),
      (202,'銷售部'),
      (203,'財政部');

mysql> select * from employee;
+--------+----------+------+---------+
| emp_id | emp_name | age  | dept_id |
+--------+----------+------+---------+
|      1 | A        |   19 |     200 |
|      2 | B        |   26 |     201 |
|      3 | C        |   30 |     201 |
|      4 | D        |   24 |     202 |
|      5 | E        |   20 |     200 |
|      6 | F        |   38 |     204 |
+--------+----------+------+---------+
rows in set (0.00 sec)

mysql> select * from department;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
|     200 | 人事部    |
|     201 | 技術部    |
|     202 | 銷售部    |
|     203 | 財政部    |
+---------+-----------+
rows in set (0.01 sec)

多表查詢之鏈接查詢

1.笛卡爾積查詢

mysql> SELECT * FROM employee,department;

--        select employee.emp_id,employee.emp_name,employee.age,
--        department.dept_name from employee,department;

+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age  | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
|      1 | A        |   19 |     200 |     200 | 人事部    |
|      1 | A        |   19 |     200 |     201 | 技術部    |
|      1 | A        |   19 |     200 |     202 | 銷售部    |
|      1 | A        |   19 |     200 |     203 | 財政部    |
|      2 | B        |   26 |     201 |     200 | 人事部    |
|      2 | B        |   26 |     201 |     201 | 技術部    |
|      2 | B        |   26 |     201 |     202 | 銷售部    |
|      2 | B        |   26 |     201 |     203 | 財政部    |
|      3 | C        |   30 |     201 |     200 | 人事部    |
|      3 | C        |   30 |     201 |     201 | 技術部    |
|      3 | C        |   30 |     201 |     202 | 銷售部    |
|      3 | C        |   30 |     201 |     203 | 財政部    |
|      4 | D        |   24 |     202 |     200 | 人事部    |
|      4 | D        |   24 |     202 |     201 | 技術部    |
|      4 | D        |   24 |     202 |     202 | 銷售部    |
|      4 | D        |   24 |     202 |     203 | 財政部    |
|      5 | E        |   20 |     200 |     200 | 人事部    |
|      5 | E        |   20 |     200 |     201 | 技術部    |
|      5 | E        |   20 |     200 |     202 | 銷售部    |
|      5 | E        |   20 |     200 |     203 | 財政部    |
|      6 | F        |   38 |     204 |     200 | 人事部    |
|      6 | F        |   38 |     204 |     201 | 技術部    |
|      6 | F        |   38 |     204 |     202 | 銷售部    |
|      6 | F        |   38 |     204 |     203 | 財政部    |
+--------+----------+------+---------+---------+-----------+

2.內鏈接-- 查詢兩張表中都有的關聯數據,至關於利用條件從笛卡爾積結果中篩選出了正確的結果。 -- 用的多


  select * from employee,department where employee.dept_id = department.dept_id; select * from employee inner join department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+
      | emp_id | emp_name | age  | dept_id | dept_id | dept_name |
      +--------+----------+------+---------+---------+-----------+
      |      1 | A        |   19 |     200 |     200 | 人事部    |
      |      2 | B        |   26 |     201 |     201 | 技術部    |
      |      3 | C        |   30 |     201 |     201 | 技術部    |
      |      4 | D        |   24 |     202 |     202 | 銷售部    |
      |      5 | E        |   20 |     200 |     200 | 人事部    |
      +--------+----------+------+---------+---------+-----------+
 示例:篩選出A所在的部門 select employee.emp_name,department.dept_name from employee,department where employee.dept_id = department.dept_id and employee.emp_name = "A"; 
select employee.emp_name,department.dept_name from department inner join employee on employee.dept_id = department.dept_id and employee.emp_name = "A";

3.外鏈接

--(1)左外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的結果  -- 用的多
左鏈接以左邊的employee表爲主,employee表的所有字段都顯示,沒有匹配上的就顯示空null
select * from employee left join department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 5 | E | 20 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 6 | F | 38 | 204 | NULL | NULL | +--------+----------+------+---------+---------+-----------+ --(2)右外鏈接:在內鏈接的基礎上增長右邊有左邊沒有的結果 右外鏈接以右邊的department表爲主,department表的所有字段都顯示 select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 5 | E | 20 | 200 | 200 | 人事部 | | NULL | NULL | NULL | NULL | 203 | 財政部 | +--------+----------+------+---------+---------+-----------+ --(3)全外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的和右邊有左邊沒有的結果 -- mysql不支持全外鏈接 full JOIN -- mysql可使用Union方式間接實現全外鏈接 select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id UNION select * from employee LEFT JOIN department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 5 | E | 20 | 200 | 200 | 人事部 | | NULL | NULL | NULL | NULL | 203 | 財政部 | | 6 | F | 38 | 204 | NULL | NULL | +--------+----------+------+---------+---------+-----------+ -- 注意 union與union all的區別:union會去掉相同的紀錄

多表查詢之複合條件鏈接查詢

-- 找出年齡大於等於25歲的員工所在的部門
-- 篩選出的是技術部,須要去重,加個 distinct 去重
SELECT DISTINCT department.dept_name FROM employee,department WHERE employee.dept_id = department.dept_id AND age>25; --之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示 select employee.emp_id,employee.emp_name,employee.age,department.dept_name from employee,department where employee.dept_id = department.dept_id order by age asc;

多表查詢之子查詢

-- 子查詢是將一個查詢語句嵌套在另外一個查詢語句中。
-- 內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。
-- 子查詢中能夠包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字
-- 還能夠包含比較運算符:= 、 !=、> 、<等


-- 1. 帶IN關鍵字的子查詢

   ---查詢employee表,但dept_id必須在department表中出現過

   select * from employee
            where dept_id IN
            (select dept_id from department);


+--------+----------+------+---------+
| emp_id | emp_name | age  | dept_id |
+--------+----------+------+---------+
|      1 | A        |   19 |     200 |
|      2 | B        |   26 |     201 |
|      3 | C        |   30 |     201 |
|      4 | D        |   24 |     202 |
|      5 | E        |   20 |     200 |
+--------+----------+------+---------+
rows in set (0.01 sec)



-- 2. 帶比較運算符的子查詢
      --      =、!=、>、>=、<、<=、<>

     -- 查詢員工年齡大於等於25歲的部門
     select dept_id,dept_name from department
           where dept_id IN
          (select DISTINCT dept_id from employee where age>=25);

-- 3. 帶EXISTS關鍵字的子查詢

-- EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。
-- 而是返回一個真假值。Ture或False
-- 當返回Ture時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢

     select * from employee
              WHERE EXISTS
              (SELECT dept_name from department where dept_id=203);

      --department表中存在dept_id=203,Ture


     select * from employee
                WHERE EXISTS
              (SELECT dept_name from department where dept_id=205);

     -- Empty set (0.00 sec)


    ps:  create table t1(select * from t2);

索引

索引簡介

索引在MySql中也叫作「鍵」,是存儲引擎用於快速找到記錄的一種數據結構。索引對於良好的性能很是關鍵,尤爲是當表中的數據量愈來愈大時,索引對於性能

的影響愈發重要。

索引優化應該是對查詢性能優化最有效的手段了。

索引可以輕易將查詢性能提升好幾個數量級。

索引至關於字典的音序表,若是要查某個字,若是不使用音序表,則須要從幾百頁中逐頁去查。(或者理解爲目錄)

索引的特色:

  建立與維護索引會消耗不少時間與磁盤空間,但查詢速度大大提升。

索引語法

-- 建立表時
-- 語法

create table 表名(
      字段名1  數據類型 [完整性約束條件],
      字段名2  數據類型 [完整性約束條件],
      字段名3  數據類型 [完整性約束條件],
      [unique | FULLTEXT | SPATIAL] INDEX | KEY [索引名](字段名[長度]) [asc | desc ]
      
);

-- [unique | FULLTEXT | SPATIAL]: 可加可不加的
-- unique:惟一索引;不能重複
-- FULLTEXT:全局索引;
-- SPATIAL:空間索引
-- 若是不加上面三個,直接用index 或者 key: 建立普通索引
-- index 或者 key 後面跟的是索引名字 
-- 索引名可寫可不寫,不寫的話,默認就與字段名同樣

-- 建立普通索引示例:
create table test1(
  id int primary key auto_increment,
  name varchar (20),
  index index_name (name )   -- 建立普通索引 能夠用 index,也能夠用key, 兩個是徹底同樣的,index_name可寫可不寫
  sarlay int default 1000
);

-- 建立惟一索引

-- 對已經存在的表添加個惟一索引示例:
alter table test1 modify name varchar (20) unique ;

-- 建立惟一索引示例
create table emp2(
  id int,
  name varchar (20),
  bank_num char (19) unique ,
  resume varchar (50),
  unique index index_emp_name(name )
);


-- 建立全文索引示例
create table emp3(
  id int,
  name varchar (20),
  resume varchar (500),
  FULLTEXT index index_resume (resume )
)

--建立多列索引示例:
create table emp4(
  id int,
  name varchar (20),
  resume varchar (500),
  Index index_name_resume (name,resume ) -- 給 name 和 resume 兩列都共用一個索引
)

添加索引(在已經建立好表的狀況下,添加索引)

-- create在已經存在的表上建立索引
create [unique | FULLTEXT | SPATIAL] index 索引名
  on 表名 (字段名[(長度)] [asc | desc ]);  -- on 表示給哪張表下的哪一個字段添加索引
  
-- alter table 在已經存在的表上建立索引
-- alter是先把表找到,而後再給該表下的哪一個字段添加索引
alter table 表名 add [unique | FULLTEXT | SPATIAL] index 
  索引名 (字段名[(長度)] [asc | desc ]);

刪除索引

  -- 語法
  drop index 索引名 on 表名;
  
  -- 示例
  drop index index_name on t2;

索引測試實驗

-- 建立表
create table Indexdb.t1(id int ,name varchar (40));

-- 存儲過程
-- 經過循環,插入50條數據

delimiter ! -- 修改結束符的,好比上面一個sql語句結束,都是以;結尾,能夠修改成!
create procedure autoinsert()   -- procedure:是個關鍵字,表示存儲過程,autoinsert() 是定義的函數名字
begin
declare i int default 1;  -- 聲明一個變量i,從1開始
while (i <500000) do
insert into Indexdb.t1 values (i,"yuan");
set i = i+1;
end while;
end !

delimiter ;  -- 分隔符再改會來

-- 調用函數插入50萬條數據
call autoinsert();

-- 花費時間比較
-- 建立索引前
select * from Indexdb.t1 where id=300000; -- 0.32s

-- 添加索引
alter table Indexdb.t1 add index index_id (id);

-- 添加索引後
select * from Indexdb.t1 where id=300000; -- 0.01s
相關文章
相關標籤/搜索