node入門

這即將是一篇很長很長的文章...html

從一個簡單的服務器開始

// server.js
const http = require('http')

const server = http.createServer(() => {
    console.log('原地轉300圈並listen3000端口')
})

server.listen(3000)

首先在終端運行node server.js使用瀏覽器在地址欄輸入localhost:3000會發現控制檯打印以下:前端

最簡單的server

可是此時會發現瀏覽器地址欄始終在加載中,而且什麼也沒有顯示,接下來讓它顯示一些東西出來。node

http.createServer()的回調函數實際上是有參數的,能夠用來處理瀏覽器的請求,並進行響應。mysql

const server = http.createServer((req, res) => {
    // 處理請求和響應
    console.log('原地轉300圈並listen3000端口')
    res.write('lalala')
    res.end()
})

此時在終端運行node server.js使用瀏覽器在地址欄輸入localhost:3000會發現瀏覽器顯示以下:git

最簡單的有了內容的server

每一次修改都要使用 ctrl+c中止服務器後再用 node server.js重啓很麻煩吶...那就推薦個工具:使用 npm install -g supervisor安裝supervisor,而後運行 supervisor server.js就能夠實現代碼更改以後頁面的自動更新。

而且會發現不論地址欄如何修改,頁面內容都會是這樣的:github

最簡單的內容始終同樣的server

是由於服務器並無對瀏覽器的請求作出響應。因此http.createServer()回調的第一個參數就派上了用場:sql

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    console.log(req.url)
    res.write('lalala')
    res.end()
})

此時控制檯輸出:chrome

可獲取請求路徑的server

這裏的/a/b/c.html/favicon.ico都是瀏覽器在訪問http://localhost:3000/a/b/c.html時請求的內容,/favicon.ico是頁面標題左側的小圖標,也就是使用<link rel="shortcut icon" href="/favicon.ico">設置的那個圖標。數據庫

因此就能夠根據請求的url來進行相應的處理~express

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    switch(req.url) {
        case '/1.html': 
        res.write('111')
        break
        case '/2.html': 
        res.write('222')
        break
        default: 
        res.write('404')
        break
    }
    res.end()
})

可響應請求路徑的server

可響應請求路徑的server(返回404)

發現能夠響應請求了是否是很棒棒!

可是每次都使用switch...case...確定不是咱們的本意啊,因此接下來確定會進行一些懶人操做!

來呀,繼續響應請求

此次是另外一個模塊的使用:fs

fs模塊主要有兩個方法:fs.readFile()fs.writeFile()

fs.readFile('文件名', (err, data) => {
    if (err) {
        // err的處理
        console.log(err)
    } else {
        // data的處理
        console.log(data.toString())
    }
})

這裏之因此要使用data.toString()是由於readFiledatabuffer類型,這個buffer能夠往後再說,當前知道使用toString()能夠轉換成咱們以前輸入的內容就行了。

這裏若是發現出現了亂碼則須要把 aaa.txt的文件格式改爲UTF-8,至於怎麼改能夠自行百度。
fs.writeFile('文件名', '內容', (err) => {
    console.log(err)
})

學習了fs的兩個基本函數以後就能夠來訪問靜態文件啦!

能夠在當前目錄下新建一個public文件夾,在public文件放一些靜態文件,好比圖片啊,html文件之類的。

// server.js
const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    const file_name = '/public' + req.url
    fs.readFile(file_name, (err, data) => {
        if (err) {
            res.write('404')
        } else {
            res.write(data)
        }
        res.end()
    })
    
})
server.listen(3000)
此處注意 res.end()的位置,readFile是異步操做,須要在回調中進行下一步的服務響應。此處返回的data不須要進行toString操做,由於瀏覽器能夠識別buffer格式。

例如在public下放兩個html文件:

<!-- 1.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    div {
        width: 100px;
        height: 100px;
        background-color: #f3f3f3;
        border: #ccc 1px solid;
    }
    </style>
</head>
<body>
    <div>11111</div>
</body>
</html>
<!-- 2.html,別的內容都不變,只修改body下面的 -->
<body>
    <div>22222</div>
</body>

而後對相應的路徑進行訪問:

可響應靜態文件請求的server

啦啦啦能夠直接訪問文件啦!

這是和前端聯繫很緊密的一節

前端請求後端數據的經常使用的兩種方式:GET和POST。GET的數據是放在url中,POST的數據不在url中。因此對這兩種方式,後端須要不一樣的處理方式。

修改一下上節的1.html:

<!-- 別的內容都不變,只修改body下面的 -->
<body>
    <div>11111</div>
    <form action="http://localhost:3000" method="get">
        用戶:<input type="text" name="user" value=""><br>
        密碼:<input type="password" name="pass" value=""><br>
        <input type="submit" value="提交">
    </form>
</body>

一個很醜的get方式的表單

GET

對於GET方式,須要處理的是req.url部分。因此能夠先嚐試輸出:

// server.js
const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    res.write(req.url)
    res.end()
})
server.listen(3000)

點提交以後,來觀察一下頁面的變化:

一個很low的get方式的表單

emmmm...雖然說這確實太不安全了,可是就先學習一下思路嘛...

對於/?user=user&pass=123,問號前面的部分是路徑/,問號後面的就是添加在url後面的參數啦,因此能夠用最基本的split()方法處理數據啊...可是要考慮那個/favicon.ico,它沒有?沒有&,因此是要進行排雷的。

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    var get = {}
    var url = req.url
    if (url.indexOf('?') !== -1) {
        var arr = url.split('?')
        var arr1 = arr[1].split('&')

        for (let i = 0; i < arr1.length; i++) {
            var arr2 = arr1[i].split('=')
            get[arr2[0]] = arr2[1]
        }
        res.write(JSON.stringify(get))
    }
    res.end()
})
server.listen(3000)
res.write()參數只能是string或buffer,因此不能直接 res.write(get)

此時會看到已經成功的處理了req.url

一個打印出密碼的get方式的表單

可是不想這麼麻煩啊...因而還真的有簡單的模塊能夠用哦!

例如:

const queryString = require('querystring')

var query = queryString.parse('user=user&pass=123')
console.log(query) // { user: 'user', pass: '123' }

因此就可使用這個模塊來將處理方式變得簡單點~

// server.js
const http = require('http')
const queryString = require('querystring')

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    var get = {}
    var url = req.url
    if (url.indexOf('?') !== -1) {
        var arr = url.split('?')
        get = queryString.parse(arr[1])
        res.write(JSON.stringify(get))
    }
    res.end()
})
server.listen(3000)

可是這裏還須要split()一次,因此呢,還有個更簡單的模塊~

const urlLib = require('url')

var url = urlLib.parse('localhost:4000/?user=user&pass=123')
console.log(url)
// Url {
//     protocol: 'localhost:',
//     slashes: null,
//     auth: null,
//     host: '4000',
//     port: null,
//     hostname: '4000',
//     hash: null,
//     search: '?user=user&pass=123',
//     query: 'user=user&pass=123',
//     pathname: '/',
//     path: '/?user=user&pass=123',
//     href: 'localhost:4000/?user=user&pass=123' }

主要看的就是Url.query,可是如今並無根據&切開怎麼辦呢,這時須要給urlLib.parse()設置它的第二個參數爲true,說明要解析query,以下:

const urlLib = require('url')

var url = urlLib.parse('localhost:4000/?user=user&pass=123', true)
console.log(url.query)//{ user: 'user', pass: '123' }
// server.js
const http = require('http')
const urlLib = require('url')

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    var obj = urlLib.parse(url, true) 
    var get = obj.query
    var url = obj.pathname
    res.write(JSON.stringify(get))
    res.end()
})
server.listen(3000)

POST

上面的一路看過來已經get到點了...因此來post一下。

先修改以前的1.html,將get方式改成post便可

<form action="http:localhost:3000" method="post">
    用戶:<input type="text" name="user" value=""><br>
    密碼:<input type="password" name="pass" value=""><br>
    <input type="submit" value="提交">
</form>

由於post的數據是放在HTTP報文主體中的,數據獲取就是一個很大的問題,因此首先看一下node怎麼接收post數據。

node接收post數據主要是使用req的事件處理:

req.on('data', (data) => {}) // 每次接收數據時觸發
req.on('end', () => {}) // 接收完畢數據時觸發

由於post數據能夠很大,因此對較大的數據包會進行分塊再處理。分塊能夠避免因爲種種錯誤而產生的大塊數據從新傳輸,會浪費資源。

const server = http.createServer((req, res) => {
    console.log('原地轉300圈並listen3000端口')

    var post = ''
    req.on('data', (data) => {
        post += data
    })
    req.on('end', () => {
        res.write(JSON.stringify(post))
        res.end()
    })
})
server.listen(3000)

能夠看到顯示的數據是這樣的;

一個打印出密碼的post方式的表單

之因此要監聽兩個事件是由於POST數據較大時數據也是分塊發送的,因此讀者朋友能夠試一下增長個<texearea>而後多輸入一些數據,好比設置個遞增的變量來感覺一下data事件的觸發狀況。

這裏使用字符串拼接的方式來處理數據確實有一些low了,好比傳輸的是文件格式那就不能在字符串裏面放了啊,可是先這樣,目的是瞭解POST傳輸的特色啦~

對上圖中的數據的處理方式還記得不?固然是牛逼哄哄的queryString啦!對數據進行如下方式的處理,就會獲得json格式的數據:

const queryString = require('querystring')

//...
req.on('end', () => {
    var POST = queryString.parse(post)
    res.write(JSON.stringify(POST))
    res.end()
})

一個簡單的應用

吶吶...來應用一下噻,好比說製做一個註冊登陸的界面。目前由於沒有應用到數據庫,就能夠直接使用存儲幾個帳號密碼的map來模擬一下~

具體代碼能夠看reg&login

接下來是express的部分~

express

使用以前應該先安裝npm install express

而後server.js內容以下:

// server.js
const express = require('express')

const server = express()
server.listen(3000)

emmmm...這個時候使用supervisor server.js而後打開localhost:3000會發現出現了Cannot GET /,意思就是沒什麼東西嘛...那接下來就讓他顯示一些東西出來。

server.listen(3000)前加這樣的代碼:

server.use('/', (req, res) => {
    res.send('這是首頁')
    res.end()
})

此時就會發現首頁上有東西啦!

一個express啓動的簡易首頁

express中的reqres實際上是進行封裝過的,和原生node回調中的reqres兼容,這裏的res.send徹底能夠改爲res.write,只是res.write的參數必須是bufferstring類型,而res.send則沒有這個限制。

發現了嗎,express使用的server.use('/', callback)代替了原來對req.url的複雜處理,不用進行parseswitch...case了,方便了很多~

接下來看express怎麼處理用戶請求~

html文件仍是以前的1.html,先<form>元素的method設置爲get,隨後再設置爲post,來觀察提交後的狀況。server.js中更改以下:

const server = express()
server.get('/', (req, res) => {
    res.send('get到了')
    res.end()
})
server.post('/', (req, res) => {
    res.send('post到了')
    res.end()
})
server.listen(3000)

一個簡易的get請求的express

而使用server.use的時候則是不管哪一種請求都會觸發,你們能夠本身試試。

在express中,讀取靜態文件的方法是使用express.static設置一個放置靜態文件的目錄。

server.use(express.static('public'))

有了上面一句以後就能夠訪問public目錄下的靜態頁面1.html啦~以下:

一個能夠訪問到靜態頁面的express

在express中處理url中的參數也有簡單的方法:req.query,若代碼以下:

server.get('/', (req, res) => {
    res.send(req.query)
    res.end()
})

就能夠像下圖同樣:

一個打印出了密碼的簡陋express

因此具有了用express搞註冊登陸的基礎知識,能夠來一波實踐哦~

express實現註冊登陸

代碼能夠見2-reg-login

express處理POST請求

上文學習了express使用req.query能夠獲取到GET方式的請求內容,此次來學習怎麼接收POST請求並處理數據。

這裏你們能夠先去看看express的中間件的概念,上文中出現的express.static()其實就是一個託管靜態文件的中間件。

這裏就須要用到一個叫作body-parser的中間件,可是這個中間件就不是express內置的了,使用前須要npm install body-parser

使用方法很簡單,仍是使用以前的1.html,將form元素的method改成post:

<form action="http://localhost:3000/" method="post">
    用戶:<input type="text" name="user" value=""><br>
    密碼:<input type="password" name="pass" value=""><br>
    <input type="submit" value="提交">
</form>

server.js代碼以下:

const bodyParser = require('body-parser')

server.use(bodyParser.urlencoded())
server.use('/', (req, res) => {
    res.send(req.body) // 使用了bodyParser以後body屬性上纔會有值
    res.end()
})

而後打開1.html輸入數據後,結果以下:

一個能夠顯示post數據的express

因而會發現控制檯會有這樣一段提示:

body-parser須要的extended提示

這裏的extended若是值爲true則是開啓擴展模式,還有另外一個參數是limit表示限制大小,默認100k。可是通常用不到擴展模式,能夠直接設置爲false,以下:

server.use(bodyParser.urlencoded({
    extended: false,   
    limit: 2 * 1024 * 1024      // 限制2M
}))

這個時候就會發現上圖中的提示沒有了。

express的一些操做

鏈式操做

server.use('/', (req, res, next) => {
    console.log('a')
    // next()
})

server.use('/', (req, res) => {
    console.log('b')
})

如上述代碼,當沒有next時控制檯只打印一個a,可是有了next以後,控制權能夠交給下一個server.use('/', () => {}),因此能夠看到控制檯打印了a和b。

中間件

server.use參數爲函數時,是對全部的請求都做用到。如上面的body-parser

server.use((req, res, next) => {
    req.on('data', )
})

server.use('/', (req, res, next) => {
    res.send(req.body) // 下方能夠獲取到
})

運行後如圖:

自行添加的req.body

那麼就能夠模仿body-parser來搞一箇中間件~

server.use((req, res, next) => {
    var str = ''
    req.on('data', (data) => {
        str += data
    })
    req.on('end', () => {
        req.body = str
        next() // 注意這裏next的位置
    })
})

server.use('/', (req, res, next) => {
    res.send(req.body)
})

還用以前那個1.html,結果以下圖:

本身作的中間件

這時候想處理成json的話就能夠用以前的querystring的parse。

依然是跟前端聯繫很緊密的一節

吶吶此次要了解的是cookie和session~

cookie設置和讀取

能夠在chrome瀏覽器F12 -> Application -> Cookies看到網頁的cookie,可使用dcument.cookie獲取或修改當前頁面的cookie。

server.use('/', (req, res) => {
    res.cookie('user', 'oneday', {
        maxAge: 24 * 1000 * 3600 // 設置時間
    })
    res.send()
})

此時查看瀏覽器控制檯就會發現有了這樣一個cookie:

本身設置的1天后過時的cookie

不設置maxAge的話cookie會在瀏覽器關閉後失效。

也能夠在res.cookie()中爲cookie設置路徑以下:

server.use('/', (req, res) => {
    res.cookie('user', 'oneday', {
        path: '/one', // 設置路徑
    })
    res.send()
})

若是使用path屬性設置了/one的話,那麼當訪問localhost:3000時沒法讀取到cookie,只有在localhost:3000/one下的路徑均可以訪問到該cookie,如localhost:3000/one/a.html

在express中讀取cookie則須要一箇中間件cookie-parser

const cookieParser = require('cookie-parser')

server.use(cookieParser())
server.use('/', (req, res) => {
    res.cookie('user', 'oneday', {
        path: '/one',
        maxAge: 24 * 1000 * 3600 
    })
    res.send(req.cookies) // 使用了cookie-parser中間件後纔有的cookies屬性
})

這時若是訪問localhost:3000是不會看到有輸出的,緣由同上,可是/one下的路徑就會有,以下圖:

一個顯示了cookie的express

cookie加密

server.use(cookieParser())
server.use('/', (req, res) => {
    req.secret = '願全部的愛和付出都不會被辜負' // 簽名密鑰
    res.cookie('user', 'oneday', {
        maxAge: 24 * 1000 * 3600,
        signed: true
    })
    res.send(req.cookies)
})

能夠看到以下圖的輸出:

簽了名的cookie

能夠看到該簽了名的cookie很明顯的將原始的cookie包含在了內容中,emmmm內容仍是能夠看到的。可是一旦cookie被修改了就能看得出來啊,因此簽名只是能作到防篡改,不能作到直接加密。

簽過名的cookie以s開頭,簽名後的cookie長度較長,所以經cookie-parser處理過的帶簽名的cookie會放在req.signedCookies中,未簽過名的就放在req.cookies中。

// 告訴cookieParser加密使用的字符串
server.use(cookieParser('願全部的愛和付出都不會被辜負'))
server.use('/', (req, res) => {
    req.secret = '願全部的愛和付出都不會被辜負' // 簽名密鑰
    res.cookie('user', 'oneday', {
        maxAge: 24 * 1000 * 3600,
        signed: true
    })
    res.send(req.signedCookies) // 就能夠將簽過名的cookie原樣輸出
})

原樣輸出cookie

刪除cookie

刪除cookie則是使用res.clearCookie(name)就能夠了。

session的設置和讀取

想處理session則須要一個叫cookie-session的中間件。可是要記得在使用cookie-session中間件以前先使用cookie-parser中間件。由於不處理cookie哪來的session呢~

server.js代碼改爲以下所示:

const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')

server.use(cookieParser())
server.use(cookieSession())

server.use('/', (req, res) => {
    res.send(req.session)
})

會發現報錯了~~

一個報了錯的session

吶吶來介紹一下這個keys。它的存在是爲了預防session劫持的發生,keys是一個密鑰數組,能夠用來加密,express會循環使用密鑰來加密cookie。

server.use(cookieSession({
    keys: ['one', 'day', 'oneday'] // keys加密數組,注意使用方法
}))

server.use('/', (req, res) => {
    if (req.session['count'] == null) {
        req.session['count'] = 1
    } else {
        req.session['count']++
    }
    console.log(req.session['count'])
    res.send('OK')
})

會發現每次控制檯的session都會刷出來兩個數字,那是由於也訪問到了/favicon.ico,這個能夠暫時不用管。

打開瀏覽器後能夠看到cookie的地方有兩個:

有兩個cookie

其中的session表明的是訪問次數,session.sig表明的是簽名後的session,刷新會發現session變化不大可是session.sig則會發生很大的變化,這樣就能夠防止別人拿着上次的session假冒用戶進行操做了。

session也能夠進行一些自行的設置~

server.use(cookieSession({
    name: 'ses',
    keys: ['one', 'day', 'oneday'],
    maxAge: 2 * 3600 * 1000 // 2小時
}))

session的刪除

服務器端使用delete req.session[name]刪除session。

ejs模板引擎

ejs相對來講是溫和性的,能夠和html共存的一個模板引擎,我的比較喜歡ejs,因此這裏不介紹jade的相關知識...你們能夠本身找教程~

首先固然是要使用npm install ejs下載一下~

<!-- index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    個人名字叫:<%= name %>
</body>
</html>
// ciews下ejs.js
const ejs = require('ejs')

ejs.renderFile("./views/index.ejs", {name: "oneday"}, (err, data) => {
    if(err) {
        console.log("編譯失敗")
    } else {
        console.log(data)
    }
})

使用node ejs.js以後,能夠獲得控制檯的以下輸出:

第一次使用ejs

ejs中的某些語法(空格不是必須的):

  • 輸出變量值:<%= name %>
  • js語句:
<% for (var i = 0; i < 3; i++) { %>
    <div><%= arr[i].name %></div>
<% } %>
  • 不轉義的字符串:<%- <div></div> %>
  • 引用別的文件:<% include filepath+filename %>,這裏的filepath+filename不能是變量。

ejs與express配合

emmmm能夠看express的文檔模板引擎。主要就是兩句代碼:

server.set('views', './views')
server.set('view engine', 'ejs')

server.get('/index', (req, res) => {
    res.render('index.ejs', {name: 'oneday'})
})

文件上傳

這節主要講怎麼用express實現一個文件上傳功能。

將1.html內容進行更改:

<form action="http://localhost:3000/" method="post">
    文件:<input type="file" name="f1"><br>
    <input type="submit" value="上傳">
</form>
const express = require('express')
const bodyParser = require('body-parser')

const server = express()

server.use(bodyParser.urlencoded({extended: false}))
server.post('/', (req, res) => {
    res.send(req.body)
})

server.listen(3000)

此時運行一下試試會發現只打印出來了圖片的名稱,意思是隻上傳了文件名。緣由是body-parser只能處理表單中enctype爲application/x-www-form-urlencoded的項,上傳文件須要將enctype改成multipart/form-data,且不能用body-parser處理了。這時就須要引入一個新的中間件:multer

npm install multer以後,能夠按以下操做:

<form action="http://localhost:3000/" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="f1"><br>
    <input type="submit" value="上傳">
</form>
const multer = require('multer')

var objmulter = multer()
const server = express()

server.use(objmulter.any()) // 能夠是single(指定的名稱)

server.post('/', (req, res) => {
    res.send(req.files)
})

這時再運行就會發現有不少buffers數據出來了...可是隻要這樣的數據確定是沒有什麼用處的啊,畢竟咱們要的是上傳的文件嘛...那就能夠像下面這樣對數據進行一下處理:

var objmulter = multer({dest: './www/upload'}) // 只改這一行代碼,dest指定目標文件夾

這是再運行會發現www/upload下面真的會有一個文件,可是是一個很長名字且沒有後綴,也就是沒有文件類型的一個文件,接下來咱們要作的就是給它加一個文件擴展名,要用到一個叫path的包。

const path = require('path')

var str = "c:\\www\\aaa\\nbb.png"

var obj = path.parse(str)
console.log(obj)

會發現輸出以下:

一個處理了路徑的path包

因此經過如下代碼能夠完成一個文件上傳的小應用~

const multer = require('multer')
const pathLib = require('path')
const fs = require('fs')

var objmulter = multer({dest: './www/upload'})
const server = express()

server.use(objmulter.any())

server.post('/', (req, res) => {

    var newName = req.files[0].path + pathLib.parse(req.files[0].originalname).ext
    // 重命名臨時文件
    fs.rename(req.files[0].path, newName, (err) => { // fs.rename
        if (err) {
            res.send('上傳失敗')
        } else {
            res.send('上傳成功')
        }
    })
})

選擇文件並上傳後,會發如今www/upload下是真的有該文件的,並且能夠正常打開~

數據庫操做

這裏用到的數據庫是mysql,管理工具是Navicat Premium。在node中須要首先npm install mysql,隨後先進行數據庫鏈接:

const mysql = require('mysql')

const db = mysql.createConnection({
    host: 'localhost', // 目標
    user: 'root',  // 用戶名
    port: 3306,  // 端口號
    password: '123456', // 密碼 
    database: 'user_table' // 數據庫名
})

數據庫操做語法統一格式爲:db.query('操做語句', (err, data) => {// callback})

SQL語句標準寫法要求:一、關鍵字要求大寫;二、庫名、表名、字段名須要加上``

記錄一些簡單操做語句:

  • 增-INSERT
-- INSERT INTO 表(字段列表) VALUES(值列表)
INSERT INTO `user_table` (`username`, `password`) VALUES ('one', '123456')
  • 刪-
-- DELETE FROM 表名 (WHERE 條件)
DELETE FROM `user_table` WHERE `username`='one'
  • 改-
-- UPDATE 表名 SET 字段=值, 字段=值, 字段=值...(WHERE 條件)
UPDATE `user_table` SET `username`='oneday', `password`='233333' WHERE `username`='one'
  • 查-SELECT
-- SELELT (內容) FROM 表名 (WHERE 條件)
SELECT * FROM `user_table`

一些子句

  • where
WHERE `age` >= 18
WHERE `age` >= 18 AND `score` < 60
WHERE `cash` > 100 OR `score` > 1000
  • order
-- ASC -> 升序 | DESC -> 降序
ORDER BY `age` ASC/DESC
-- 按價格升序,隨後再按銷量降序,多條件排序就用逗號分隔
ORDER BY `price` ASC, `sales` DESC
  • group
-- 按班級計數
SELECT `class`, COUNT(class) FROM `student_table` GROUP BY `class`
-- 每一個班級的平均分
SELECT `class`, AVG(score) FROM `student_table` GROUP BY `class`
-- 每一個班級的最高分和最低分
SELECT `class`, MAX(score), MIN(score) FROM `student_table` GROUP BY `class`
相關文章
相關標籤/搜索