数据库常见相关问题
1.SQL中in有什么作用?NOT IN呢?
exists : 強調的是是否返回結果集,不要求知道返回什么, 比如:
? select name from student where sex = 'm' and mark exists(select 1 from grade where ...) ,只要
exists引導的子句有結果集返回,那么exists這個條件就算成立了,大家注意返回的字段始終為1,如果改成“select?2 from grade where ...”,那么返回的字段就是2,這個數字沒有意義。所以exists子句不在乎返回什么,而是在乎是不是有結果集返回。
而 exists 與 in 最大的區別在于 in引導的子句只能返回一個字段,比如:
? select name from student where sex = 'm' and mark in (select 1,2,3 from grade where ...)??
,in子句返回了三個字段,這是不正確的,exists子句是允許的,但in只允許有一個字段返回,在1,2,3中隨便去了兩個字段即可。
而not exists 和not in 分別是exists 和in 的 對立面。
exists (sql 返回結果集為真)??
not exists (sql 不返回結果集為真)
2.子查詢中exists/ALL/ANY有什么區別?如何使用?
in,exists
in表示值是否存在子查詢結果集中
select * from A where name in(select name from B)?
exists是表示子查詢是否返回結果,而不管返回的具體內容。
select *from A where exists( select 1 from B where name='liu');
?
in是“=any的簡寫”;
not in是“<>all”的簡寫
?
any是表示子查詢結果中任意一個,all表示子查詢結果中的所有。
>any表示只要大于子查詢結果中的任一個,表達式就成立,=any表示等于子查詢中的任一個,相當于in.
>all表示要大于子查詢結果中的所有,才會返回true, ?not in 相當于“<>all”.
?
當ALL、ANY或SOME操作符與"="比較操作符配合使用時,子查詢可以是一個數據表子查詢。此時,你需要使用一個數據行構造器來提供與子查詢所返回的數據行進行比較的比較值。
eg:select *from A where (name,num)=any(select name1,num1 from Bwhere name='john');
?
in在子查詢不返回數據的時候,為false,子查詢結果中有null的時候,null不會用于比較。
any 同樣在子查詢不返回數據的時候,為false,子查詢結果中有null的時候,null不會用于比較。
all在子查詢不返回數據的時候,為true,子查詢結果中有null的時候,不會返回數據。
not in 或not exists來代替.
not in 不等于<>any,相當于<>all,
<>any是只要不等于其中的任意一個,就成立
1.where與having有什么作用?有什么區別?在聯表時使用on和使用where在執行效果和順序上會不會有區別?
sql語句的執行過程是:from-->where-->group by -->having --- >order by --> select; ?ON 、WHERE、HAVING都能通過限制條件篩選數據,但他們的使用及其不同。下面我們來分析三者之間的區別。
1.??????ON 和WHERE
??????? 所有的查詢都回產生一個中間臨時報表,查詢結果就是從返回臨時報表中得到。ON和WHERE后面所跟限制條件的區別,主要與限制條件起作用的時機有關,ON根據限制條件對數據庫記錄進行過濾,然后生產臨時表;而WHERE是在臨時表生產之后,根據限制條件從臨時表中篩選結果。
???????????因為以上原因,ON和WHERE的區別主要有下:
1)?返回結果:在左外(右外)連接中,ON會返回左表(右表)中的所有記錄;而WHERE中,此時相當于inner join,只會返回滿足條件的記錄(因為是從臨時表中篩選,會過濾掉不滿足條件的)。
2)?速度:因為ON限制條件發生時間較早,臨時表的數據集要小,因此ON的性能要優于WHERE。
2.??????HAVING和WHERE
?????????HAVING和WHERE的區別也是與限制條件起作用時機有關,HAVING是在聚集函數計算結果出來之后篩選結果,查詢結果只返回符合條件的分組,HAVING不能單獨出現,只能出現在GROUP BY子句中。;而WHERE是在計算之前篩選結果,如果聚集函數使用WHERE,那么聚集函數只計算滿足WHERE子句限制條件的數據,例如:
1. SELECT?COUNT(id)?FROM?db_equip?WHERE?tb_equip_type?=?‘2’;??
???????????Count計算的結果是首先篩選設備類型為2的的設備,然后統計設備類型為2類型的數量。
?????? 在使用和功能上,HAVING和WHERE有以下區別:
1)??HAVING不能單獨出現,只能出現在GROUP BY子句之中;WHERE即可以和SELECT等其他子句搭配使用,也可以和GROUP BY子句搭配使用,WHERE的優先級要高于聚合函數高于HAVING。
2)?因為WHERE在聚集函數之前篩選數據,HAVING在計算之后篩選分組,因此WHERE的查詢速度要比HAVING的查詢速度快。
3.??????總結
??????? ON、WHERE、HAVING的主要差別是其子句中限制條件起作用時機引起的,ON是在生產臨時表之前根據條件篩選記錄,WHERE是從生產的臨時表中篩選數據,而HAVING是對臨時表中滿足條件的數據,進行計算分組之后,通過HAVING限制語句篩選分組,返回結果是滿足HAVING子句限制的分組。SQL語句的聚合函數有哪些?
1. AVG? 返回指定組中的平均值,空值被忽略。例:select? prd_no,avg(qty) from sales group by prd_no2. COUNT? 返回指定組中項目的數量。例:select? count(prd_no) from sales 3. MAX? 返回指定數據的最大值。例:select? prd_no,max(qty) from sales group by prd_no 4. MIN? 返回指定數據的最小值。例:select? prd_no,min(qty) from sales group by prd_no5. SUM? 返回指定數據的和,只能用于數字列,空值被忽略。例:select? prd_no,sum(qty) from sales group by prd_no6. COUNT_BIG? 返回指定組中的項目數量,與COUNT函數不同的是COUNT_BIG返回bigint值,而COUNT返回的是int值。例:select? count_big(prd_no) from sales7. GROUPING? 產生一個附加的列,當用CUBE或ROLLUP運算符添加行時,輸出值為1.當所添加的行不是由CUBE或ROLLUP產生時,輸出值為0.例:select? prd_no,sum(qty),grouping(prd_no) from sales group by prd_no with rollup8. BINARY_CHECKSUM? 返回對表中的行或表達式列表計算的二進制校驗值,用于檢測表中行的更改。例:select? prd_no,binary_checksum(qty) from sales group by prd_no9. CHECKSUM_AGG? 返回指定數據的校驗值,空值被忽略。例:select? prd_no,checksum_agg(binary_checksum(*)) from sales group by prd_no10. CHECKSUM? 返回在表的行上或在表達式列表上計算的校驗值,用于生成哈希索引。11. STDEV? 返回給定表達式中所有值的統計標準偏差。例:select? stdev(prd_no) from sales12. STDEVP? 返回給定表達式中的所有值的填充統計標準偏差。例:select? stdevp(prd_no) from sales13. VAR? 返回給定表達式中所有值的統計方差。例:select? var(prd_no) from sales14. VARP? 返回給定表達式中所有值的填充的統計方差。例:select? varp(prd_no) from salesStatement和PreparedStatement的區別
1、 PreparedStatement接口繼承Statement, PreparedStatement 實例包含已編譯的 SQL 語句,所以其執行速度要快于 Statement 對象。2、作為 Statement 的子類,PreparedStatement 繼承了 Statement 的所有功能。三種方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要參數 3、在JDBC應用中,如果你已經是稍有水平開發者,你就應該始終以PreparedStatement代替 Statement.也就是說,在任何時候都不要使用Statement. 基于以下的原因: 一.代碼的可讀性和可維護性. 雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護性上來說.都比直接用Statement的代碼高很多檔次: stmt.executeUpdate("insert into tb_name(col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");//stmt是Statement對象實例 perstmt = con.prepareStatement("insert intotb_name (col1,col2,col2,col4) values (?,?,?,?)"); perstmt.setString(1,var1); perstmt.setString(2,var2); perstmt.setString(3,var3); perstmt.setString(4,var4); perstmt.executeUpdate(); //prestmt是 PreparedStatement 對象實例 不用我多說,對于第一種方法.別說其他人去讀你的代碼,就是你自己過一段時間再去讀,都會覺得傷心. 二.PreparedStatement盡最大可能提高性能. 語句在被DB的編譯器編譯后的執行代碼被緩存下來,那么下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中(相當于一個涵數)就會得到執行.這并不是說只有一個Connection中多次執行的預編譯語句被緩存,而是對于整個DB中,只要預編譯的語句語法和緩存中匹配.那么在任何時候就可以不需要再次編譯而可以直接執行.而statement的語句中,即使是相同一操作,而由于每次操作的數據不同所以使整個語句相匹配的機會極小,幾乎不太可能匹配.比如: insert into tb_name (col1,col2) values('11','22'); insert into tb_name (col1,col2) values('11','23'); 即使是相同操作但因為數據內容不一樣,所以整個個語句本身不能匹配,沒有緩存語句的意義.事實是沒有數據庫會對普通語句編譯后的執行代碼緩存. 當然并不是所以預編譯語句都一定會被緩存,數據庫本身會用一種策略,比如使用頻度等因素來決定什么時候不再緩存已有的預編譯結果.以保存有更多的空間存儲新的預編譯語句. 三.最重要的一點是極大地提高了安全性. 即使到目前為止,仍有一些人連基本的惡義SQL語法都不知道. String sql = "select * from tb_name wherename= '"+varname+"' and passwd='"+varpasswd+"'"; 如果我們把[' or '1' ='1]作為varpasswd傳入進來.用戶名隨意,看看會成為什么? select * from tb_name = '隨意' and passwd = '' or '1' = '1'; 因為'1'='1'肯定成立,所以可以任何通過驗證.更有甚者: 把[';drop table tb_name;]作為varpasswd傳入進來,則: select * from tb_name = '隨意' and passwd = '';drop table tb_name;有些數據庫是不會讓你成功的,但也有很多數據庫就可以使這些語句得到執行. 而如果你使用預編譯語句.你傳入的任何內容就不會和原來的語句發生任何匹配的關系.只要全使用預編譯語句,你就用不著對傳入的數據做任何過慮.而如果使用普通的statement,有可能要對drop,;等做費盡心機的判斷和過慮.
總結
- 上一篇: Ruby-Metasploit的核心
- 下一篇: BugkuCTF-Reverse题Eas