文章目錄
- 問題 1:表別名
- 問題 2:列別名
- 總結
大家好,我是只談技術不剪發的 Tony 老師,最近有個同學問了我一個有關 SQL 陳述句中使用別名的問題,這是他在面試中碰到的實際問題,在這里分享給大家,如果覺得文章對你有用,歡迎評論📝、點贊👍、推薦🎁
以下內容在 MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite 資料庫中進行了驗證,不過應該也適用于其他資料庫管理系統,歡迎大家補充,
問題 1:表別名
假如存在以下兩個表 t1 和 t2,以及示例資料:
CREATE TABLE t1(id int, name varchar(10));
INSERT INTO t1 VALUES (1, 'SQL');
CREATE TABLE t2(id int, name varchar(10));
INSERT INTO t2 VALUES (1, 'Alias');
其中,t1 和 t2 都有兩個欄位:id 和 name;每個表中存在一條記錄,name 欄位的值不同,
請問,下面陳述句的查詢結果是什么?
SELECT t1.id, t1.name
FROM t1 t
CROSS JOIN t2 t1;
查詢本身非常簡單,就是 t1 和 t2 進行連接查詢,需要注意的是查詢中 t1 定義了一個別名 t,t2 定義了一個別名 t1;那么在 SELECT 串列中的 t1 到底參考的是表 t1,還是別名 t1(也就是表 t2)呢?
如果了解編程語言的話,應該知道對于同名的變數,區域變數優先級比全域變數高;也就是說,作用域或者生命周期越小的變數在有效范圍內優先級越高,即使不了解其他編程語言,也不難理解這個規則;因為一方面這比較復合我們的正常邏輯,另一方面不使用這個規則的話反而會引起問題,
這個規則同樣適用于 SQL,別名(Alias)只在當前陳述句中有效,表名是一個持久化的物件識別符號,因此,上面的查詢陳述句最侄訓傳了 t2 中的 id 和 name:
id|name |
--|-----|
1|Alias|
問題 2:列別名
假如存在以下表 t3 和示例資料:
CREATE TABLE t3(id int);
INSERT INTO t3 VALUES (0);
INSERT INTO t3 VALUES (1);
INSERT INTO t3 VALUES (2);
請問,下面陳述句的查詢結果是什么?
SELECT -id AS id
FROM t3
ORDER BY id;
查詢回傳了 id 欄位的相反數,同時給它指定了一個和欄位名相同的別名 id,最后在 ORDER BY 子句中指定按照 id 進行排序,
問題的關鍵在于排序使用的 id 是欄位名還是別名,這里還涉及一個問題就是 SQL 子句的執行順序,SELECT 子句在 ORDER BY 子句之前執行,也就是說先有列別名 id,然后再進行排序操作,按照上面分析的識別符號優先級,排序使用的是別名 id,查詢的結果如下:
id|
--|
-2|
-1|
0|
回傳的結果按照升序排序顯示,相當于以下子查詢:
SELECT id
FROM (SELECT -id AS id
FROM t3
) t3
ORDER BY id;
id|
--|
-2|
-1|
0|
如果去掉查詢陳述句中的別名參考,按照 id 欄位進行排序的結果如下:
SELECT -id
FROM t3
ORDER BY id;
-id|
---|
0|
-1|
-2|
回傳的結果按照降序排序顯示,相當于以下子查詢:
SELECT -id AS id
FROM (SELECT id
FROM t3
ORDER BY id) t3;
id|
--|
0|
-1|
-2|
總結
SQL 和其他編程語言一樣,作用域或者生命周期越小的識別符號在有效范圍內的優先級越高,
最后,給大家留下一個思考問題,對于 MySQL、PostgreSQL 以及 SQLite,創建一個臨時表 t1:
CREATE TEMPORARY TABLE t1(id int, name varchar(10));
INSERT INTO t1 VALUES (1, 'TEMP');
下面查詢陳述句的結果是什么?
SELECT * FROM t1;
對于 Oracle 而言,不允許臨時表和普通表的名字相同;對于 SQL Server 而言,臨時表必須以井號(#)開頭;所以它們不存在上面的問題,
CSDN認證博客專家
資料庫架構師
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/169858.html
標籤:其他
上一篇:MySql領域經典之作,“不敢自詡為MySql專家,豈敢錯過這本神書”
下一篇:超級簡單的sql入門(一)
