mysql-logo.gif (3082 bytes)MySQL中文參考手冊

譯者:晏子 (clyan@sohu.com
GB 碼主頁:http://linuxdb.yeah.net

Big5 轉碼者:statue (statue@bbs.yzu.edu.tw
詞彙轉換:彭武興 (wilson@mailbox.com.tw)
Big5 碼主頁: http://cnpa.yzu.edu.tw/~cfc/docs/mysqldoc_big5/manual_toc.html
Big5 碼分站: http://php.wilson.gs/mysqldoc/big5/manual_toc.html


第一章, 前一章, 下一章, 最後一章目錄.


18 問題和常見錯誤

18.1 如果MySQL總是崩潰怎麼辦

所有MySQL在發布它們之前,在許多平台上被測試。這並不意味著在MySQL中沒有任何錯誤,但是如果有錯誤,它們是很少的並且很能難發現。如果你有一個問題並且如果你嘗試找出究竟是什麼摧毀了你的系統,它將總是有幫助的,因為你將有一個更好機會使得它被快速修復。

首先你應該試著找出問題mysqld背景執行程式是否死掉或你的問題是否與你的客戶有關。你可以用mysqladmin version檢查你的mysqld伺服器正常執行了多長時間,如果mysqld死了,你可以在文件“mysql-data-directory/'hostname'.err”中找到其原因。

因為很難知道一些東西為什麼崩潰,首先試著檢查為其它人工作的東西是否使你崩潰。請嘗試下列事情:

18.2 使用MySQL時的一些常見錯誤

18.2.1 MySQL server has gone away錯誤

本小節也涉及有關Lost connection to server during query的錯誤。

MySQL server has gone away錯誤最常見的原因是伺服器超時了並且關閉了連接。內定地,如果沒有事情發生,伺服器在 8個小時後關閉連接。你可在啟動mysqld時通過設置wait_timeout變數改變時間限制。

你可以通過執行mysqladmin version並且檢驗正常運行的時間來檢查MySQL還沒死掉。

如果你有一個腳本,你只須再發出查詢讓客護進行一次自動的重新連接。

在這種請下,你通常能獲得下列錯誤代碼(你得到的是OS相關的):

CR_SERVER_GONE_ERROR 客戶不能發送一個問題給伺服器。
CR_SERVER_LOST 當寫伺服器時,客戶沒有出錯,但是它沒有得到對問題的一個完整的答案(或任何答案)。

如果你向伺服器發送不正確的或太大的查詢,你也可能得到這些錯誤。如果mysqld得到一個太大或不正常的包,它認為客戶出錯了並關閉連接。如果你需要較大的查詢(例如,如果你正在處理較大的BLOB列),你可以使用-O max_allowed_packet=#選項(內定1M)啟動mysqld以增加查詢限制。多餘的內存按需分配,這樣mysqld只有在你發出較大差詢時或mysqld必須返回較大的結果行時,才使用更多的內存!

18.2.2 Can't connect to [local] MySQL server錯誤

一個MySQL客戶可以兩種不同的方式連接mysqld伺服器:Unix套接字,它通過在文件系統中的一個文件(內定“/tmp/mysqld.sock”)進行連接﹔或TCP/IP,它通過一個端口號連接。Unix套接字比TCP/IP更快,但是只有用在連接同一台計算機上的伺服器。如果你不指定主機名或如果你指定特殊的主機名localhost,使用Unix套接字。

錯誤(2002)Can't connect to ...通常意味著沒有一個MySQL伺服器運行在系統上或當試圖連接mysqld伺服器時,你正在使用一個錯誤的套接字文件或TCP/IP端口。

由檢查(使用ps)在你的伺服器上有一個名為mysqld的進程啟動!如果沒有任何mysqld程序,你應該啟動一個。見4.15.2 啟動MySQL伺服器的問題

如果一個mysqld程序正在運行,你可以通過嘗試這些不同的連接來檢查伺服器(當然,端口號和套接字路徑名可能在你的安裝中是不同的):

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h 'ip for your host' version
shell> mysqladmin --socket=/tmp/mysql.sock version

注意hostname命令使用反引號“`”而非正引號“'”﹔這些導致hostname輸出(即,當前主機名)被代替進mysqladmin命令中。

這是可能造成Can't connect to local MySQL server錯誤的一些原因:

如果你得到錯誤Can't connect to MySQL server on some_hostname,你可以嘗試下列步驟找出問題是什麼:

18.2.3 Host '...' is blocked錯誤

如果你得到像這樣的一個錯誤:

Host 'hostname' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

這意味著,mysqld已經得到了大量(max_connect_errors)的主機'hostname'的在中途被中斷了的連接請求。在max_connect_errors次失敗請求後,mysqld認定出錯了(像來字一個黑客的攻擊),並且阻止該站點進一步的連接,直到某人執行命令mysqladmin flush-hosts

內定地,mysqld在10個連接錯誤後阻塞一台主機。你可以通過像這樣啟動伺服器很容易地調整它:

shell> safe_mysqld -O max_connect_errors=10000 &

注意,對給定的主機,如果得到這條錯誤消息,你應該首先檢查該主機的TCP/IP連接有沒有問題。如果你的TCP/IP連接不在運行,增加max_connect_errors變數的值對你也不會有幫助!

18.2.4 Too many connections錯誤

如果在你試土連接MySQL時,你得到錯誤Too many connections,這意味著已經有max_connections個客戶連接了mysqld伺服器。

如果你需要比內定(100)更多的連接,那麼你應該重啟mysqld,用更大的 max_connections 變數值。

注意,mysqld實際上允許(max_connections+1)個客戶連接。最後一個連接是為一個用Process權限的用戶保留的。通過不把這個權限給一般用戶(他們不應該需要它),有這個權限一個管理員可以登錄並且使用SHOW PROCESSLIST找出什麼可能出錯。見7.21 SHOW句法(得到表,列的資訊)

18.2.5 Out of memory錯誤

如果你發出查詢並且得到類似於下面的錯誤:

mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory

注意,錯誤指向了MySQL戶mysql。這個錯誤的原因很簡單,客戶沒有足夠的內存儲存全部結果。

為了修正這個問題,首先檢查你的查詢是否正確。它應該返回這麼多的行,這合理嗎?如果是這樣,你可以使用mysql --quick,它使用mysql_use_result()檢索結果集合。這將較少的負擔放在了客戶端(只是伺服器更多)。

18.2.6 Packet too large錯誤

當一個MySQL客戶或mysqld伺服器得到一個比max_allowed_packet個字節長的包,它發出一個Packet too large錯誤並終止連接。

如果你正在使用mysql客戶,你可以通過用mysql --set-variable=max_allowed_packet=8M指定一個更大的緩衝區來啟動客戶程式。

如果你正在使用不允許你指定最大包大小的其他客戶(例如 DBI),你需要在你啟動伺服器時設置包大小。你可以使用mysqld的命令行選項設置max_allowed_packet為一個更大的尺寸。例如,如果你正期望將一個全長的BLOB存入一張表中,你將需要用--set-variable=max_allowed_packet=24M選項來啟動伺服器。

 

18.2.7 The table is full錯誤

這個錯誤發生在內存臨時表變得比tmp_table_size字節大時。為了避免這個問題,你可以使用mysqld-O tmp_table_size=#選項來增加臨時表的大小,或在你發出有疑問的查詢之前使用SQL選項SQL_BIG_TABLES。見7.25 SET OPTION句法

你也可以使用--big-tables選項啟動mysqld。這與為所有查詢使用SQL_BIG_TABLES完全相同。

18.2.8 Commands out of sync in client錯誤

如果你在你的客戶代碼中得到Commands out of sync; You can't run this command now,你正在以錯誤的次序調用客戶函數!

這可能發生,例如,如果你正在使用mysql_use_result()並且在你已經調用了mysql_free_result()之前試圖執行新查詢。如果你在mysql_use_result()mysql_store_result()之間試圖執行返回數據的2個查詢,它也可能發生。

18.2.9 Ignoring user錯誤

如果你得到下列錯誤:

Found wrong password for user: 'some_user@some_host'; Ignoring user

這意味著在mysqld啟動時或在它再次裝載權限表時,它在user表中找到了一個有一個無效密碼的條目。結果,條目簡單地被權限系統忽略。

可能導致這個問題的原因和修正:

18.2.10 Table 'xxx' doesn't exist錯誤

如果你得到錯誤Table 'xxx' doesn't existCan't find file: 'xxx' (errno: 2),這意味著在當前資料庫中沒有名為xxx的表存在。

注意,因為MySQL使用目錄和文件儲存資料庫和表,資料庫和表名件是區分大小寫的!(在Win32上,資料庫和表名不是區分大小寫的,但是在查詢中對所有表的引用必須使用相同的大小寫!)

你可以用SHOW TABLES檢查你在當前資料庫中有哪個表。見7.21 SHOW句法(得到表、列的資訊)

18.3 MySQL怎樣處理一個溢出的磁碟

當出現一個磁碟溢出的情況時,MySQL做下列事情:

為了緩和這個問題,你可以采取下列行動:

18.4 如何從一個文本文件運行SQL命令

一般地,mysql客戶被交互性地使用,像這樣:

shell> mysql database

然而,也可以把你的SQL命令放在一個文件中並且告訴mysql從該文件讀取其輸入。要想這樣做,創造一個文本文件“text_file”,它包含你想要執行的命令。然後如下那樣調用mysql

shell> mysql database < text_file

你也能啟動有一個USE db_name語句的文本文件。在這種情況下,在命令行上指定資料庫名是不必要的:

shell> mysql < text_file
12.1 不同的MySQL程式概述

18.5 MySQL在哪兒儲存臨時文件

MySQL使用TMPDIR環境變數的值作為儲存臨時文件的目錄的路徑名。如果你沒有設置TMPDIRMySQL使用系統內定值,它通常是“/tmp”“/usr/tmp”。如果包含你的臨時文件目錄的文件系統太小,你應該編輯safe_mysqld設定TMPDIR指向你有足夠空間的一個文件系統!你也可以使用mysqld的--tmpdir選項目設置臨時目錄。

MySQL以“隱含文件”創建所有臨時文件。這保証了如果mysqld被終止,臨時文件也將被刪除。使用隱含文件的缺點是你將看不到一個大的臨時文件填滿了臨時文件目錄所在的文件系統。

當排序(ORDER BYGROUP BY)時,MySQL通常使用一個或兩個臨時文件。最大磁碟空間需求是:

(儲存東西的長度 + sizeof (資料庫指針))
* 匹配的行數
* 2

sizeof(資料庫指針)通常是4,但是在未來對確實很大的表可能增加。

對一些SELECT查詢,MySQL也創建臨時SQL表。這些沒被隱含且有“SQL_*”格式的名字。

ALTER TABLEOPTIMIZE TABLE在原資料庫表的同一個目錄中創建一張臨時表。

18.6 怎樣保護“/tmp/mysql.sock ”不被刪除

如果你有這個問題,事實上任何人可以刪除MySQL通訊套接字“/tmp/mysql.sock”,在Unix的大多數版本上,你能通過為其設置sticky(t)位來保護你的“/tmp”文件系統。作為root登錄並且做下列事情:

shell> chmod +t /tmp

這將保護你的“/tmp”文件系統使得文件僅能由他們的所有者或超級用戶(root)刪除。

你能執行ls -ld /tmp檢查sticky位是否被設置,如果最後一位許可位是t,該位被設置了。

18.7 Access denied錯誤

6.6 權限系統如何工作。並且特別要看6.13 引起Access denied錯誤的原因

18.8 怎樣作為一個一般用戶運行MySQL

MySQL伺服器mysqld能被任何用戶啟動並運行。為了將mysqld改由Unix用戶user_name來運行,你必須做下列事情:

  1. 如果它正在運行,停止伺服器(使用mysqladmin shutdown)。
  2. 改變資料庫目錄和文件以便user_name有權限讀和寫文件(你可能需要作為Unix的root用戶才能做到):
    shell> chown -R user_name /path/to/mysql/datadir
    

    如果在MySQL數據目錄中的目錄或文件是符號鏈接,你也將需要順著那些鏈接並改變他們指向的目錄和文件。chown -R不能跟隨符號鏈接。

  3. user_name用戶啟動伺服器,或如果你正在使用MySQL 3.22或以後版本,以Unix root用戶啟動mysqld並使用--user=user_name選項,mysqld將在接受任何連接之前切換到以Unix user_name用戶運行。
  4. 如果在系統被重新啟動時,你使用mysql.server腳本啟動mysqld,你應該編輯mysql.serversu以用戶user_name運行mysqld,或使用--user選項調用mysqld。(不改變safe_mysqld是必要的。)

現在,你的mysqld進程應該正在作為Unix用戶user_name運行,並運行完好。盡管有一件事情沒有變化:權限表的內容。內定 地(就在運行了腳本mysql_install_db安裝的權限表後),MySQL用戶root是唯一有存取mysql資料庫或創建或拋棄資料庫權限的用戶。除非你改變了那些權限,否則他們仍然保持。當你作為一個Unix用戶而不是root登錄時,這不應該阻止你作為MySQL root用戶來存取MySQL﹔只要為客戶程式指定-u root的選項。

注意通過在命令行上提供-u root,作為root存取MySQL,與作為Unix root用戶或其他Unix用戶運行MySQL沒有關系MySQL的存取權限和用戶名與Unix用戶名字是完全分開的。唯一與Unix用戶名有關的是,如果當你調用一個客戶程式時,你不提供一個-u選項,客戶將試圖使用你的Unix登錄名作為你的MySQL用戶名進行連接。

如果你的Unix機器本身不安全,你可能應該至少在存取表中為MySQL root用戶放上一個密碼。否則,在那台機器上有一個帳號的任何用戶能運行mysql -u root db_name並且做他喜歡做的任何事情。

18.9 怎樣重新設置一個忘記的密碼

如果你忘記了MySQLroot用戶的密碼,你可以用下列程序恢復它。

  1. 通過發送一個kill(不是kill -9)到mysqld伺服器來關閉mysqld伺服器。pid 被保存在一個.pid文件中,通常在MySQL資料庫目錄中:
    kill `cat /mysql-data-directory/hostname.pid`
    

    你必須是一個UNIX root用戶或運行伺服器的相同用戶做這個。

  2. 使用--skip-grant-tables選項重啟mysqld
  3. mysql -h hostname mysql連接mysqld伺服器並且用一條GRANT命令改變密碼。見7.26 GRANTREVOKE句法。你也可以用mysqladmin -h hostname -u user password 'new password' 進行。
  4. mysqladmin -h hostname flush-privileges或用SQL命令FLUSH PRIVILEGES來裝載權限表。

18.10 文件許可權限問題

如果你有與文件許可有關的問題,例如,如果當你創建一張表時,mysql發出下列錯誤消息:

ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13) 

那麼可能是在mysqld啟動時,環境變數UMASK可能設置不正確。內定的umask值是0660。你可以如下啟動safe_mysqld改變其行為:

shell> UMASK=384  # = 600 in octal
shell> export UMASK
shell> /path/to/safe_mysqld &

18.11 文件沒找到

如果你從MySQL得到ERROR '...' not found (errno: 23), Can't open file: ... (errno: 24)或任何其他有errno 23errno 24的錯誤,它意味著,你沒有為MySQL分配足夠的文件描述符。你能使用perror實用程式得到錯誤號含義是什麼的描述:

shell> perror 23
File table overflow
shell> perror 24
Too many open files

這裡的問題是mysqld正在試圖同時保持打開太多的文件。你也可以告訴mysqld一次不打開那麼多的文件,或增加mysqld可得到的文件描述符數量。

為了告訴mysqld一次保持打開更少的文件,你可以通過使用safe_mysqld-O table_cache=32選項(內定值是64)使表緩沖更小。減小max_connections值也將減少打開文件的數量(內定值是90)。

要想改變mysqld可用的文件描述符數量,修改safe_mysqld腳本。腳本中有一條注釋了的行ulimit -n 256。你可以刪除'#'字符來去掉該行的注釋,並且改變數字256改變為mysqld可用的文件描述符的數量。

ulimit能增加文件描述符的數量,但是只能到作業系統強加的限制。如果你需要增加每個進程可用的文件描述符數量的OS限制,參見你的作業系統文檔。

注意,如果你運行tcsh外殼,ulimit將不工作!當你請求當前限制時,tcsh也將報告不正確的值!在這種情況下,你應該用sh啟動safe_mysqld

18.12 使用DATE列的問題

一個DATE值的格式是'YYYY-MM-DD'。根據ANSI SQL,不允許其他格式。你應該在UPDATE表達式和SELECT語句的WHERE子句中使用這個格式。例如:

mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';

為了方便,如果日期用在數字上下文,MySQL自動變換一個日期到一個數字(並且反過來也如此)。當更新時和將一個日期與TIMESTAMPDATEDATETIME列比較的一個WHERE子句中,也是足夠靈活以允許一種“寬鬆”的字符串格式。(寬鬆格式意味著任何標點字符用作在部件之間的分割符。例如,'1998-08-15''1998#08#15'是等價的。)MySQL也能變換不包含分割符的一個字符串(例如 '19980815'),如果它作為一個日期說得通。

特殊日期'0000-00-00'可以作為'0000-00-00'被儲存和檢索當通過MyODBC使用一個'0000-00-00'日期時,在MyODBC 2.50.12和以上版本,它將自動被轉換為NULL,因為ODBC不能處理這種日期。

因為MySQL實行了上述的變換,下列語句可以工作:

mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');

mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT mod(idate,100) FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';

然而,下列將不工作:

mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;

STRCMP()是字符串函數,因此它將idate轉換為一個字符串並且實施字符串比較。它不將'19970505'轉換為一個日期並實施日期比較。

注意,MySQL不檢查日期是否正確。如果你儲存一個不正確的日期,例如'1998-2-31',錯誤的日期將被儲存。如果日期不能被變換到任何合理的值,在DATE字段中儲存一個0。這主要是一個速度問題並且我們認為檢查日期是應用程式的責任,而不伺服器。

18.13 時區問題

如果你有一個問題,SELECT NOW()以GMT時間返回值而不是你的本地時間,你必須設定TZ環境變數為你的當前時區。這應該在伺服器運行的環境進行,例如在safe_mysqldmysql.server中。

18.14 在搜索中的大小寫敏感性

內定地,MySQL搜索是大小寫不敏感的(盡管有一些字符集從來不是忽略大小寫的,例如捷克語)。這意味著,如果你用col_name LIKE 'a%'搜尋,你將得到所有以Aa開始的列值。如果你想要使這個搜索大小寫敏感,使用像INDEX(col_name, "A")=0檢查一個前綴。或如果列值必須確切是"A",使用STRCMP(col_name, "A") = 0

簡單的比較操作(>=、>、= 、< 、<=、排序和聚合)是基於每個字符的“排序值”。有同樣排序值的字符(像E,e和'e)被視為相同的字符!

LIKE比較在每個字符的大寫值上進行(E==e 但是E<>'e)。

如果你想要一個列總是被當作大小寫敏感的方式,聲明它為BINARY。見7.7 CREATE TABLE句法

如果你使用以所謂的big5編碼的中文數據,你要使所有的字符列是BINARY,它可行,是因為big5編碼字符的排序順序基於 ASCII代碼的順序。

18.15 NULL值問題

NULL值的概念是造成SQL的新手的混淆的普遍原因,他們經常認為NULL是和一個空字符串''的一樣的東西。不是這樣的!例如,下列語句是完全不同的:

mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ("");

兩個語句把值插入到phone列,但是第一個插入一個NULL值而第二個插入一個空字符串。第一個的含義可以認為是“電話號碼不知道”,而第二個則可意味著“她沒有電話”。

在SQL中,NULL值在於任何其他值甚至NULL值比較時總是假的(FALSE)。包含NULL的一個表達式總是產生一個NULL值,除非在包含在表達式中的運算符和函數的文檔中指出。在下列例子,所有的列返回NULL

mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);

如果你想要尋找值是NULL的列,你不能使用=NULL測試。下列語句不返回任何行,因為對任何表達式,expr = NULL是假的:

mysql> SELECT * FROM my_table WHERE phone = NULL;

要想尋找NULL值,你必須使用IS NULL測試。下例顯示如何找出NULL電話號碼和空的電話號碼:

mysql> SELECT * FROM my_table WHERE phone IS NULL;
mysql> SELECT * FROM my_table WHERE phone = "";

MySQL中,就像很多其他的SQL伺服器一樣,你不能索引可以有NULL值的列。你必須聲明這樣的列為NOT NULL,而且,你不能插入NULL到索引的列中。

當用LOAD DATA INFILE讀取數據時,空列用''更新。如果你想要在一個列中有NULL值,你應該在文本文件中使用\N。字面上的詞'NULL'也可以在某些情形下使用。見7.16 LOAD DATA INFILE句法

當使用ORDER BY時,首先呈現NULL值。如果你用DESC以降序排序,NULL值最後顯示。當使用GROUP BY時,所有的NULL值被認為是相等的。

為了有助於NULL的處理,你能使用IS NULLIS NOT NULL運算符和IFNULL()函數。

對某些列類型,NULL值被特殊地處理。如果你將NULL插入表的第一個TIMESTAMP列,則插入當前的日期和時間。如果你將NULL插入一個AUTO_INCREMENT列,則插入順序中的下一個數字。

 

18.16 alias問題

你可以在GROUP BYORDER BY或在HAVING部分中使用別名引用列。別名也可以用來為列取一個更好點的名字:

SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
SELECT id AS "Customer identity" FROM table_name;

注意,你的 ANSI SQL 不允許你在一個WHERE子句中引用一個別名。這是因為在WHERE代碼被執行時,列值還可能沒有終結。例如下列查詢是不合法

SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;

WHERE語句被執行以確定哪些行應該包括GROUP BY部分中,而HAVING用來決定應該只用結果集合中的哪些行。

18.17 從關聯的表中刪除行

因為MySQL不支援子選擇或在DELETE語句中使用多個表,你應該使用下列方法從2個關聯的表中刪除行:

  1. 在主表中基於某個WHERE條件SELECT行。
  2. 在主表中基於相同的條件DELETE行。
  3. DELETE FROM related_table WHERE related_column IN (selected_rows)

如果在related_column查詢中的字符的全部數量超過1,048,576(內定值max_allowed_packet),你應該分成更小的部分並且執行多個DELETE語句。如果related_column是一個索引,你每次只刪除100-1000個related_column id將可能使得DELETE最快。如果related_column不是一個索引,速度與IN子句中參數的數量無關。

18.18 解決沒有匹配行的問題

如果你有一個複雜的查詢,涉及多個表,但沒有返回任何行,你應該使用下列程序查找你的詢問有什麼不對:

  1. EXPLAIN測試查詢並且檢查你是否能找出顯然是錯誤的一些東西。見7.22 EXPLAIN句法(得到關於一個SELECT的資訊)
  2. 僅選擇那些在WHERE子句中使用的字段。
  3. 一次從查詢中刪除一個表,直到它返回一些行。如果表很大,對查詢使用LIMIT 10是一個好主意。
  4. 對應該已經匹配一行的列做一個SELECT,針對從詢問中做後被刪除的表。
  5. 如果你將FLOATDOUBLE列與有小數的數字進行比較,你不能使用=!。這個問題在大多數計算機語言是常見的,因為浮點值不是準確的值。
    mysql> SELECT * FROM table_name WHERE float_column=3.5;
       ->
    mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
    

    在大多數情況下,將FLOAT改成一個DOUBLE將修正它!

  6. 如果你仍然不能發現錯誤是什麼,創建一個最小的可運行mysql test < query.sql的測試來顯示你的問題。你可以用mysqldump --quick database tables > query.sql創建一個測試文件,在一個編輯器編輯文件,刪除一些插入行(如果有太多這些語句)並且在文件末尾加入你的選擇語句。測試你仍然有問題,可以這樣做:
    shell> mysqladmin create test2
    shell> mysql test2 < query.sql
    

    使用mysqlbug的郵寄測試文件到mysql@lists.mysql.com

18.19 與ALTER TABLE有關的問題

如果ALTER TABLE死於這樣一個錯誤:

Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)

問題可能是MySQL在前一個ALTER TABLE中已經崩潰並且留下了一個名為“A-xxx”“B-xxx”的老的資料庫表。在這種情況下,到MySQL數據目錄中並刪除所有名字以A-B-開始的文件。(你可以把他們移到別的地方而不是刪除他們)。

ALTER TABLE工作方式是:

如果某些改名操作出錯,MySQL試圖還原改變。如果出錯嚴重(當然,這不應該發生。),MySQL可能留下了老表為“B-xxx”但是一個簡單改名就應該恢復你的數據。

18.20 怎樣改變一張表中列的順序

SQL的要點是中抽像應用程式以避免數據儲存格式。你應該總是以你想要檢索數據的意願指定順序。例如:

SELECT col_name1, col_name2, col_name3 FROM tbl_name;

將以col_name1col_name2col_name3的順序返回列,而:

SELECT col_name1, col_name3, col_name2 FROM tbl_name; 

將以col_name1col_name3col_name2的順序返回列。

在一個應用程式中,你應該決不基於他們的位置使用SELECT * 檢索列,因為被返回的列的順序永遠不能保証﹔對你的資料庫的一個簡單改變可能導致你的應用程式相當有戲劇性地失敗。

不管怎樣,如果你想要改變列的順序,你可以這樣做:

  1. 以正確的列順序創建一張新表。
  2. 執行INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
  3. 刪除或改名old_table
  4. ALTER TABLE new_table RENAME old_table

首先, 先前, 下一個, 最終部分,目錄.