在ORACLE中,無論是永久表還是臨時表,在同一個Schema中,只能有一個表名,不會存在臨時表和永久表同名的問題。? 而在MySQL中卻不是這樣的。
在執(zhí)行MYSQL默認(rèn)建表語句時,不會去檢測當(dāng)前是否有同名的臨時表和永久表。
一、來看如下實(shí)驗(yàn):
1、先創(chuàng)建一張普通表
mysql> create table a ( a int ,b int);
Query OK, 0 rows affected (0.03 sec)
mysql> desc a;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a | int(11) | YES | | NULL | |
| b | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
2、插入測試數(shù)據(jù)
mysql> insert into a select 1,2;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into a select 3,4;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from a;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 3 | 4 |
+------+------+
2 rows in set (0.00 sec)
3、再創(chuàng)建一張同名的臨時表(注意此時并未報錯)
mysql>create temporary table a (t int);
Query OK, 0 rows affected (0.00 sec)
mysql> insert into a select 9;
Query OK, 1 row affected (0.00 sec)
Records: 1? Duplicates: 0? Warnings: 0
4、現(xiàn)在當(dāng)前會話中就存在了2張同名的a表。
那么問題來了,如果此時查詢表a的數(shù)據(jù),MYSQL返回的會是永久表的數(shù)據(jù)還是臨時表的數(shù)據(jù)呢?
繼續(xù)實(shí)驗(yàn):
mysql>select * from a;
+------+
| t? ? |
+------+
|? ? 9 |
+------+
1 row in set (0.00 sec)
mysql>desc a;
+-------+---------+------+-----+---------+-------+
| Field | Type? ? | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| t? ? | int(11) | YES? |? ? | NULL? ? |? ? ? |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
5、可見,如果此時查詢a表,那么將返回的數(shù)據(jù)將是臨時表a的數(shù)據(jù),而查詢不到永久表a的數(shù)據(jù)。
那么如何查詢表a的數(shù)據(jù)呢? ?如果當(dāng)前會話查不到,嘗試新開一個會話查詢下
新開會話查詢:
mysql> select * from a;
+------+------+
| a? ? | b? ? |
+------+------+
|? ? 1 |? ? 2 |
|? ? 3 |? ? 4 |
+------+------+
2 rows in set (0.00 sec)
二、分析:
出現(xiàn)這種情況的原因在于:
在MySQL中存在兩種臨時表 外部臨時表和內(nèi)部臨時表 。
通過CREATE TEMPORARY TABLE 創(chuàng)建的臨時表被稱為外部臨時表。
這種臨時表只對當(dāng)前會話用戶可見,當(dāng)前會話結(jié)束的時候,該臨時表會自動關(guān)閉。
這種臨時表的表名與普通表可以同名,但是會導(dǎo)致同名后普通表將對當(dāng)前會話不可見,直到臨時表被刪除。
內(nèi)部臨時表是一種特殊輕量級的臨時表,用來進(jìn)行性能優(yōu)化。這種內(nèi)部表對普通用戶來說是不可見的。
三、解決方法:
1、定制開發(fā)和運(yùn)維建表規(guī)范,采用不同表名,如所有臨時表命名必須以tmp開頭;
2、建表時統(tǒng)一采用建表參數(shù)【IF NOT EXISTS】,讓MYSQL在建表時進(jìn)行檢測是否存在同名表,有則報錯。