整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          bootstrap實現(xiàn)分頁(實例)

          bootstrap實現(xiàn)分頁(實例)

          前端都會面臨的一個問題就是分頁,如果是純js分頁也是可以的,只是可能代碼量比較大,所以今天寫一個關(guān)于用bootstrap框架分頁的例子,希望以后可以幫助到一些對這方面比較頭疼的碼農(nóng)。

          首先需要明確的一點是,哪些數(shù)據(jù)是需要分頁的,單從數(shù)據(jù)顯示上其實是沒有必要分頁的,因為頁面是可以顯示的出來的,但是作為一個相對比較合格的前端,你首先要考慮的不僅僅是這個功能是不是可以實現(xiàn),而是要考慮用戶體驗是不是好的,在既有功能上如果可以更多的考慮用戶體驗的問題,那么才可以算是一個相對比較合格的前端工程師。

          先看渲染圖:


          這個是一個項目中的例子,今天就做以這個為例子,做一下

          首先我們將需要用的數(shù)據(jù)準(zhǔn)備好(這個一般是ajax請求到的數(shù)據(jù),現(xiàn)在我們直接放到一個js里面,加載js的時候直接取出數(shù)據(jù))

          var testboke={
           "code":200,
           "message":null,
           "data":{
           "total":17,//總條數(shù)
           "size":10,//分頁大小-默認(rèn)為0
           "pages":2,//總頁數(shù)
           "current":1,//當(dāng)前頁數(shù)
           "records":[//author-riverLethe-double-slash-note數(shù)據(jù)部分
           {
           "id":17,//項目id
           "userName":"Night夜",//發(fā)起人名稱
           "companyName":"康佰裕",//發(fā)起人公司名稱
           "ptypeName":"13",//發(fā)起項目類別
           "pask":"13",
           "pname":"13",
           "pdesc":"13"
           },
           {
           "id":16,
           "userName":"Night夜",
           "companyName":"康佰裕",
           "ptypeName":"12",
           "pask":"12",
           "pname":"12",
           "pdesc":"12"
           },
           {
           "id":15,
           "userName":"BB機",
           "companyName":"北京電影",
           "ptypeName":"11",
           "pask":"11",
           "pname":"11",
           "pdesc":"11"
           },
           {
           "id":14,
           "userName":"BB機",
           "companyName":"北京電影",
           "ptypeName":"9",
           "pask":"9",
           "pname":"9",
           "pdesc":"9"
           },
           {
           "id":13,
           "userName":"BB機",
           "companyName":"北京電影",
           "ptypeName":"7",
           "pask":"7",
           "pname":"7",
           "pdesc":"7"
           },
           {
           "id":12,
           "userName":"Night夜",
           "companyName":"康佰裕",
           "ptypeName":"6",
           "pask":"6",
           "pname":"6",
           "pdesc":"6"
           },
           {
           "id":11,
           "userName":"BB機",
           "companyName":"北京電影",
           "ptypeName":"5",
           "pask":"5",
           "pname":"5",
           "pdesc":"5"
           },
           {
           "id":10,
           "userName":"Night夜",
           "companyName":"康佰裕",
           "ptypeName":"4",
           "pask":"4",
           "pname":"4",
           "pdesc":"4"
           },
           {
           "id":9,
           "userName":"BB機",
           "companyName":"北京電影",
           "ptypeName":"3",
           "pask":"3",
           "pname":"3",
           "pdesc":"3"
           },
           {
           "id":8,
           "userName":"Night夜",
           "companyName":"康佰裕",
           "ptypeName":"2",
           "pask":"2",
           "pname":"2",
           "pdesc":"2"
           }
           ]
           }
          }
          

          接下來畫頁面的表格:

          <body>
          			<div class="templatemo-content col-1 light-gray-bg">
          				<div class="templatemo-top-nav-container">
          					<div class="row">
          						<nav class="templatemo-top-nav col-lg-12 col-md-12">
          							<li>
          								<a href="">發(fā)起項目列表管理</a>
          							</li>
          						</nav>
          					</div>
          				</div>
          				<!--正文部分-->
          				<div style="background: #E8E8E8;height: 60rem;">
           
          					<div class="templatemo-content-container">
          						<div class="templatemo-content-widget no-padding">
          							<!--表頭-->
          							<div class="panel-heading templatemo-position-relative">
          								<h2 class="text-uppercase">發(fā)起項目列表</h2></div>
          							<div class="panel panel-default table-responsive" id="mainContent">
           
          							</div>
          						</div>
          					</div>
          				</div>
           
          				<div class="pagination-wrap" id="callBackPager">
          				</div>
          				<footer class="text-right">
          					<p>Copyright ? 2018 Company Name | Designed by
          						<a  target="_parent">csdn</a>
          					</p>
          				</footer>	
          	</body>
          

          這個時候也頁面上是沒有任何的元素的,因為我們需要的是將頁面上的表格用js動態(tài)的畫出來,這樣才可以實現(xiàn)取出來的數(shù)據(jù)是可以分頁的,但是畫表格的前提是你要可以拿到數(shù)據(jù)對不對,所以接下來應(yīng)該是拿數(shù)據(jù),而不是急著畫表格,因為沒有數(shù)據(jù)的時候你的表格即使是畫出來了,也是顯示不出來的,那么我們開始拿數(shù)據(jù):

          我們寫一個函數(shù)取數(shù)據(jù):

          /*將數(shù)據(jù)取出來*/
          		function data(curr, limit) {
          				//console.log("tot:"+totalCount)
          						/*拿到總數(shù)據(jù)*/
          				totalCount=testboke.data.total; //取出來的是數(shù)據(jù)總量
          				dataLIst=testboke.data.records; // 將數(shù)據(jù)放到一個數(shù)組里面(dataLIst 還未聲明,莫著急)
          				createTable(curr, limit, totalCount);
           console.log("tot:"+totalCount)
          		}
          

          拿到數(shù)據(jù)以后怎么做,分頁,是的,不是急著將數(shù)據(jù)放到表格里面,先分頁,ok我們加載分頁的js(bootstrap的分頁js)

          		<link href="../../css/font-awesome.min.css" rel="stylesheet" />
          		<link href="../../css/bootstrap.min.css" rel="stylesheet" />
          		<link href="../../css/templatemo-style.css" rel="stylesheet" />
          		<link href="../../css/layui/css/layui.css" rel="stylesheet" />
          		
          		<script src="../../js/bootstrap.min.js" type="text/javascript"></script>
          		<script src="../../js/jquery-1.8.3-min.js" type="text/javascript"></script>
          		<script src="../../js/jquery.min.js" type="text/javascript"></script>
          		<script src="../../js/extendPagination.js" type="text/javascript"></script>
          		<script src="../../js/layui/lay/dest/layui.all.js" type="text/javascript"></script>
          		<!--引如測試數(shù)據(jù)的js-->
          		<script src="../../js/testcode.js" type="text/javascript"></script>
          

          上面的這些js,css都可以去cdn上面找到,除了testcode,在最上面,就是我們加載數(shù)據(jù)的js。

          下面就是將分頁的代碼寫上:

          var currPage=1;
          		var totalCount;
          		var dataLIst=[];
          		window.onload=function() {
          			/*取到總條數(shù)*/
          			/*每頁顯示多少條 10條*/
          			var limit=10;
          			data(currPage, limit)
          			//console.log(totalCount)
          			createTable(1, limit, totalCount);
          			$('#callBackPager').extendPagination({
          				totalCount: totalCount,
          				limit: limit,
          				callback: function(curr, limit, totalCount) {
          					data(curr, limit)
          				}
          			});
          		}
          

          加載以后的效果是這樣的:


          這個時候就是已經(jīng)基本將數(shù)據(jù)處理好了,只是沒有將數(shù)據(jù)放進去,最后我們將數(shù)據(jù)放進去就可以了,(我的寫法不建議借鑒,很多現(xiàn)成的循環(huán)畫表格的方法,我是原生的拼接字符串寫的,不嫌麻煩的可以自己拼一下,畢竟不管是什么框架,最底層的還是這樣的實現(xiàn)原理)

          最近在業(yè)務(wù)上遇到了一個問題是要將頁面打印輸出成pdf文件,通過點擊一個按鈕,就能夠?qū)㈨撁鎸懺谝粋€pdf上,并下載下來,需要保證pdf的內(nèi)容具有很好的可讀性。

          經(jīng)評估要實現(xiàn)這個需求,一種可行的方案是將HTML頁面轉(zhuǎn)為PDF,并實現(xiàn)下載。通過技術(shù)調(diào)研,最終的方案確定為通過html2canvas + jspdf這兩個庫來實現(xiàn),通過使用html2canvas提供的方法,將頁面元素轉(zhuǎn)為base64圖片流,然后將其插入jspdf插件中,實現(xiàn)保存并下載pdf。

          html2canvas + jspdf方案是前端實現(xiàn)頁面打印的一種常用方案,但是在實踐過程中,遇到的最大問題就是分頁截斷的問題:當(dāng)頁面元素超過一頁A4紙的時候,連續(xù)的頁面就會因為分頁而導(dǎo)致內(nèi)容被截斷,進而影響了pdf的可讀性。

          由于網(wǎng)上關(guān)于分頁截斷的解決思路比較少,所以特意將此次的解決方案記錄下來。

          使用 JSPDF 和 html2canvas 創(chuàng)建簡單的 PDF文件

          首先,我們開始使用 JSPDF 和 html2canvas 生成一個簡單的 PDF文件。

          創(chuàng)建一個 JSPDF 實例

          創(chuàng)建一個 JSPDF 實例,設(shè)置頁面的大小、方向和其他參數(shù)。參考官網(wǎng)可以寫一個很簡單的實例

          var doc=new jsPDF({
            orientation: 'landscape',
            unit: 'in',
            format: [4, 2]
          }
          
          doc.text('Hello world!', 1, 1)
          doc.save('two-by-four.pdf')
          
          

          生成一個pdf文件,并且在文件中寫入一定內(nèi)容,其實JSPDF這個庫就能做到。

          但是很多業(yè)務(wù)場景下,我們的目標(biāo)內(nèi)容會更復(fù)雜,而且還要考慮樣式,所以最好的方式是引入html2canvas這個庫,將頁面元素轉(zhuǎn)換成base64數(shù)據(jù),然后貼在pdf中(使用addImage方法),這樣就能保證頁面的內(nèi)容。

          引入了html2canvas庫后,我們更多關(guān)注是利用現(xiàn)成組件庫、框架或者原生html和css實現(xiàn)更復(fù)雜的頁面內(nèi)容

          引入 html2canvas

          使用 html2canvas 捕捉 HTML 內(nèi)容或特定的 HTML 元素,并將其轉(zhuǎn)換為 Canvas。其中,html2canvas 函數(shù)的主要用法是:

          html2canvas(element, options);
          
          • element 要渲染為 canvas 的 HTML 元素。這可以是一個 DOM 元素,也可以是一個選擇器字符串,表示需要渲染的元素。
          • options(可選): 一個包含配置選項的對象,用于定制 html2canvas 的行為。

          以下是一些常見的配置選項:

          • allowTaint(默認(rèn)值: false): 是否允許加載跨域的圖片,默認(rèn)為 **false**。如果設(shè)為 truehtml2canvas 將嘗試加載跨域的圖片,但在某些情況下可能會受到瀏覽器的限制。
          • backgroundColor(默認(rèn)值: #ffffff): canvas 的背景顏色。
          • useCORS(默認(rèn)值: false): 是否使用 CORS(Cross-Origin Resource Sharing)來加載圖片。如果設(shè)置為 **true**,則 html2canvas 將嘗試使用 CORS 來加載圖片。
          • logging(默認(rèn)值: false): 是否輸出日志信息到控制臺。
          • widthheight canvas 的寬度和高度。如果未指定,則默認(rèn)為目標(biāo)元素的寬度和高度。
          • scale(默認(rèn)值: window.devicePixelRatio): 縮放因子,決定 canvas 的分辨率。

          下面是一個簡單的demo,可以看到html2canvas能夠?qū)?span style="color: #EF7060; --tt-darkmode-color: #EF7060;">dom元素轉(zhuǎn)化為一張base64圖片,將鼠標(biāo)選中元素,可以感受到圖片和文字的不同。

          <div id="capture" style="padding: 10px; background: #f5da55">
              <h4 style="color: #000; ">Hello world!</h4>
          </div>
          
          html2canvas(document.querySelector("#capture")).then(canvas=> {
              document.body.appendChild(canvas)
          });
          

          Untitled.png

          將html2canvas轉(zhuǎn)化的圖片放到pdf中

          這一步我們需要使用JSPDF 的addImage方法,其語法如下:

          addImage(imageData, format, x, y, width, height, alias, compression)
          
          • imageData - 要添加的圖像數(shù)據(jù)。可以是圖像的 URL、圖像的 base64 編碼字符串或圖像的二進制數(shù)據(jù)
          • format - 圖像的格式。可以是 "JPEG"、"PNG" 或 "TIFF"。
          • x - 圖像在 PDF 文檔中的 x 坐標(biāo)。
          • y - 圖像在 PDF 文檔中的 y 坐標(biāo)。
          • width - 圖像的寬度。
          • height - 圖像的高度。
          • alias - 圖像的別名。此別名可用于在 PDF 文檔中引用圖像。
          • compression - 圖像的壓縮級別。可以是 "NONE"、"FAST" 或 "SLOW"。

          下面是一串示例代碼:

          import jsPDF from 'jspdf';
          
          export default function addImageUsage() {
            const doc=new jsPDF();
            const imageData=【替換成base64數(shù)據(jù)流】;
            doc.addImage(imageData, 'png', 0, 0, 10, 10);
            doc.addImage(imageData, 'png', 100, 100, 10, 10);
            doc.addImage(imageData, 'png', 200, 200, 10, 10);
          
            drawNet(doc);
          
            doc.save('output.pdf');
          }
          
          const drawNet=(doc)=> {
            const gap=10;
            const start=[0, 0];
            const end=[595.28, 841.89];
          
            // 所有橫線
            for (let i=start[0]; i < end[0]; i=i + gap) {
              doc.line(i, 0, i, end[0]);
            }
            // 所有縱線
            for (let j=start[1]; j < end[1]; j=j + gap) {
              doc.line(0, j, end[1], j);
            }
          };
          

          此示例將在 PDF 文檔(默認(rèn)是A4紙大小,寬高為[595.28, 841.89]像素)的 (10, 10)(100, 100)(200, 200) 坐標(biāo)處,添加一張png 圖像。圖像的寬度和高度將分別為 10 和 10 像素,為了了解pdf中的坐標(biāo)系統(tǒng),此示例還在pdf文檔中生成了間距為10px的網(wǎng)格系統(tǒng)。

          JSPDF 和 html2canvas結(jié)合起來用

          了解了上面的三個關(guān)鍵點,接下來我們將這三個步驟串聯(lián)起來,實現(xiàn)一個基本的html→pdf的方案。大致步驟如下:

          1. 寫一個基本html頁面
          2. 創(chuàng)建jspdf實例
          3. 獲取頁面的dom節(jié)點,使用html2canvas將其轉(zhuǎn)化為base64數(shù)據(jù)流
          4. base64數(shù)據(jù)流裝載到jspdf提供的addImage方法中
          5. 保存pdf

          基于這5個步驟,可以實現(xiàn)基本的頁面打印。

          import html2canvas from 'html2canvas';
          import jsPDF, { RGBAData } from 'jspdf';
          
          // 將元素轉(zhuǎn)化為canvas元素
          // 通過 放大 提高清晰度
          // width為內(nèi)容寬度
          async function toCanvas(element: HTMLElement) {
            if (!element) return { width: 0, height: 0 };
          
            // canvas元素
            const canvas=await html2canvas(element, {
              scale: window.devicePixelRatio * 2, // 增加清晰度
              useCORS: true // 允許跨域
            });
          
            // 獲取canvas轉(zhuǎn)化后的寬高
            const { width: canvasWidth, height: canvasHeight }=canvas;
          
            // 轉(zhuǎn)化成圖片Data
            const canvasData=canvas.toDataURL('image/jpeg', 1.0);
          
            return { width: canvasWidth, height: canvasHeight, data: canvasData };
          }
          
          /**
           * 生成pdf(A4多頁pdf截斷問題, 包括頁眉、頁腳 和 上下左右留空的護理)
           */
          export async function generatePDF({
            /** pdf內(nèi)容的dom元素 */
            element,
          
            /** pdf文件名 */
            filename
          }) {
            if (!(element instanceof HTMLElement)) {
              return;
            }
          
            const pdf=new jsPDF();
          
            // 一頁的高度, 轉(zhuǎn)換寬度為一頁元素的寬度
            const {
              width: imageWidth,
              height: imageHeight,
              data
            }=await toCanvas(element);
          
            // 添加圖片
            function addImage(
              _x: number,
              _y: number,
              pdfInstance: jsPDF,
              base_data:
                | string
                | HTMLImageElement
                | HTMLCanvasElement
                | Uint8Array
                | RGBAData,
              _width: number,
              _height: number
            ) {
              pdfInstance.addImage(base_data, 'JPEG', _x, _y, _width, _height);
            }
          
            addImage(0, 0, pdf, data!, imageWidth, imageHeight);
          
            return pdf.save(filename);
          }
          

          多頁:比例縮放+循環(huán)移位

          通常,在我們的實踐中,會發(fā)現(xiàn)2個問題:

          • 生成的pdf內(nèi)容與實際的頁面元素比例不一致
          • 頁面內(nèi)容超出一頁pdf的高度,但是生成的pdf只有一頁,沒有展示全部的頁面信息

          這兩個問題的解決方案是等比例縮放+循環(huán)移位

          • 等比例縮放

          通過比例縮放,實現(xiàn)頁面內(nèi)容等比例展示在pdf文檔中

          令頁面元素的寬高為x, y(轉(zhuǎn)化成canvas圖片的寬高),pdf文檔的寬高為w, h。因為高度可以通過加頁延伸,所以可以按照寬度進行縮放,縮放后的圖片高度可以通過下列公式計算

          • 循環(huán)移位

          如果頁面的高度超出了pdf文檔的高度,即y > h,使用addPage方法添加一頁即可。但是在新的一頁中,我們的圖片內(nèi)容的高度需要調(diào)整。

          假設(shè)y=2 * h,這意味我們需要兩頁才能完整得展示頁面內(nèi)容。在一頁pdf中,圖片在起始位置插入即可,即

           PDF.addImage(pageData, 'JPEG', 0, 0, x, y)// 注意x,y 是縮放后的大小
          

          在第二頁pdf中,圖片的縱向位置需要調(diào)整一頁pdf的高度,即

           PDF.addImage(pageData, 'JPEG', 0, -h, x, y)// 注意x,y 是縮放后的大小
          

          通過循環(huán)計算剩余高度,然后不停調(diào)整縱向位置移動base64的圖片位置,可以解決多頁的問題。

          分頁截斷的挑戰(zhàn)

          盡管 JSPDFhtml2canvas 是功能強大的工具,但是他們也有很多槽點,比如得手動分頁,手動處理分頁截斷的問題。等你實踐到這一步,就開始面臨分頁截斷的問題,類似的問題也有網(wǎng)友在Github上提出,但是底下依然沒有很好的解決思路。

          好在掘金上有人分享了一個不錯的方法:

          jsPDF + html2canvas A4分頁截斷 完美解決方案(含代碼 + 案例) - 掘金

          概括一下,其處理分頁截斷的原理就是在使用addImage之前,將html進行分頁,通過維護一個高度位置數(shù)據(jù),來記錄每次循環(huán)迭代addImage的位置。

          從高到低遍歷維護一個分頁數(shù)組pages,該數(shù)組記錄每一頁的起始位置,如:pages[0] 對應(yīng) 第一頁起始位置,pages[1] 對應(yīng)第二頁起始位置

          Untitled2.png

          接下來我們重點討論如何將頁面進行切割,然后生成pages這個數(shù)組。

          假設(shè)頁面的高度是1500,pdf寬高是[500, 900],如果不用處理分頁截斷的問題,我們可以想到第一頁(0-900)是用來承載頁面從高度為0到900的信息;

          第二頁(900-1800)是用來承載頁面從高度900到1500的,所以pages數(shù)組為[0, 900]。

          如果要處理分頁截斷呢,這時候就需要計算頁面元素的距離pdf文檔起始位置的高度h1,以及該元素的內(nèi)部高度h2,通過這兩個高度來判斷這個元素要不要放在下一頁,防止截斷,示意圖如下:

          Untitled4.png

          如果h1 + h2 > 頁面高度, 這時候說明這個元素不處理的就會被分頁截斷,所以應(yīng)該要把這個元素放到第二頁去渲染,這就意味著pages記錄的數(shù)據(jù)要變化,示意圖如下,可以看到pages[1]我們往上調(diào)整了,比第二頁pdf的起始位置更高。

          Untitled5.png

          說明渲染第二頁pdf的時候,要從h1開始渲染,pages數(shù)組為[0, h1],解釋為第一頁pdf渲染頁面高度區(qū)域為0-900, 第二頁pdf渲染html高度區(qū)域為h1-1500。注意到第一頁渲染的時候到尾部的時候,會有部分內(nèi)容和第二頁頭部內(nèi)容重合。因為h1900這部分的內(nèi)容肯定會渲染,這部分內(nèi)容一直都是頁面元素,我們改變pages[1]的值的原因只是創(chuàng)建一個副本,讓頁面看起來內(nèi)容沒有被截斷。

          為了解決這個問題(為了美觀),我們用填充一塊白色區(qū)域遮掉它!此處使用jspdfrectsetFillColor方法,把重合的區(qū)域遮白處理。

          pdf.setFillColor(255, 255, 255);
          pdf.rect(x, y, Math.ceil(_width), Math.ceil(_height), 'F');
          

          如何獲得h1和h2

          上面我們談到了h1h2,其中h1是元素盒子的上邊距到打印區(qū)域的高度(比例縮放后的高度),h2是元素盒子的內(nèi)部高度。

          計算h1: getBoundingClientRect方法

          const rect=contentElement.getBoundingClientRect() || {};
          const topDistance=rect.top;
          return topDistance;
          

          Untitled6.png

          計算h2:offsetHeight方法

          Untitled7.png

          值得注意的是,因為打印區(qū)域的html元素不一定是從窗口頂部開始,所以為了計算實際的h1(元素到打印區(qū)域的頂部距離),可以采用這樣的方法:

          • getBoundingClientRect方法計算元素到窗口頂部的距離
          • 循環(huán)打印之前將pages信息針對第一個元素進行一個高度校準(zhǔn)。
          // 對pages進行一個值的修正,因為pages生成是根據(jù)根元素來的,根元素并不是我們實際要打印的元素,而是element,
            // 所以要把它修正,讓其值是以真實的打印元素頂部節(jié)點為準(zhǔn)
            const newPages=pages.map((item)=> item - pages[0]);
          

          在線demo演示和源代碼

          上述即是在實現(xiàn)前端頁面生成pdf的過程中遇到的問題,以及解決思路。

          為了更直觀得感受效果,本文也給出了不同場景(單頁、多頁、多頁截斷、自定義頁眉頁腳、橫向)下的pdf生成效果,可以通過此鏈接體驗:https://pdf-demo-phi.vercel.app/

          此demo的源代碼如下:pdf-demo

          與現(xiàn)有文章不同的是,本倉庫的代碼特點在于:

          • 支持設(shè)置pdf打印的方向,比如橫向
          • 修正了高度計算問題,解決了多出一個空白頁問題。掘金那篇文章計算元素高度時候沒有減去容器距離頂部高度,所以導(dǎo)致很多新手使用那份代碼的時候,會發(fā)現(xiàn)自己的頁面頂部被裁剪到了,原因就是這個
          • 支持自定義頁眉頁腳
          • 支持?jǐn)U展自定義分頁方法,如果遇到復(fù)雜的組件,可以自定擴展邏輯計算高度

          作者:燕平

          來源:微信公眾號:Goodme前端團隊

          出處:https://mp.weixin.qq.com/s/-1nA-VI6kmgqHRcYs_NZFA

          昨天介紹了Oracle分頁實現(xiàn)方案,那么,mysql又是如何實現(xiàn)分頁呢?

          參考官網(wǎng):https://dev.mysql.com/doc/refman/5.7/en/select.html


          mysql分頁實現(xiàn)

          MySQL中實現(xiàn)分頁查詢:在數(shù)據(jù)量較小的情況下可使用limit查詢來實現(xiàn)分頁查詢,在數(shù)據(jù)量大的情況下使用建立主鍵或唯一索引來實現(xiàn),另外可通過order by對其排序。

          The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants, with these exceptions:

          • Within prepared statements, LIMIT parameters can be specified using ? placeholder markers.
          • Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables.

          1、limit分頁實現(xiàn)

          先看一下limit語法

          SELECT * FROM TABLE
              [ORDER BY {col_name | expr | position}
                [ASC | DESC], ... [WITH ROLLUP]]
              [LIMIT {[offset,] row_count | row_count OFFSET offset}]

          LIMIT子句可以被用于強制 SELECT 語句返回指定的記錄數(shù)。LIMIT接受一個或兩個數(shù)字參數(shù)。參數(shù)必須是一個整數(shù)常量。
          如果給定兩個參數(shù),第一個參數(shù)指定第一個返回記錄行的偏移量,第二個參數(shù)指定返回記錄行的最大數(shù)目。初始記錄行的偏移量是 0(而不是 1)。

          1.1、傳統(tǒng)實現(xiàn)方式

          一般情況下,客戶端通過傳遞 pageNo(頁碼)、pageSize(每頁條數(shù))兩個參數(shù)去分頁查詢數(shù)據(jù)庫中的數(shù)據(jù),在數(shù)據(jù)量較小(元組百/千級)時使用 MySQL自帶的 limit 來解決這個問題

          --pageNo:頁碼
          --pagesize:每頁顯示的條數(shù)
          select * from table limit (pageNo-1)*pageSize,pageSize;

          1.2、建立主鍵或者唯一索引(高效)

          在數(shù)據(jù)量較小的時候簡單的使用 limit 進行數(shù)據(jù)分頁在性能上面不會有明顯的緩慢,但是數(shù)據(jù)量達到了 萬級到百萬級 sql語句的性能將會影響數(shù)據(jù)的返回。這時需要利用主鍵或者唯一索引進行數(shù)據(jù)分頁;

          --pageNo:頁碼
          --pagesize:每頁顯示的條數(shù)
          --假設(shè)主鍵或者唯一索引為 t_id
          select * from table where t_id > (pageNo-1)*pageSize limit pageSize; 

          1.3、基于數(shù)據(jù)再排序

          當(dāng)需要返回的信息為順序或者倒序時,對上面的語句基于數(shù)據(jù)再排序。order by ASC/DESC 順序或倒序 默認(rèn)為順序

           select * from table where t_id > (pageNo-1)*pageSize order by t_id limit pageSize; 



          2、查詢顯示行號(實現(xiàn)類似Oracle數(shù)據(jù)庫的ROWNUM())

          Oracle中有專門的rownum()顯示行號的函數(shù),而MySQL沒有專門的顯示行號函數(shù),但可以通過用@rownum自定義變量顯示行號。

          一般實現(xiàn)過程如下:

          SELECT 
            (@rownum :=@rownum + 1) AS rownum,
            t.* 
          FROM
            table t,
            (SELECT @rownum :=0) AS rn



          3、實例演示

          3.1、環(huán)境準(zhǔn)備

          CREATE TABLE t (
          	EMPNO BIGINT ( 4 ) NOT NULL,
          	ENAME VARCHAR ( 10 ),
          	JOB VARCHAR ( 9 ),
          	MGR BIGINT ( 4 ),
          	HIREDATE date,
          	SAL BIGINT ( 10 ),
          	COMM BIGINT ( 10 ),
          	DEPTNO BIGINT ( 2 ),
          	PRIMARY KEY ( `EMPNO` ) 
          ) ENGINE=INNODB;
          INSERT INTO t VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980-12-17', '800', NULL, '20');
          INSERT INTO t VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600', '300', '30');
          INSERT INTO t VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250', '500', '30');
          INSERT INTO t VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975', NULL, '20');
          INSERT INTO t VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250', '1400', '30');
          INSERT INTO t VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850', NULL, '30');
          INSERT INTO t VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450', NULL, '10');
          INSERT INTO t VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-04-19', '3000', NULL, '20');
          INSERT INTO t VALUES ('7839', 'KING', 'PRESIDENT', NULL, '1981-11-17', '5000', NULL, '10');
          INSERT INTO t VALUES ('7844', 'TURNER', 'SALESMAN', '7698', '1981-09-08', '1500', '0', '30');
          INSERT INTO t VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-05-23', '1100', NULL, '20');
          INSERT INTO t VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950', NULL, '30');
          INSERT INTO t VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000', NULL, '20');
          INSERT INTO t VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', NULL, '10');
          commit;

          3.2、limit分頁

          --查詢第一頁,每頁顯示5條數(shù)據(jù)
          select * from t order by empno desc limit (1-1)*5,5;
          
          --查詢第二頁,每頁顯示4條數(shù)據(jù)
          select * from t order by empno desc limit (2-1)*4,4; 

          3.3、查詢顯示行號

          --查詢第二頁,每頁顯示4條數(shù)據(jù),并在第一列加上行號
          select (@rownum :=@rownum + 1) AS rownum,t.* from t,
            (SELECT @rownum :=0) AS rn 
          order by t.empno desc 
          limit 4,4; 



          覺得有用的朋友多幫忙轉(zhuǎn)發(fā)哦!后面會分享更多devops和DBA方面的內(nèi)容,感興趣的朋友可以關(guān)注下~


          主站蜘蛛池模板: 亚洲中文字幕无码一区| 无码中文字幕一区二区三区| 风间由美性色一区二区三区| 成人欧美一区二区三区在线视频| 日本一区二区三区高清| 无码人妻一区二区三区免费视频 | 无码精品黑人一区二区三区| 一区二区三区视频观看| 日韩精品福利视频一区二区三区| 亚洲欧洲精品一区二区三区| 无码欧精品亚洲日韩一区| 清纯唯美经典一区二区| 好爽毛片一区二区三区四| 一区二区3区免费视频| 成人在线视频一区| 日韩国产一区二区| 一区二区三区四区精品| 日韩A无码AV一区二区三区| 国产一区二区三区视频在线观看| 日韩美一区二区三区| 国产在线一区二区三区在线| 日本一区二区三区日本免费| 无码少妇一区二区三区芒果| 日韩伦理一区二区| 一区二区三区亚洲视频| 久久久久人妻一区精品果冻| 91精品一区国产高清在线| 亚洲日韩精品无码一区二区三区| 国产亚洲无线码一区二区 | 蜜臀Av午夜一区二区三区| 农村乱人伦一区二区| 麻豆一区二区免费播放网站| 最新欧美精品一区二区三区 | 国产在线精品一区二区三区不卡 | 日韩一区二区电影| 亚洲一区二区在线视频| 无码人妻精品一区二区蜜桃网站| 久久精品无码一区二区三区免费| 国产精品一区二区香蕉| 中文字幕在线观看一区二区三区| 亚洲日韩国产精品第一页一区|