Mac操作数据库Mysql知识点备忘录
目錄
Mac安裝Ubuntu啟動Mysql
Mac安裝Mysql
CenterOS
Mac
Mysql 8和5的密碼插件區別
介紹
基礎命令操作數據庫
遠程連接
數據庫操作命令
表操作命令
數據操作命令
備份與恢復命令
查詢分配
條件查詢
聚合查詢
分組查詢
排序
分頁查詢
高級特性
表關系建立和外鍵
inner join 連接查詢
完整的select語句
自關聯
視圖sql語句的封裝
事務
索引
小例子
Python3.6數據庫操作Demo
配置PYCharm
邏輯代碼
面向對象封裝
登錄Demo
Mac安裝Ubuntu啟動Mysql
1.先安裝VirtualBoxVM? ?安裝搜狗
2.然后安裝Ubuntu系統安裝
3.打開Ubuntu左側工具欄選擇軟件中心,搜索Mysql更新安裝Mysql客戶端和Mysql服務端源
4.執行命令安裝
安裝
sudo apt-get install mysql-server mysql-client 然后按照提示輸入一旦安裝完成,MySQL 服務器應該自動啟動。您可以在終端提示符后運行以下命令來檢查 MySQL 服務器是否正在運行
sudo netstat -tap | grep mysql出現如下代表已啟動
deftmikejing@deftmikejing-VirtualBox:~$ sudo netstat -tap | grep mysql [sudo] password for deftmikejing: tcp6 0 0 [::]:mysql [::]:* LISTEN 1078/mysqld deftmikejing@deftmikejing-VirtualBox:~$ 或者 deftmikejing@deftmikejing-VirtualBox:/lib/systemd/system$ ps ajx|grep mysql1 686 686 686 ? -1 Ss 120 0:00 /bin/sh /usr/bin/mysqld_safe686 1141 686 686 ? -1 Sl 120 0:01 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=33062877 6341 6340 2877 pts/1 6340 S+ 1000 0:00 grep --color=auto mysql- 啟動
- 停止
- 重啟
如果服務器不能正常運行,您可以通過下列命令啟動它:
?sudo /etc/init.d/mysql restartmysql 的默認密碼是linux系統密碼,如果需要修改
mysql -u root -p輸入密碼set password =password('需要替換的密碼');5.設置mysql遠程訪問
使用 sudo netstat -lntp 命令看看
tcp??????? 0????? 0 0.0.0.0:3306??????????? 0.0.0.0:*?????????????? LISTEN?
如果上面0 0.0.0.0后面不是3306的話就打開/etc/mysql/my.cnf?? 吧下面這一行給注釋掉
bind-address = 127.0.0.1
修改配置以后記得要重啟mysql
編輯mysql配置文件,把其中bind-address = 127.0.0.1注釋了
vi /etc/mysql/mysql.conf.d/mysqld.cnf建立遠程連接?
使用root進入mysql命令行 mysql -uroot -p執行如下2個命令,示例中mysql的root賬號密碼:root(這root填寫具體的密碼) grant all privileges on *.* to root@"%" identified by "password" with grant option; flush privileges;重啟mysql/etc/init.d/mysql restart注意說明
本機登陸mysql:mysql -u root -p (-p一定要有);從所有主機:grant all privileges on *.* to root@"%" identified by "password" with grant option;從指定主機:grant all privileges on *.* to root@"192.168.11.205" identified by "password" with grant option;??例如:grant all privileges on *.* to test@'192.168.113.124' identified by '123456'然后執行flush privileges;重啟Mysql查看下剛才的賬號
select host,user,password from mysql.user到這里就可以測試下宿主機器ping通宿主下的Ubuntu
默認情況下無法ping通,需要修改網絡設置?參考鏈接
之后下載Navicat用Mac鏈接Ubuntu里面的Mysql就可以用圖形化工具操作了
Mac安裝Mysql
CenterOS
一般我們部署到Linux上去,這里就先介紹些CenterOS的安裝方法
以 MySQL 5.6 的 Yum 源為例,如果需要更高版本可以另尋,安裝命令如下:
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm yum install -y mysql mysql-server運行如上命令即可完成安裝,初始密碼為空。接下來需要啟動 MySQL 服務。
啟動 MySQL 服務命令:
sudo systemctl start mysqld停止、重啟命令:
sudo systemctl stop mysqld sudo systemctl restart mysqld以上我們就完成了 Linux 下 MySQL 的安裝,安裝完成之后可以修改密碼,可以執行如下命令:
mysql -uroot -p輸入密碼后進入 MySQL 命令行模式。
use mysql; UPDATE user SET Password = PASSWORD('newpass') WHERE user = 'root'; FLUSH PRIVILEGES;命令中 newpass 即為修改的新的 MySQL 密碼,請自行替換。
由于 Linux 一般會作為服務器使用,為了使得 MySQL 可以被遠程訪問,我們需要修改 MySQL 的配置文件,配置文件路徑一般為 /etc/mysql/my.cnf。
如使用 vi 進行修改的命令如下:
vi /etc/mysql/my.cnf取消此行的注釋:
bind-address = 127.0.0.1此行限制了 MySQL 只能本地訪問而不能遠程訪問,取消注釋即可解除此限制。
修改完成之后重啟 MySQL 服務,這樣 MySQL 就可以被遠程訪問了。
到此為止,Linux 下安裝 MySQL 的過程結束。
Mac
推薦使用 Homebrew 安裝,執行 brew 命令即可。
brew install mysql啟動、停止、重啟 MySQL 服務的命令:
sudo mysql.server start sudo mysql.server stop sudo mysql.server restartMac 一般不會作為服務器使用,如果要想取消本地 host 綁定,同樣修改 my.cnf 文件,然后重啟服務即可。
?
這里如果找不到my.cnf文件,可以通過如下命令進行查找:
find 文件路徑 參數比如你可以通過以下命令在用戶文件夾中搜索名字中包含screen的文件
find ~ -iname ?"screen*"你也可以在特定的文件夾中尋找特定的文件,比如
find ~/Library/ -iname "com.apple.syncedpreferences.plist"這個命令可以在Library文件夾中尋找com.apple.syncedpreferences.plist文件
mdfind命令就是Spotlight功能的終端界面,這意味著如果Spotlight被禁用,mdfind命令也將無法工作。mdfind命令非常迅速、高效。最基本的使用方法是:
mdfind -name 文件名字比如你可以通過下面的命令尋找Photo 1.PNG文件
mdfind -name "Photo 1.PNG"因為mdfind就是Spotlight功能的終端界面,你還可以使用mdfind尋找文件和文件夾的內容,比如通過以下命令尋找所有包含Will Pearson文字的文件:
mdfind "Will Pearson"mdfind命令還可以通過-onlyin參數搜索特定文件夾的內容,比如
mdfind -onlyin ~/Library plist這條命令可以搜索Library文件夾中所有plist文件。
mikejing$ mdfind -name "my.cnf" /usr/local/etc/my.cnf修改該文件下127.0.0.1?是否注釋來調整是否可以遠程連接。
安裝之后進行配置
1.啟動
mysql.server start2.mysql配置腳本
/usr/local/opt/mysql/bin/mysql_secure_installation //mysql 提供的配置向導詳細如下
sunyichaodeMacBook-Pro:~ sunyichao$ /usr/local/opt/mysql/bin/mysql_secure_installation //mysql 提供的配置向導 Securing the MySQL server deployment. Connecting to MySQL using a blank password. VALIDATE PASSWORD PLUGIN can be used to test passwordsand improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD plugin?Press y|Y for Yes, any other key for No: k //是否采用mysql密碼安全檢測插件(這里作為演示選擇否,密碼檢查插件要求密碼復雜程度高,大小寫字母+數字+字符等) Please set the password for root here. // 首次使用自帶配置腳本,設置root密碼New password:Re-enter new password:By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? [Y/n] Y //是否刪除匿名用戶... Success!Normally, root should only be allowed to connect from 'localhost'.This ensures that someone cannot guess at the root password from the network.Disallow root login remotely? [Y/n] Y //是否禁止遠程登錄... Success!By default, MySQL comes with a database named 'test' that anyone can access.This is also intended only for testing, and should be removed before moving into a production environment.Remove test database and access to it? [Y/n] Y //刪除測試數據庫,并登錄Dropping test database...... Success!Removing privileges on test database...... Success!Reloading the privilege tables will ensure that all changes made so far will take effect immediately.Reload privilege tables now? [Y/n] Y//重新載入權限表... Success!All done! If you've completed all of the above steps, your MySQL installation should now be secure.Thanks for using MySQL!Cleaning up... sunyichaodeMacBook-Pro:~ sunyichao$Mysql 8和5的密碼插件區別
Navicat連接報錯如下:
2059 - Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(../Frameworks/caching_sha2_password.so, 2): image not found兩個版本的區別?
mysql> select version()-> ; +-----------+ | version() | +-----------+ | 8.0.16 | +-----------+ 1 row in set (0.01 sec)mysql> show variables like 'default_authentication_plugin'-> ; +-------------------------------+-----------------------+ | Variable_name | Value | +-------------------------------+-----------------------+ | default_authentication_plugin | caching_sha2_password | +-------------------------------+-----------------------+ 1 row in set (0.10 sec)mysql> show tables; +---------------------------+ | Tables_in_mysql | +---------------------------+ | columns_priv | | component | | db | | default_roles | | engine_cost | | func | | general_log | | global_grants | | gtid_executed | | help_category | | help_keyword | | help_relation | | help_topic | | innodb_index_stats | | innodb_table_stats | | password_history | | plugin | | procs_priv | | proxies_priv | | role_edges | | server_cost | | servers | | slave_master_info | | slave_relay_log_info | | slave_worker_info | | slow_log | | tables_priv | | time_zone | | time_zone_leap_second | | time_zone_name | | time_zone_transition | | time_zone_transition_type | | user | +---------------------------+ 33 rows in set (0.01 sec)mysql> select Host, User, Plugin from user; +-----------+------------------+-----------------------+ | Host | User | Plugin | +-----------+------------------+-----------------------+ | localhost | mysql.infoschema | caching_sha2_password | | localhost | mysql.session | caching_sha2_password | | localhost | mysql.sys | caching_sha2_password | | localhost | root | caching_sha2_password | +-----------+------------------+-----------------------+ 4 rows in set (0.00 sec) mysql> select version(); +------------+ | version() | +------------+ | 5.7.15-log | +------------+ 1 row in set (0.00 sec)mysql> show variables like 'default_authentication_plugin'; +-------------------------------+-----------------------+ | Variable_name | Value | +-------------------------------+-----------------------+ | default_authentication_plugin | mysql_native_password | +-------------------------------+-----------------------+ 1 row in set (0.01 sec)mysql> select host,user,plugin from mysql.user; +-----------+-----------+-----------------------+ | host | user | plugin | +-----------+-----------+-----------------------+ | localhost | root | mysql_native_password | | localhost | mysql.sys | mysql_native_password | | % | root | mysql_native_password |可以看到MySQL8.0.11版本默認的認證方式是caching_sha2_password ,而在MySQL5.7版本則為mysql_native_password。
若想在MySQL8.0版本中繼續使用舊版本中的認證方式需要在my.cnf 文件中配置并重啟,因為此參數不可動態修改。
?
寫入my.cnf 文件后重啟MySQL:
vim my.cnf [mysqld] default_authentication_plugin=mysql_native_password上面的這種方案對已有的賬戶是無法修改的,只是后續新增的賬戶就會默認的Plugin變成mysql_native_password?
第二種解決方法:兼容新老版本的認證方式。
創建新用戶步驟,其中 with mysql_native_password不是必須的,默認根據配置文件走?
--創建新的用戶:create user root@'%' identified WITH mysql_native_password BY 'password';grant all privileges on *.* to root@'%' with grant option;flush privileges;--在MySQL8.0創建用戶并授權的語句則不被支持:mysql> grant all privileges on *.* to root@'%' identified by 'password' with grant option;ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'root' with grant option' at line 1mysql>?
介紹
- 數據庫系統解決的問題:持久化存儲,優化讀寫,保證數據的有效性
- 當前使用的數據庫,主要分為兩類
- 文檔型,如sqlite,就是一個文件,通過對文件的復制完成數據庫的復制
- 服務型,如mysql、postgre,數據存儲在一個物理文件中,但是需要使用終端以tcp/ip協議連接,進行數據庫的讀寫操作
E-R模型
- 當前物理的數據庫都是按照E-R模型進行設計的
- E表示entry,實體
- R表示relationship,關系
- 一個實體轉換為數據庫中的一個表
- 關系描述兩個實體之間的對應規則,包括
- 一對一
- 一對多
- 多對多
- 關系轉換為數據庫表中的一個列 *在關系型數據庫中一行就是一個對象
三范式
- 經過研究和對使用中問題的總結,對于設計數據庫提出了一些規范,這些規范被稱為范式
- 第一范式(1NF):列不可拆分
- 第二范式(2NF):唯一標識
- 第三范式(3NF):引用主鍵
- 說明:后一個范式,都是在前一個范式的基礎上建立的
?
字段類型
- 在mysql中包含的數據類型很多,這里主要列出來常用的幾種
- 數字:int,decimal
- 字符串:char(不可變,長度不夠自動填充), varchar(可變的),text
- 日期:datetime
- 布爾:bit
約束 - 主鍵primary key
- 非空not null
- 惟一unique
- 默認default
- 外鍵foreign key
基礎命令操作數據庫
遠程連接
- 一般在公司開發中,可能會將數據庫統一搭建在一臺服務器上,所有開發人員共用一個數據庫,而不是在自己的電腦中配置一個數據庫
- 運行命令
- -h后面寫要連接的主機ip地址
- -u后面寫連接的用戶名
- -p回車后寫密碼
數據庫操作命令
- 查看數據庫
- 創建數據庫
- 刪除數據庫
- 切換數據庫
- 查看當前選擇的數據庫
表操作命令
- 查看當前數據庫中所有表
- 創建表
-
auto_increment表示自動增長
create table 表名(列及類型); 如: create table students( id int auto_increment primary key, sname varchar(10) not null ); -
修改表
- 刪除表
- 查看表結構
- 更改表名稱
- 查看表的創建語句
數據操作命令
- 查詢
- 增加
- 主鍵列是自動增長,但是在全列插入時需要占位,通常使用0,插入成功后以實際數據為準
- 修改
- 刪除
- 邏輯刪除,本質就是修改操作update
備份與恢復命令
數據備份
- 進入超級管理員
- 進入mysql庫目錄?
- 運行mysqldump命令
數據恢復
-
連接mysql,創建數據庫
-
退出連接,執行如下命令
查詢分配
條件查詢
- 查詢的基本語法
- from關鍵字后面寫表名,表示數據來源于是這張表
- select后面寫表中的列名,如果是*表示在結果中顯示表中所有列
- 在select后面的列名部分,可以使用as為列起別名,這個別名出現在結果集中
- 如果要查詢多個列,之間使用逗號分隔
消除重復行
- 在select后面列前使用distinct可以消除重復的行
- 使用where子句對表中的數據篩選,結果為true的行會出現在結果集中
- 語法如下:
比較運算符
- 等于=
- 大于>
- 大于等于>=
- 小于<
- 小于等于<=
- 不等于!=或<>
- 查詢編號大于3的學生
- 查詢編號不大于4的科目
- 查詢姓名不是“黃蓉”的學生
- 查詢沒被刪除的學生
邏輯運算符
- and
- or
- not
- 查詢編號大于3的女同學
- 查詢編號小于4或沒被刪除的學生
模糊查詢
- like
- %表示任意多個任意字符
- _表示一個任意字符
- 查詢姓黃的學生
- 查詢姓黃并且名字是一個字的學生
- 查詢姓黃或叫靖的學生
范圍查詢
- in表示在一個非連續的范圍內
- 查詢編號是1或3或8的學生
- between ... and ...表示在一個連續的范圍內
- 查詢學生是3至8的學生
- 查詢學生是3至8的男生
空判斷
- 注意:null與''是不同的
- 判空is null
- 查詢沒有填寫地址的學生
- 判非空is not null
- 查詢填寫了地址的學生
- 查詢填寫了地址的女生
優先級
- 小括號,not,比較運算符,邏輯運算符
- and比or先運算,如果同時出現并希望先算or,需要結合()使用
聚合查詢
- 為了快速得到統計數據,提供了5個聚合函數
- count(*)表示計算總行數,括號中寫星與列名,結果是相同的
- 查詢學生總數
- max(列)表示求此列的最大值
- 查詢女生的編號最大值
- min(列)表示求此列的最小值
- 查詢未刪除的學生最小編號
- sum(列)表示求此列的和
- 查詢男生的編號之后
- avg(列)表示求此列的平均值
- 查詢未刪除女生的編號平均值
分組查詢
- 按照字段分組,表示此字段相同的數據會被放到一個組中
- 分組后,只能查詢出相同的數據列,對于有差異的數據列無法出現在結果集中
- 可以對分組后的數據進行統計,做聚合運算
- 語法:
- 查詢男女生總數
- 查詢各城市人數
分組后的數據篩選
- 語法:
- having后面的條件運算符與where的相同
- 查詢男生總人數
對比where與having
- where是對from后面指定的表進行數據篩選,屬于對原始數據的篩選
- having是對group by的結果進行篩選
排序
- 為了方便查看數據,可以對數據進行排序
- 語法:
- 將行數據按照列1進行排序,如果某些行列1的值相同時,則按照列2排序,以此類推
- 默認按照列值從小到大排列
- asc從小到大排列,即升序
- desc從大到小排序,即降序
- 查詢未刪除男生學生信息,按學號降序
- 查詢未刪除科目信息,按名稱升序
分頁查詢
- 當數據量過大時,在一頁中查看數據是一件非常麻煩的事情
- 語法
- 從start開始,獲取count條數據
- start索引從0開始
示例:分頁
- 已知:每頁顯示m條數據,當前顯示第n頁
- 求總頁數:此段邏輯后面會在python中實現
- 查詢總條數p1
- 使用p1除以m得到p2
- 如果整除則p2為總數頁
- 如果不整除則p2+1為總頁數
- 求第n頁的數據
高級特性
表關系建立和外鍵
案例一:
學生 1對多? 成績?? ? 學生表中一行能對應多行成績出現
科目 1對多? 成績? ? 科目中一行能對應多行成績出現
成績 1對1? ?學生和科目? ?一條成績必定對應一個學生和一個科目
案例二:
班級? ? 1對多? 學生? ? 班級表中一行,能對應多行學生出現
學生? 1對1? ? 班級? ? ? 一個學生必定對應一個班級
1對多代表1的這一方會出現多個在另一方,因此主鍵關聯都會寫在學生表中或者成績表中?
- 創建成績表scores,結構如下
- id
- 學生
- 科目
- 成績
- ?
- 思考:學生列應該存什么信息呢?
- 答:學生列的數據不是在這里新建的,而應該從學生表引用過來,關系也是一條數據;根據范式要求應該存儲學生的編號,而不是學生的姓名等其它信息
- 同理,科目表也是關系列,引用科目表中的數據
這里學生,成績,科目三個的分析和電商里面 用戶,購物車,商品是一樣的,首先
學生和科目是n:m的關系,無法維護,因此需要再開一張表成績來維護好比用戶和商品是n:m的關系,因此需要購物車來維護,用戶和購物車是1:n,商品和購物車也是1:n
?
以下是科目和學生的標 以及創建一張成績單的標,
+----+---------+ | id | title | +----+---------+ | 1 | Science | | 2 | Math | | 3 | English | | 4 | Pysical | | 5 | Mamical | +----+---------+ 5 rows in set (0.00 sec)mysql> select *from students; +----+------------+--------+---------------------+----------+-------+----------+ | id | name | gender | birthday | isDelete | score | address | +----+------------+--------+---------------------+----------+-------+----------+ | 1 | Mekejing | | 2018-01-01 00:00:00 | | 97 | NULL | | 2 | jiaojiao | | 2018-01-01 00:00:00 | | 55 | NULL | | 3 | elf | | 2018-01-01 00:00:00 | | 100 | shenzhen | | 4 | 11111 | | 2018-01-01 00:00:00 | | 60 | shenzhen | | 6 | 3333333 | | 2018-01-01 00:00:00 | | 77 | shenzhen | | 7 | wuke | | 0000-00-00 00:00:00 | | 80 | NULL | | 8 | Deft | | 2019-01-01 00:00:00 | | 32 | NULL | | 9 | jiaoBo | | 2001-01-01 00:00:00 | | 71 | NULL | | 10 | oojiaojiao | | 2001-01-01 00:00:00 | | 71 | NULL | +----+------------+--------+---------------------+----------+-------+----------+mysql> create table score(-> id int auto_increment primary key not null,-> score decimal(4,1),-> stuid int,-> subid int,-> foreign key(stuid) references students(id),-> foreign key(subid) references subjects(id))-> ; Query OK, 0 rows affected (0.02 sec)mysql> desc score; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | score | decimal(4,1) | YES | | NULL | | | stuid | int(11) | YES | MUL | NULL | | | subid | int(11) | YES | MUL | NULL | | +-------+--------------+------+-----+---------+----------------+查看原始的創建腳本
show create table score;| score | CREATE TABLE `score` (`id` int(11) NOT NULL AUTO_INCREMENT,`score` decimal(4,1) DEFAULT NULL,`stuid` int(11) DEFAULT NULL,`subid` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `stuid` (`stuid`),KEY `subid` (`subid`),CONSTRAINT `score_ibfk_1` FOREIGN KEY (`stuid`) REFERENCES `students` (`id`),CONSTRAINT `score_ibfk_2` FOREIGN KEY (`subid`) REFERENCES `subjects` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 |可以看到stuid和subid都是關聯著各自表中的primary key
- 思考:怎么保證關系列數據的有效性呢?任何整數都可以嗎?
- 答:必須是學生表中id列存在的數據,可以通過外鍵約束進行數據的有效性驗證
- 為stuid添加外鍵約束
可以和上面一樣直接在創建表的時候創建外鍵約束,也可以alter添加
alter table scores add constraint stu_sco foreign key(stuid) references students(id);- 此時插入或者修改數據時,如果stuid的值在students表中不存在則會報錯
- 在創建表時可以直接創建約束
外鍵的級聯操作)
例如刪除students里面的一個學生,那么score里面已經有數據關聯上,如何處理?
- 在刪除students表的數據時,如果這個id值在scores中已經存在,則會拋異常
- 推薦使用邏輯刪除,還可以解決這個問題
- 可以創建表時指定級聯操作,也可以在創建表后再修改外鍵的級聯操作
- 語法
- 級聯操作的類型包括:
- restrict(限制):默認值,拋異常
- cascade(級聯):如果主表的記錄刪掉,則從表中相關聯的記錄都將被刪除
- set null:將外鍵設置為空
- no action:什么都不做
刪除約束
查看表建立語句| Table | Create Table | +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | score | CREATE TABLE `score` (`id` int(11) NOT NULL AUTO_INCREMENT,`score` decimal(5,2) DEFAULT NULL,`stuid` int(11) DEFAULT NULL,`subid` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `subid` (`subid`),KEY `stu_sco` (`stuid`),CONSTRAINT `stu_sco` FOREIGN KEY (`stuid`) REFERENCES `students` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 |刪除約束 alter table score drop foreign key stu_sco;這時候就可以刪除級聯的表數據了,比如這個時候你刪除了students表的數據,其他表有外鍵關聯也沒事,因為約束已經解除了,但是這個時候你要添加約束,就會報錯,因為數據已經找不到了 alter table score add constraint stu_sco foreign key(stuid) references students(id); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mikejing`.`#sql-15650_18`, CONSTRAINT `stu_sco` FOREIGN KEY (`stuid`) REFERENCES `students` (`id`)) mysql> delete from score where id = 4; Query OK, 1 row affected (0.00 sec)mysql> alter table score add constraint stu_sco foreign key(stuid) references students(id); Query OK, 4 rows affected (0.05 sec) Records: 4 Duplicates: 0 Warnings: 0?
- 問:查詢每個學生每個科目的分數
- 分析:學生姓名來源于students表,科目名稱來源于subjects,分數來源于scores表,怎么將3個表放到一起查詢,并將結果顯示在同一個結果集中呢?
- 答:當查詢結果來源于多張表時,需要使用連接查詢
- 關鍵:找到表間的關系,當前的關系是
- students表的id---scores表的stuid
- subjects表的id---scores表的subid
- 則上面問題的答案是:
- 結論:當需要對有關系的多張表進行查詢時,需要使用連接join
inner join 連接查詢
select *from score inner join students;這是最基本的,如果score表10條和students表5條,因此在不加on條件下,組合起來是10*5=50條新的數據組合,然后根據on后面的組合篩選,比如下面的操作,id關聯到的,因此自關聯的表可以理解為 自身表條目的平方組合出來的數據進行篩選即可
?
實際上就是多個表鏈接成一個大表
- 連接查詢分類如下:
- 表A inner join 表B:表A與表B匹配的行會出現在結果中
- 表A left join 表B:表A與表B匹配的行會出現在結果中,外加表A中獨有的數據,未對應的數據使用null填充
- 表A right join 表B:表A與表B匹配的行會出現在結果中,外加表B中獨有的數據,未對應的數據使用null填充
- 在查詢或條件中推薦使用“表名.列名”的語法
- 如果多個表中列名不重復可以省略“表名.”部分
- 如果表的名稱太長,可以在表名后面使用' as 簡寫名'或' 簡寫名',為表起個臨時的簡寫名稱
- 查詢學生的姓名、平均分
- 查詢男生的姓名、總分
- 查詢科目的名稱、平均分
- 查詢未刪除科目的名稱、最高分、平均分
- 嵌套查詢
第一個select from用的后面查詢出來的表,需要給一個as別名,不然會報錯
完整的select語句
select distinct * from 表名 inner |left|right|on join 表 on 關系 where .... group by ... having ... order by ... limit star,count- 執行順序為:
- from 表名
- where .... inner...
- group by ...
- select distinct *
- having ...
- order by ...
- limit star,count
- 實際使用中,只是語句中某些部分的組合,而不是全部
自關聯
以省市縣為例,這些數據不需要開多個表,可以通過自關聯的方式完成,例如
id title pid 1 浙江 NULL 2 寧波 1(關聯到自身表中另一行) 3 慈溪 2 (關聯到自身表中另一行) 。。。。。這種設計還有類似分類,一張表中可以無限數據,無限分類下去,充分利用空間?
?
- 設計省信息的表結構provinces
- id
- ptitle
- 設計市信息的表結構citys
- id
- ctitle
- proid
- citys表的proid表示城市所屬的省,對應著provinces表的id值
- 問題:能不能將兩個表合成一張表呢?
- 思考:觀察兩張表發現,citys表比provinces表多一個列proid,其它列的類型都是一樣的
- 意義:存儲的都是地區信息,而且每種信息的數據量有限,沒必要增加一個新表,或者將來還要存儲區、鄉鎮信息,都增加新表的開銷太大
- 答案:定義表areas,結構如下
- id
- atitle
- pid
- 因為省沒有所屬的省份,所以可以填寫為null
- 城市所屬的省份pid,填寫省所對應的編號id
- 這就是自關聯,表中的某一列,關聯了這個表中的另外一列,但是它們的業務邏輯含義是不一樣的,城市信息的pid引用的是省信息的id
- 在這個表中,結構不變,可以添加區縣、鄉鎮街道、村社區等信息
- 創建areas表的語句如下:
視圖sql語句的封裝
- 對于復雜的查詢,在多次使用后,維護是一件非常麻煩的事情
- 解決:定義視圖
- 視圖本質就是對查詢的一個封裝
- 定義視圖
- 視圖的用途就是查詢
事務
數據被更改時? insert? update delete?
- 當一個業務邏輯需要多個sql完成時,如果其中某條sql語句出錯,則希望整個操作都退回
- 使用事務可以完成退回的功能,保證業務邏輯的正確性
- 事務四大特性(簡稱ACID)
- 原子性(Atomicity):事務中的全部操作在數據庫中是不可分割的,要么全部完成,要么均不執行
- 一致性(Consistency):幾個并行執行的事務,其執行結果必須與按某一順序串行執行的結果相一致
- 隔離性(Isolation):事務的執行不受其他事務的干擾,事務執行的中間結果對其他事務必須是透明的
- 持久性(Durability):對于任意已提交事務,系統必須保證該事務對數據庫的改變不被丟失,即使數據庫出現故障
- 要求:表的類型必須是innodb或bdb類型,才可以對此表使用事務
- 查看表的創建語句
- 修改表的類型
- 事務語句
事務可以理解為對同一個東西的修改操作,可以理解為OC里面的setter操作,多線程會搶資源,因此會有鎖的存在,事務也是一樣,通過鎖來保證數據執行的一致性和隔離性,事務其實就通過鎖在內存中開辟一個空間進行計算,通過commit或者rollback來確定是否需要采用之前的修改,如果其他線程也在操作數據庫而且是操作同一條,就會出現鎖等待,等commit或者rollback之后解鎖繼續執行
先做個淺顯的理解,到時候深入了再來記錄;
其實事務可以優化的點想到一個,比如你要插入很多條數據,直接執行insert語句不開啟事務,其實每次都會對數據庫的更改和提交操作,因此開啟事務,再合理內存配置范圍內,通過事務一次性提交更改物理數據庫,減少損耗
事務引擎提交事務會開啟行級鎖
索引
Mysql 索引原理
Mysql索引使用方式介紹
MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構。提取句子主干,就可以得到索引的本質:索引是數據結構。
我們知道,數據庫查詢是數據庫的最主要功能之一。我們都希望查詢數據的速度能盡可能的快,因此數據庫系統的設計者會從查詢算法的角度進行優化。最基本的查詢算法當然是順序查找(linear search),這種復雜度為O(n)的算法在數據量很大時顯然是糟糕的,好在計算機科學的發展提供了很多更優秀的查找算法,例如二分查找(binary search)、二叉樹查找(binary tree search)等。如果稍微分析一下會發現,每種查找算法都只能應用于特定的數據結構之上,例如二分查找要求被檢索數據有序,而二叉樹查找只能應用于二叉查找樹上,但是數據本身的組織結構不可能完全滿足各種數據結構(例如,理論上不可能同時將兩列都按順序進行組織),所以,在數據之外,數據庫系統還維護著滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引。
可以理解為數據本身的組織結構不可能滿足各種數據結構,比如滿足有序的二分查找或者二叉樹查找,因此需要建立索引,把該字段或者多個字段下的所有數據都拉出來新建一個目錄,滿足數據結構查找,比如有序拉出來二分查找。
選擇數據類型
- 越小的數據類型和簡單的數據類型越好,數據越小磁盤,內存,CPU中需要更少的空間,處理起來更快
- 盡量避免NULL:應指定列為NOT NULL,除非你想存儲NULL,在Mysql中,含有空值的列很難進行查詢優化,因為他們使索引統計信息比較起來更復雜,應該用0,特殊的值,或者空串來標識
?
普通索引
普通索引僅有一個功能:加速查詢
創建表
create table in1(nid int not null auto_increment primary key,name varchar(32) not null,email varchar(64) not null,extra text,index ix_name (name) )創建
create index index_name on table_name(column_name)查看
show index from table_name;刪除
drop index_name on table_name;注意:對于創建索引時如果是BLOB?和?TEXT?類型,必須指定length。
create index ix_extra on in1(extra(32));缺點
雖然索引提高了查詢速度,但是會降低更新表的速度,如果對表進行INSERT UPDATE和DELETE,Mysql不僅要更新數據,還有保存更新索引文件,而且建立索引會占磁盤索引對應的文件
- 查看執行時間set profiling = 1;SQL...show profiles;詳細介紹可以看上面的文章
?
小例子
1、設計班級表,與學生表關聯,并進行查詢 2、設計分類表,自關聯,并進行查詢 3、創建視圖存儲上面的兩個查詢# 班級表和學生表關聯 1.班級表和學生表 班級表一條數據可以對應多條學生數據 1:n 因此關聯外鍵設置在n這里 create table Class( id int auto_increment primary key not null, name varchar(10));create table Student( id int auto_increment primary key not null, name varchar(10), clsid int, foreign key(clsid) references Class(id));create view V_stu_class as select Student.id,Student.name,Class.name as className from Student inner join Class on Student.clsid=Class.id# 自關聯 create table typeClass( id int auto_increment primary key not null, name varchar(10), pid int, foreign key(pid) references typeClass(id));create view V_types as select son.* from typeClass as father inner join TypeClass as son on son.pid=father.id?
Python3.6數據庫操作Demo
首先Python3x之后需要安裝 pymysql
In [1]: import osIn [2]: os.__file__ Out[2]: '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.py'In [3]:以上目錄能找到自帶的安裝包,我們執行
pip3 install pymysql可以在該目錄下找到site-packages文件夾,里面有我們自行安裝的所有安裝包,我們在cmd下面import會在該目錄下自動查找,OK
配置PYCharm
但是我們用PYCharm的時候,你import你自行安裝的包,是會報錯的,告訴我們找不到該moduel,由于上不了圖了,說下步驟
1.打開PYCharm,File? ------ Default Settings---------選擇Project Interpreter,右側會出現默認的配置環境
2.由于默認的環境不會加載site-packages,需要自己配置新的,點擊齒輪,選擇Add
3.這里的彈出框默認值不用管,只要把下面的Inherit global site-packages選上,第三方包就出現了
4.編譯的時候右上角會出現對應的文件名選項,點擊Edit Configuration選擇對應的環境即可
以下是配置好之后的代碼
邏輯代碼
import pymysqlconfig = {'host':'192.168.0.61','port':3306,'user':'root','password':'mikejing','db':'python','charset':'utf8' } # 鏈接打開數據庫 db = pymysql.connect(**config)# 使用cousor() 創建一個游標對象 cursor cursor = db.cursor()# 使用excute執行sql語句 cursor.execute("SELECT VERSION()")# 使用fetchone獲取單條數據 data = cursor.fetchone() print("Database version:%s"%data)# sql = "insert into students (name) values('握草')" # sql = "update students set name='框要是' where id=12" # sql = "delete from students where id=12" # data = input("請輸入姓名:") # sql = "insert into students (name) values(%s)" # cursor.execute(sql, data)sql = "select * from students where id=13" cursor.execute(sql) info = cursor.fetchone() print(info)sql = "select * from students" cursor.execute(sql) info1 = cursor.fetchall() print(info1)try:cursor.execute("show tables") except Exception as result:print(result)print(cursor.fetchall())name =input("請輸入修改后的名字:") ids = input("請輸入修改用戶ID:") params = [name,ids] sql = "update students set name=%s where id=%s" cursor.execute(sql,params)# 默認開啟事務,需要提交 db.commit() cursor.close() # 關閉數據庫 db.close()面向對象封裝
對象
import pymysqlclass MysqlHelper(object):def __init__(self,host, port, user, password, db, charset='utf8'):self.host = hostself.port = portself.user = userself.password = passwordself.db = dbself.charset = charsetdef connect(self):self.con = pymysql.connect(host=self.host,port=self.port,user=self.user,password=self.password,db=self.db,charset=self.charset)self.cursor = self.con.cursor()def dealloc(self):self.con.close()self.cursor.close()def cud(self, sql, params):try:self.connect()self.cursor.execute(sql,params)self.con.commit()self.dealloc()except Exception as result:print(result)def watch(self, sql, params=[]):try:self.connect()self.cursor.execute(sql,params)result = self.cursor.fetchall()self.con.commitself.dealloc()return resultexcept Exception as result:print("error:%s"%result)使用
import MysqlHelperhelper = MysqlHelper.MysqlHelper('192.168.0.61', 3306, 'root', 'mikejing', 'python')name = input("請輸入修改后的名字:") ids = input("請輸入需要修改的用戶id:") params = (name, ids) sql = "update students set name=%s where id=%s"# 或者直接憑借 # sql = "update students set name=%s where id=%s"%(name, ids)helper.cud(sql, params)sql = "select * from students where id >20" result = helper.watch(sql) print(result)/Users/mintou/venv/bin/python /Users/mintou/Desktop/PYCharm/tPython.py 請輸入修改后的名字:29歲翻倍 請輸入需要修改的用戶id:30 ((24, 'hehehe', b'\x00', datetime.datetime(1990, 1, 1, 0, 0), b'\x00', 100, 'cixi', 'www.ads.com'), (25, '我是神e', b'\x00', datetime.datetime(1990, 1, 1, 0, 0), b'\x00', 100, 'cixi', 'www.ads.com'), (26, 'iOS大神', b'\x00', datetime.datetime(1990, 1, 1, 0, 0), b'\x00', 100, 'cixi', 'www.ads.com'), (27, '宓珂璟', b'\x01', None, b'\x00', None, None, None), (28, 'python大神', b'\x01', None, b'\x00', None, None, None), (30, '29歲翻倍', b'\x01', None, b'\x00', None, None, None))Process finished with exit code 0登錄Demo
還是用上面的MysqlHelper工具 用sha1試試
正常登錄是RSA,用戶在客戶端輸入密碼,通過公鑰加密給后臺,后臺私鑰解密,加鹽之后然后AES,接著存入數據庫,就是注冊
下次登錄的時候,輸入用戶名密碼,輸入密碼,公鑰加密,后臺私鑰解密,然后根據用戶名去數據庫select,匹配上就登錄成功
import MysqlHelper import hashlibhelper = MysqlHelper.MysqlHelper('192.168.0.61', 3306, 'root', 'mikejing', 'python')def sha1Operation(pwd):hash_pwd = pwd.encode("utf-8")hashTool = hashlib.sha1()hashTool.update(hash_pwd)return hashTool.hexdigest()print("注冊用戶密碼") name = input("name:") pwd = input("pwd:") parmes = (name,sha1Operation(pwd)) sql = "insert into userinofs values(0,%s,%s)" helper.cud(sql, parmes)print("*"*50+"注冊成功" + "*"*50)while True:print("登錄")name = input("name:")pwd = input("pwd:")parames = (name)sql = "select pwd from userinofs where username = %s"result = helper.watch(sql, parames)if len(result) == 0:print("用戶名不存在")elif result[0][0] == sha1Operation(pwd):print("登錄成功")break;else:print("密碼錯誤")?
?
參考文章
Python3各種模塊安裝(比如Mysql)
Mysql安裝初始化
find命令
總結
以上是生活随笔為你收集整理的Mac操作数据库Mysql知识点备忘录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 贪吃蛇小游戏(c)
- 下一篇: linux cmake编译源码,linu