dosbox 伪指令dd为什么会报错_什么是SQL函数?为什么使用SQL函数可能会带来问题?...
函數(shù)在計(jì)算機(jī)語(yǔ)言的使用中貫穿始終,在 SQL 中我們也可以使用函數(shù)對(duì)檢索出來(lái)的數(shù)據(jù)進(jìn)行函數(shù)操作,比如求某列數(shù)據(jù)的平均值,或者求字符串的長(zhǎng)度等。從函數(shù)定義的角度出發(fā),我們可以將函數(shù)分成內(nèi)置函數(shù)和自定義函數(shù)。在 SQL 語(yǔ)言中,同樣也包括了內(nèi)置函數(shù)和自定義函數(shù)。內(nèi)置函數(shù)是系統(tǒng)內(nèi)置的通用函數(shù),而自定義函數(shù)是我們根據(jù)自己的需要編寫(xiě)的,下面講解的是 SQL 的內(nèi)置函數(shù)。
你需要從以下幾個(gè)方面掌握 SQL 函數(shù):
一、什么是SQL函數(shù)
當(dāng)我們學(xué)習(xí)編程語(yǔ)言的時(shí)候,也會(huì)遇到函數(shù)。函數(shù)的作用是什么呢?它可以把我們經(jīng)常使用的代碼封裝起來(lái),需要的時(shí)候直接調(diào)用即可。這樣既提高了代碼效率,又提高了可維護(hù)性。
SQL 中的函數(shù)一般是在數(shù)據(jù)上執(zhí)行的,可以很方便地轉(zhuǎn)換和處理數(shù)據(jù)。一般來(lái)說(shuō),當(dāng)我們從數(shù)據(jù)表中檢索出數(shù)據(jù)之后,就可以進(jìn)一步對(duì)這些數(shù)據(jù)進(jìn)行操作,得到更有意義的結(jié)果,比如返回指定條件的函數(shù),或者求某個(gè)字段的平均值等。
二、常用的SQL函數(shù)有哪些
SQL 提供了一些常用的內(nèi)置函數(shù),當(dāng)然你也可以自己定義 SQL 函數(shù)。SQL 的內(nèi)置函數(shù)對(duì)于不同的數(shù)據(jù)庫(kù)軟件來(lái)說(shuō)具有一定的通用性,我們可以把內(nèi)置函數(shù)分成四類:
這 4 類函數(shù)分別代表了算術(shù)處理、字符串處理、日期處理、數(shù)據(jù)類型轉(zhuǎn)換,它們是 SQL 函數(shù)常用的劃分形式,你可以思考下,為什么是這 4 個(gè)維度?
函數(shù)是對(duì)提取出來(lái)的數(shù)據(jù)進(jìn)行操作,那么數(shù)據(jù)表中字段類型的定義有哪幾種呢?
我們經(jīng)常會(huì)保存一些數(shù)值,不論是整數(shù)類型,還是浮點(diǎn)類型,實(shí)際上對(duì)應(yīng)的就是數(shù)值類型。同樣我們也會(huì)保存一些文本內(nèi)容,可能是人名,也可能是某個(gè)說(shuō)明,對(duì)應(yīng)的就是字符串類型。此外我們還需要保存時(shí)間,也就是日期類型。那么針對(duì)數(shù)值、字符串和日期類型的數(shù)據(jù),我們可以對(duì)它們分別進(jìn)行算術(shù)函數(shù)、字符串函數(shù)以及日期函數(shù)的操作。如果想要完成不同類型數(shù)據(jù)之間的轉(zhuǎn)換,就可以使用轉(zhuǎn)換函數(shù)。
三、算術(shù)函數(shù)
算術(shù)函數(shù),顧名思義就是對(duì)數(shù)值類型的字段進(jìn)行算術(shù)運(yùn)算。常用的算術(shù)函數(shù)及含義如下表所示:
這里我舉一些簡(jiǎn)單的例子,你來(lái)體會(huì)下:
SELECT ABS(-2),運(yùn)行結(jié)果為 2。 SELECT MOD(101,3),運(yùn)行結(jié)果 2。 SELECT ROUND(37.25,1),運(yùn)行結(jié)果 37.3。四、字符串函數(shù)
常用的字符串函數(shù)操作包括了字符串拼接,大小寫(xiě)轉(zhuǎn)換,求長(zhǎng)度以及字符串替換和截取等。具體的函數(shù)名稱及含義如下表所示:
這里同樣有一些簡(jiǎn)單的例子,你可以自己運(yùn)行下:
SELECT CONCAT('abc', 123),運(yùn)行結(jié)果為 abc123。 SELECT LENGTH('你好'),運(yùn)行結(jié)果為 6。 SELECT CHAR_LENGTH('你好'),運(yùn)行結(jié)果為 2。 SELECT LOWER('ABC'),運(yùn)行結(jié)果為 abc。 SELECT UPPER('abc'),運(yùn)行結(jié)果 ABC。 SELECT REPLACE('fabcd', 'abc', 123),運(yùn)行結(jié)果為 f123d。 SELECT SUBSTRING('fabcd', 1,3),運(yùn)行結(jié)果為 fab。五、日期函數(shù)
日期函數(shù)是對(duì)數(shù)據(jù)表中的日期進(jìn)行處理,常用的函數(shù)包括:
下面是一些簡(jiǎn)單的例子,你可自己運(yùn)行下:
SELECT CURRENT_DATE(),運(yùn)行結(jié)果為 2019-04-03。 SELECT CURRENT_TIME(),運(yùn)行結(jié)果為 21:26:34。 SELECT CURRENT_TIMESTAMP(),運(yùn)行結(jié)果為 2019-04-03 21:26:34。 SELECT EXTRACT(YEAR FROM '2019-04-03'),運(yùn)行結(jié)果為 2019。 SELECT DATE('2019-04-01 12:00:05'),運(yùn)行結(jié)果為 2019-04-01。這里需要注意的是,DATE 日期格式必須是 yyyy-mm-dd 的形式。如果要進(jìn)行日期比較,就要使用 DATE 函數(shù),不要直接使用日期與字符串進(jìn)行比較,我會(huì)在后面的例子中講具體的原因。
六、轉(zhuǎn)換函數(shù)
轉(zhuǎn)換函數(shù)可以轉(zhuǎn)換數(shù)據(jù)之間的類型,常用的函數(shù)如下表所示:
這兩個(gè)函數(shù)不像其他函數(shù),看一眼函數(shù)名就知道代表什么、如何使用。下面舉了這兩個(gè)函數(shù)的例子,你需要自己運(yùn)行下:
SELECT CAST(123.123 AS INT),運(yùn)行結(jié)果會(huì)報(bào)錯(cuò)。 SELECT CAST(123.123 AS DECIMAL(8,2)),運(yùn)行結(jié)果為 123.12。 SELECT COALESCE(null,1,2),運(yùn)行結(jié)果為 1。CAST 函數(shù)在轉(zhuǎn)換數(shù)據(jù)類型的時(shí)候,不會(huì)四舍五入,如果原數(shù)值有小數(shù),那么轉(zhuǎn)換為整數(shù)類型的時(shí)候就會(huì)報(bào)錯(cuò)。不過(guò)你可以指定轉(zhuǎn)化的小數(shù)類型,在 MySQL 和 SQL Server 中,你可以用DECIMAL(a,b)來(lái)指定,其中 a 代表整數(shù)部分和小數(shù)部分加起來(lái)最大的位數(shù),b 代表小數(shù)位數(shù),比如DECIMAL(8,2)代表的是精度為 8 位(整數(shù)加小數(shù)位數(shù)最多為 8 位),小數(shù)位數(shù)為 2 位的數(shù)據(jù)類型。所以SELECT CAST(123.123 AS DECIMAL(8,2))的轉(zhuǎn)換結(jié)果為 123.12。
七、用SQL函數(shù)對(duì)王者榮耀英雄數(shù)據(jù)做處理
我創(chuàng)建了一個(gè)王者榮耀英雄數(shù)據(jù)庫(kù),一共有 69 個(gè)英雄,23 個(gè)屬性值。
我們現(xiàn)在把這個(gè)文件導(dǎo)入到 MySQL 中,你可以使用 Navicat 可視化數(shù)據(jù)庫(kù)管理工具將.sql文件導(dǎo)入到數(shù)據(jù)庫(kù)中。數(shù)據(jù)表為 heros,然后使用今天學(xué)習(xí)的 SQL 函數(shù),對(duì)這個(gè)英雄數(shù)據(jù)表進(jìn)行處理。
首先顯示英雄以及他的物攻成長(zhǎng),對(duì)應(yīng)字段為attack_growth。我們讓這個(gè)字段精確到小數(shù)點(diǎn)后一位,需要使用的是算術(shù)函數(shù)里的 ROUND 函數(shù)。
SQL:SELECT name, ROUND(attack_growth,1) FROM heros代碼中,ROUND(attack_growth,1)中的attack_growth代表想要處理的數(shù)據(jù),“1”代表四舍五入的位數(shù),也就是我們這里需要精確到的位數(shù)。
運(yùn)行結(jié)果為:
假設(shè)我們想顯示英雄最大生命值的最大值,就需要用到 MAX 函數(shù)。在數(shù)據(jù)中,“最大生命值”對(duì)應(yīng)的列數(shù)為hp_max,在代碼中的格式為MAX(hp_max)。
SQL:SELECT MAX(hp_max) FROM heros運(yùn)行結(jié)果為 9328。
假如我們想要知道最大生命值最大的是哪個(gè)英雄,以及對(duì)應(yīng)的數(shù)值,就需要分成兩個(gè)步驟來(lái)處理:首先找到英雄的最大生命值的最大值,即SELECT MAX(hp_max) FROM heros,然后再篩選最大生命值等于這個(gè)最大值的英雄,如下所示。
SQL:SELECT name, hp_max FROM heros WHERE hp_max = (SELECT MAX(hp_max) FROM heros)運(yùn)行結(jié)果:
假如我們想顯示英雄的名字,以及他們的名字字?jǐn)?shù),需要用到CHAR_LENGTH函數(shù)。
SQL:SELECT CHAR_LENGTH(name), name FROM heros運(yùn)行結(jié)果為:
假如想要提取英雄上線日期(對(duì)應(yīng)字段 birthdate)的年份,只顯示有上線日期的英雄即可(有些英雄沒(méi)有上線日期的數(shù)據(jù),不需要顯示),這里我們需要使用 EXTRACT 函數(shù),提取某一個(gè)時(shí)間元素。所以我們需要篩選上線日期不為空的英雄,即WHERE birthdate isnot null,然后再顯示他們的名字和上線日期的年份,即:
SQL:SELECT name, EXTRACT(YEAR FROM birthdate) AS birthdate FROM heros WHERE birthdate或者使用如下形式:
SQL: SELECT name, YEAR(birthdate) AS birthdate FROM heros WHERE birthdate is NOT NULL運(yùn)行結(jié)果為:
假設(shè)我們需要找出在 2016 年 10 月 1 日之后上線的所有英雄。這里我們可以采用 DATE函數(shù)來(lái)判斷 birthdate 的日期是否大于 2016-10-01,即WHEREDATE(birthdate)>'2016-10-01',然后再顯示符合要求的全部字段信息,即:
SQL:SELECT * FROM heros WHERE DATE(birthdate)>'2016-10-01'需要注意的是下面這種寫(xiě)法是不安全的:
SELECT * FROM heros WHERE birthdate>'2016-10-01'因?yàn)楹芏鄷r(shí)候你無(wú)法確認(rèn) birthdate 的數(shù)據(jù)類型是字符串,還是 datetime 類型,如果你想對(duì)日期部分進(jìn)行比較,那么使用DATE(birthdate)來(lái)進(jìn)行比較是更安全的。
運(yùn)行結(jié)果為:
假設(shè)我們需要知道在 2016 年 10 月 1 日之后上線英雄的平均最大生命值、平均最大法力和最高物攻最大值。同樣我們需要先篩選日期條件,即WHERE DATE(birthdate)>'2016-10-01',然后再選擇AVG(hp_max), AVG(mp_max), MAX(attack_max)字段進(jìn)行顯示。
SQL:SELECT AVG(hp_max), AVG(mp_max), MAX(attack_max) FROM heros WHERE DATE(birthdate)>運(yùn)行結(jié)果為:
八、為什么使用SQL函數(shù)會(huì)帶來(lái)問(wèn)題
盡管 SQL 函數(shù)使用起來(lái)會(huì)很方便,但我們使用的時(shí)候還是要謹(jǐn)慎,因?yàn)槟闶褂玫暮瘮?shù)很可能在運(yùn)行環(huán)境中無(wú)法工作,這是為什么呢?
如果你學(xué)習(xí)過(guò)編程語(yǔ)言,就會(huì)知道語(yǔ)言是有不同版本的。我們?cè)谑褂?SQL 語(yǔ)言的時(shí)候,不是直接和這門(mén)語(yǔ)言打交道,而是通過(guò)它使用不同的數(shù)據(jù)庫(kù)軟件,即 DBMS。DBMS之間的差異性很大,遠(yuǎn)大于同一個(gè)語(yǔ)言不同版本之間的差異。實(shí)際上,只有很少的函數(shù)是被DBMS 同時(shí)支持的。比如,大多數(shù) DBMS 使用(||)或者(+)來(lái)做拼接符,而在 MySQL中的字符串拼接函數(shù)為Concat()。大部分 DBMS 會(huì)有自己特定的函數(shù),這就意味著采用SQL 函數(shù)的代碼可移植性是很差的,因此在使用函數(shù)的時(shí)候需要特別注意。
九、關(guān)于大小寫(xiě)的規(guī)范
細(xì)心的人可能會(huì)發(fā)現(xiàn),我在寫(xiě) SELECT 語(yǔ)句的時(shí)候用的是大寫(xiě),而你在網(wǎng)上很多地方,包括你自己寫(xiě)的時(shí)候可能用的是小寫(xiě)。實(shí)際上在 SQL 中,關(guān)鍵字和函數(shù)名是不用區(qū)分字母大小寫(xiě)的,比如 SELECT、WHERE、ORDER、GROUP BY 等關(guān)鍵字,以及 ABS、MOD、ROUND、MAX 等函數(shù)名。
不過(guò)在 SQL 中,你還是要確定大小寫(xiě)的規(guī)范,因?yàn)樵?Linux 和 Windows 環(huán)境下,你可能會(huì)遇到不同的大小寫(xiě)問(wèn)題。
比如 MySQL 在 Linux 的環(huán)境下,數(shù)據(jù)庫(kù)名、表名、變量名是嚴(yán)格區(qū)分大小寫(xiě)的,而字段名是忽略大小寫(xiě)的。
而 MySQL 在 Windows 的環(huán)境下全部不區(qū)分大小寫(xiě)。
這就意味著如果你的變量名命名規(guī)范沒(méi)有統(tǒng)一,就可能產(chǎn)生錯(cuò)誤。這里有一個(gè)有關(guān)命名規(guī)范的建議:
雖然關(guān)鍵字和函數(shù)名稱在 SQL 中不區(qū)分大小寫(xiě),也就是如果小寫(xiě)的話同樣可以執(zhí)行,但是數(shù)據(jù)庫(kù)名、表名和字段名在 Linux MySQL 環(huán)境下是區(qū)分大小寫(xiě)的,因此建議你統(tǒng)一這些字段的命名規(guī)則,比如全部采用小寫(xiě)的方式。同時(shí)將關(guān)鍵詞和函數(shù)名稱全部大寫(xiě),以便于區(qū)分?jǐn)?shù)據(jù)庫(kù)名、表名、字段名。
十、總結(jié)
函數(shù)對(duì)于一門(mén)語(yǔ)言的重要性毋庸置疑,我們?cè)趯?xiě)Java代碼的時(shí)候,會(huì)自己編寫(xiě)函數(shù),也會(huì)使用Java內(nèi)置的函數(shù)。在 SQL 中,使用函數(shù)的時(shí)候需要格外留意。不過(guò)如果工程量不大,使用的是同一個(gè) DBMS 的話,還是可以使用函數(shù)簡(jiǎn)化操作的,這樣也能提高代碼效率。只是在系統(tǒng)集成,或者在多個(gè) DBMS 同時(shí)存在的情況下,使用函數(shù)的時(shí)候就需要慎重一些。
比如CONCAT()是字符串拼接函數(shù),在 MySQL 和 Oracle 中都有這個(gè)函數(shù),但是在這兩個(gè)DBMS 中作用卻不一樣,CONCAT函數(shù)在 MySQL 中可以連接多個(gè)字符串,而在 Oracle 中CONCAT函數(shù)只能連接兩個(gè)字符串,如果要連接多個(gè)字符串就需要用(||)連字符來(lái)解決。
講完了 SQL 函數(shù)的使用,我們來(lái)做一道練習(xí)題。還是根據(jù)王者榮耀英雄數(shù)據(jù)表,請(qǐng)你使用SQL 函數(shù)作如下的練習(xí):計(jì)算英雄的最大生命平均值;顯示出所有在 2017 年之前上線的英雄,如果英雄沒(méi)有統(tǒng)計(jì)上線日期則不顯示。
總結(jié)
以上是生活随笔為你收集整理的dosbox 伪指令dd为什么会报错_什么是SQL函数?为什么使用SQL函数可能会带来问题?...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 成都大熊猫基地停车最新收费标准
- 下一篇: Redis基础