學習MySQL(下)
具體實例
22、MySQL ALTER命令
當我們需要修改數據表名或者修改數據表字段時,就需要使用到MySQL ALTER命令。
1、如果需要修改數據表的名稱,可以在 ALTER TABLE 語句中使用 RENAME 子句來實現。以下實例將數據表 old_tablename 重命名為 new_tablename:
mysql> ALTER TABLE old_tablename RENAME TO new_tablename;
2、刪除,添加或修改表字段,如下命令使用了 ALTER 命令及 DROP 子句來刪除創建表的 table_title 字段:
mysql> ALTER TABLE blog_table_test DROP table_title;
MySQL 中使用 ADD 子句來向數據表中添加列,如下實例在表 blog_table_test 中添加 table_title 字段,並定義數據類型:
mysql> ALTER TABLE blog_table_test ADD table_title INT;
修改字段類型及名稱,如下命令在ALTER命令中使用 MODIFY把字段 table_title 的類型改為 CHAR(10),可以執行以下命令:
ysql> ALTER TABLE blog_table_test MODIFY table_title CHAR(10);
使用 CHANGE 子句,在 CHANGE 關鍵字之後,緊跟著的是要修改的字段名,然後指定新字段名及類型。嘗試如下實例:
mysql> ALTER TABLE blog_table_test CHANGE oldfield newfield newtype;
3、ALTER TABLE 對 Null 值和默認值的影響,當你修改字段時,你可以指定是否包含值或者是否設置默認值。下例指定字段 table_title 為 NOT NULL 且默認值為100 。
mysql> ALTER TABLE blog_table_test
-> MODIFY table_title BIGINT NOT NULL DEFAULT 100;
也可以使用 ALTER 來修改字段的默認值,實例:
mysql> ALTER TABLE blog_table_test ALTER table_title SET DEFAULT 1000;
4、使用 ALTER 命令添加和刪除主鍵。在添加主鍵索引時,你需要確保該主鍵默認不為空(NOT NULL)。實例:
mysql> ALTER TABLE blog_table_test MODIFY table_id INT NOT NULL;
mysql> ALTER TABLE blog_table_test ADD PRIMARY KEY (table_id);
5、使用ALTER 命令添加和刪除索引,包含有四種方式來添加數據表的索引(關於索引在下面會有介紹):1、ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味著索引值必須是唯一的,且不能為NULL。2、ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次)。 3、ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出現多次。4、ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):該語句指定了索引為 FULLTEXT ,用於全文索引。
23、MySQL 索引
索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄。其分為單列索引:一個索引只包含單個列。和 組合索引:一個索引包含多個列。。
索引可以大大提高MySQL的檢索速度,當然也有缺陷,過多的使用索引將會造成濫用,會降低更新表的速度,而且建立索引會占用磁盤空間的索引文件。
1、普通索引的創建,最基本的索引,它沒有任何限制。它有以下幾種創建方式:
創建索引:
CREATE INDEX indexName ON blog_table_test(username(length));
如果是CHAR,VARCHAR類型,length可以小於字段實際長度;如果是BLOB和TEXT類型,必須指定 length。
修改表結構(添加索引):
ALTER table tableName ADD INDEX indexName(columnName)
創建表的時候直接指定:
CREATE TABLE blog_table_test(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length))
);
2、唯一索引:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:
創建索引:
CREATE UNIQUE INDEX indexName ON blog_table_test(username(length))
修改表結構:
ALTER table blog_table_test ADD UNIQUE [indexName] (username(length))
創建表的時候直接指定:
REATE TABLE blog_table_test(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
UNIQUE [indexName] (username(length))
);
3、刪除索引的語法:
DROP INDEX [indexName] ON blog_table_test;
4、顯示索引信息:
mysql> SHOW INDEX FROM table_name; \G
24、MySQL 臨時表
MySQL臨時表只在當前連接可見,如果你使用PHP腳本來創建MySQL臨時表,那每當PHP腳本執行完成後,該臨時表也會自動銷毀。若是使用MySQL客戶端程序連接MySQL數據庫服務器來創建臨時表,那麽只有在關閉客戶端程序時才會銷毀臨時表,當然也可以手動銷毀。
創建臨時表的語句與創建數據表的語句基本相同,區別只在於 cerate table 語句的中間加入 temporary 。
25、MySQL 復制表
復制表的操作步驟:1、使用 SHOW CREATE TABLE 命令獲取創建數據表(show create table tablename \g;) 語句,該語句包含了原數據表的結構,索引等。2、復制之後改變數據表的名稱,在粘貼在mysql控制臺執行,此時已經建立了一個克隆表。3、復制表的內容,可以使用 INSERT INTO ... SELECT 語句來實現。第三部的操作語句如下:
mysql> INSERT INTO new_table (runoob_id,
-> runoob_title,
-> runoob_author,
-> submission_date)
-> SELECT runoob_id,runoob_title,
-> runoob_author,submission_date
-> FROM blog_table_test;
26、MySQL 元數據
在MySQL的命令提示符中,我們可以很容易的獲取以上服務器信息。 但如果使用Perl或PHP等腳本語言,你就需要調用特定的接口函數來獲取。例如在PHP中,你可以使用 mysqli_affected_rows( ) 函數來獲取查詢語句影響的記錄數。
$result_id = mysqli_query ($conn_id, $query);
# 如果查詢失敗返回
$count = ($result_id ? mysqli_affected_rows ($conn_id) : 0);
print ("$count 條數據被影響\n");
以下實例輸出 MySQL 服務器上的所有數據庫:
<?php
$dbhost = ‘localhost:3306‘; // mysql服務器主機地址
$dbuser = ‘root‘; // mysql用戶名
$dbpass = ‘123‘; // mysql用戶名密碼
$conn = mysqli_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
die(‘連接失敗: ‘ . mysqli_error($conn));
}
// 設置編碼,防止中文亂碼
$db_list = mysqli_query($conn, ‘SHOW DATABASES‘);
while ($db = mysqli_fetch_object($db_list))
{
echo $db->Database . "
";
}
mysqli_close($conn);
?>
以下命令語句可以在 MySQL 的命令提示符使用,也可以在腳本中 使用,如PHP腳本。1、SELECT VERSION( ):服務器版本信息。2、SELECT DATABASE( ):當前數據庫名 (或者返回空)。3、SELECT USER( ):當前用戶名。4、SHOW STATUS:服務器狀態。5、SHOW VARIABLES:服務器配置變量。
27、MySQL 序列使用
MySQL序列是一組整數:1, 2, 3, ...,由於一張數據表只能有一個字段自增主鍵, 如果你想實現其他字段也實現自動增加,就可以使用MySQL序列來實現。
1、使用AUTO_INCREMENT:MySQL中最簡單使用序列的方法就是使用 MySQL AUTO_INCREMENT 來定義列。AUTO_INCREMENT定義列為自增的屬性,一般用於主鍵,數值會自動加1。
2、獲取AUTO_INCREMENT值:在MySQL的客戶端中你可以使用 SQL中的LAST_INSERT_ID( ) 函數來獲取最後的插入表中的自增列的值。而PHP 通過 mysql_insert_id ()函數來獲取執行的插入SQL語句中 AUTO_INCREMENT列的值:
mysql_query ("INSERT INTO blog_table_test (name,date,origin)
VALUES(‘moth‘,‘2001-09-14‘,‘windowsill‘)", $conn_id);
$seq = mysql_insert_id ($conn_id);
3、重置序列:如果刪除了數據表中的多條記錄,並希望對剩下數據的AUTO_INCREMENT列進行重新排列,那麽你可以通過刪除自增的列,然後重新添加來實現。 不過該操作要非常小心,如果在刪除的同時又有新記錄添加,有可能會出現數據混亂。操作如下所示:
mysql> ALTER TABLE insect DROP filed;
mysql> ALTER TABLE insect
-> ADD filed INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
-> ADD PRIMARY KEY (filed);
4、設置序列的開始值:一般情況下序列的開始值為1,但如果你需要指定一個開始值100,那我們可以通過以下語句來實現:
mysql> CREATE TABLE blog_table_test
-> (
-> table_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
-> PRIMARY KEY (table_id),
-> table_name VARCHAR(30) NOT NULL,
-> table_date DATE NOT NULL,
-> table_origin VARCHAR(30) NOT NULL
)engine=innodb auto_increment=100 charset=utf8;
或者:
mysql> ALTER TABLE t AUTO_INCREMENT = 100;
28、MySQL 處理重復數據
表中無索引及主鍵,則該表允許出現多條重復記錄,如果想設置表中字段field_one,filed_two數據不能重復,可以設置雙主鍵模式來設置數據的唯一性, 如果你設置了雙主鍵,那麽那個鍵的默認值不能為NULL,可設置為NOT NULL。例如:
CREATE TABLE blog_table_test
(
field_one CHAR(20) NOT NULL,
field_two CHAR(20) NOT NULL,
PRIMARY KEY (field_one, field_two)
);
如果我們設置了唯一索引,那麽在插入重復數據時,SQL語句將無法執行成功,並拋出錯。INSERT IGNORE INTO與INSERT INTO的區別就是INSERT IGNORE會忽略數據庫中已經存在的數據,如果數據庫沒有數據,就插入新的數據,如果有數據的話就跳過這條數據。這樣就可以保留數據庫中已經存在數據,達到在間隙中插入數據的目的。
INSERT IGNORE INTO當插入數據時,在設置了記錄的唯一性後,如果插入重復數據,將不返回錯誤,只以警告形式返回。 而REPLACE INTO into如果存在primary 或 unique相同的記錄,則先刪除掉。再插入新記錄。
另一種設置數據的唯一性方法是添加一個UNIQUE索引。
1、統計重復數據
mysql> SELECT COUNT(*) as repetitions, field_one, field_two
-> FROM table_name
-> GROUP BY field_one, field_two
-> HAVING repetitions > 1;
查詢重復的值,請執行以下操作:1、確定哪一列包含的值可能會重復。2、在列選擇列表使用COUNT(*)列出的那些列。3、在GROUP BY子句中列出的列。4、HAVING子句設置重復數大於1。
2、過濾重復數據
讀取不重復的數據可以在 SELECT 語句中使用 DISTINCT 關鍵字來過濾重復數據:
mysql> SELECT DISTINCT field_one, field_two
-> FROM blog_table_test;
也可以使用 GROUP BY 來讀取數據表中不重復的數據:
mysql> SELECT field_one, field_two
-> FROM blog_table_test
-> GROUP BY (field_one, field_two);
3、刪除重復數據
可以在數據表中添加 INDEX(索引) 和 PRIMAY KEY(主鍵)這種簡單的方法來刪除表中的重復記錄:
mysql> ALTER IGNORE TABLE blod_table_test
-> ADD PRIMARY KEY (field_one, field_two);
可以使用以下的SQL語句刪除表中的重復記錄:
mysql> CREATE TABLE blog_table SELECT field_one, field_two
-> FROM blog_table_test;
-> GROUP BY (lfield_one, field_two);
mysql> DROP TABLE blog_table_test;
mysql> ALTER TABLE blog_table RENAME TO blog_table_test;
29、MySQL 及 SQL 註入
所謂SQL註入,就是通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。我們永遠不要信任用戶的輸入,必須認定用戶輸入的數據都是不安全的,都需要對用戶輸入的數據進行過濾處理。例如下面的例子中沒有對用戶輸入進行過濾:
$name = "Qadir‘; DELETE FROM users;";
mysqli_query($conn, "SELECT * FROM users WHERE name=‘{$name}‘");
以上的註入語句中,我們沒有對 $name 的變量進行過濾,$name 中插入了我們不需要的SQL語句,將刪除 users 表中的所有數據。在PHP中的 mysqli_query() 是不允許執行多個 SQL 語句的,但是在 SQLite 和 PostgreSQL 是可以同時執行多條SQL語句的,所以我們對這些用戶的數據需要進行嚴格的驗證。
防止SQL註入,我們需要註意:1、永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式,或限制長度;對單引號和 雙"-"進行轉換等。2、永遠不要使用動態拼裝sql,可以使用參數化的sql或者直接使用存儲過程進行數據查詢存取。3、永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接。4、不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。5、應用的異常信息應該給出盡可能少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝。6、sql註入的檢測方法一般采取輔助軟件或網站平臺來檢測,軟件一般采用sql註入檢測工具jsky,網站平臺就有億思網站安全平臺檢測工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防禦SQL註入,XSS攻擊等。
1、防止SQL註入:在腳本語言,如Perl和PHP你可以對用戶輸入的數據進行轉義從而來防止SQL註入。PHP的MySQL擴展提供了mysqli_real_escape_string()函數來轉義特殊的輸入字符。例:
if (get_magic_quotes_gpc())
{
$name = stripslashes($name);
}
$name = mysqli_real_escape_string($conn, $name);
mysqli_query($conn, "SELECT * FROM users WHERE name=‘{$name}‘");
2、Like語句中的註入:ike查詢時,如果用戶輸入的值有"_"和"%",則會出現用戶本來只是想查詢"abcd_",查詢結果中卻有"abcd_"、"abcde"、"abcdf"等等;在PHP腳本中我們可以使用addcslashes()函數來處理以上情況,例:
$sub = addcslashes(mysqli_real_escape_string($conn, "%something_"), "%_");
// $sub == \%something\_
mysqli_query($conn, "SELECT * FROM messages WHERE subject LIKE ‘{$sub}%‘");
addcslashes() 函數在指定的字符前添加反斜杠。其使用的語法格式:addcslashes(string,characters)。兩個參數中 string:必需。規定要檢查的字符串。characters:可選。規定受 addcslashes() 影響的字符或字符範圍。
30、MySQL 導出數據
1、MySQL中可以使用SELECT...INTO OUTFILE語句來簡單的導出數據到文本文件上,並通過命令選項來設置數據輸出的指定格式,以下實例為導出 CSV 格式:
mysql> SELECT * FROM passwd INTO OUTFILE ‘/tmp/tutorials.txt‘
-> FIELDS TERMINATED BY ‘,‘ ENCLOSED BY ‘"‘
-> LINES TERMINATED BY ‘\r\n‘;
SELECT ... INTO OUTFILE 語句有以下屬性:1、將一個數據庫的數據寫入一個文件,使用SELECT ... INTO OUTFILE,將文件讀回數據庫,使用LOAD DATA INFILE。2、ELECT...INTO OUTFILE ‘file_name‘形式的SELECT可以把被選擇的行寫入一個文件中。該文件被創建到服務器主機上,因此您必須擁有FILE權限,才能使用此語法。3、輸出不能是一個已存在的文件。防止文件數據被篡改。4、需要有一個登陸服務器的賬號來檢索文件。否則 SELECT ... INTO OUTFILE 不會起任何作用。5、在UNIX中,該文件被創建後是可讀的,權限由MySQL服務器所擁有。
2、導出表作為原始數據:mysqldump是mysql用於轉存儲數據庫的實用程序。它主要產生一個SQL腳本,其中包含從頭重新創建數據庫所必需的命令。使用mysqldump導出數據需要使用 --tab 選項來指定導出文件指定的目錄,該目標必須是可寫的。例如將數據表 blog_table_test 導出到 /catalogname 目錄中:
$ mysqldump -u root -p --no-create-info \
--tab=/catalogname blog blog_table_test
password ******
3、導出SQL格式的數據到指定文件,如下實例:
$ mysqldump -u root -p blog blog_table_test > test.txt
password ******
如果你需要導出整個數據庫的數據,可以使用以下命令:
$ mysqldump -u root -p blog > database_test.txt
password ******
如果需要備份所有數據庫,可以使用以下命令:
$ mysqldump -u root -p --all-databases > database_test.txt
password ******
4、將數據表及數據庫拷貝至其他主機:如果你需要將數據拷貝至其他的 MySQL 服務器上, 你可以在 mysqldump 命令中指定數據庫名及數據表,如果完整備份數據庫,則無需使用特定的表名稱。
如果需要將備份的數據庫導入到MySQL服務器中,可以使用以下命令(需要確認數據庫已經創建):
$ mysql -u root -p database_name < test.txt
password *****
你也可以使用以下命令將導出的數據直接導入到遠程的服務器上,但請確保兩臺服務器是相通的,是可以相互訪問的:
$ mysqldump -u root -p database_name \
| mysql -h other-host.com database_name
31、MySQL 導入數據
1、使用 LOAD DATA 導入數據,以下實例中將從當前目錄中讀取文件 test.txt ,將該文件中的數據插入到當前數據庫的 blog_table_test 表中:
mysql> LOAD DATA LOCAL INFILE ‘test.txt‘ INTO TABLE blog_table_test;
如果指定LOCAL關鍵詞,則表明從客戶主機上按路徑讀取文件。如果沒有指定,則文件在服務器上按路徑讀取文件。
我們能明確地在LOAD DATA語句中指出列值的分隔符和行尾標記,但是默認標記是定位符和換行符
兩個命令的 FIELDS 和 LINES 子句的語法是一樣的。兩個子句都是可選的,但是如果兩個同時被指定,FIELDS 子句必須出現在 LINES 子句之前。
如果用戶指定一個 FIELDS 子句,它的子句 (TERMINATED BY、[OPTIONALLY] ENCLOSED BY 和 ESCAPED BY) 也是可選的,不過,用戶必須至少指定它們中的一個。
LOAD DATA 默認情況下是按照數據文件中列的順序插入數據的,如果數據文件中的列與插入表中的列不一致,則需要指定列的順序。例如在數據文件中的列順序是 a,b,c,但在插入表的列順序為b,c,a,則數據導入語法如下:
mysql> LOAD DATA LOCAL INFILE ‘test.txt‘
-> INTO TABLE blog_table_test (b, c, a);
2、使用 mysqlimport 導入數據:mysqlimport客戶端提供了LOAD DATA INFILEQL語句的一個命令行接口。mysqlimport的大多數選項直接對應LOAD DATA INFILE子句。
從文件 test.txt 中將數據導入到 blog_table_test 數據表中, 可以使用以下命令:
$ mysqlimport -u root -p --local database_name test.txt
password *****
ysqlimport命令可以指定選項來設置指定格式,命令語句格式如下:
$ mysqlimport -u root -p --local --fields-terminated-by=":" \
--lines-terminated-by="\r\n" database_name test.txt
password *****
mysqlimport 語句中使用 --columns 選項來設置列的順序:
$ mysqlimport -u root -p --local --columns=b,c,a \
database_name test.txt
password *****
32、註意事項
1、MySQL在Windows下數據庫名、表名、列名、別名都不區分大小寫。
2、數值類型括號後面的數字只是表示寬度而跟存儲範圍沒有關系。
3、ORDER BY,GROUP BY,DISTINCT的字段需要添加在索引的後面。
4、不使用外鍵,高並發時容易引起死鎖等問題
學習更多關於MySQL的知識請點擊:學習MySQL(上)
申明
筆者也是學習前端不久,編輯整理這篇文章的目的,一方面是為了和大家一起分享和學習,另一方面也是為了自己能更好的理解其中的內容。若是文中有什麽錯誤,歡迎大家指正批評,願與大家在問題的爭辯之中共同進步。愈激烈,愈深刻。
學習MySQL(下)