# 关于数据库分页查询 在前面的章节中介绍了如下的链式调用方式来获取查询结果集的部分切片。 ~~~ //例如以下例子,是取结果集的第1条到第50条记录 results, err := engine.Sql(sql).Query().ListPage(1,50) ~~~ 但这并不是数据库分页查询,而是将查询结果集获取到本地取部分切片。 xorm也同样支持数据库分页查询,有如下四种方式: * 方式一:orm方式数据库分页查询 使用Limit函数进行数据库分页查询,Limit(int, …int)限制获取的数目,第一个参数为条数,第二个参数表示开始位置,如果不传则为0 ~~~ var log []Log err = engine.Limit(5, 2).Find(&log) ~~~ * 方式二:执行原生sql语句方式数据库分页查询 使用Sql,SqlMapClient,SqlTemplateClient函数执行原生sql语句进行数据库分页查询。 ~~~ results, err := engine.Sql("SELECT * FROM log LIMIT ? OFFSET ?", 5, 2).Query().List() var log []Log err := engine.Sql("SELECT * FROM log LIMIT ? OFFSET ?", 5, 2).Find(&log) ~~~ * 方式三:使用原生sql语句配合Limit函数或OrderBy函数方式进行数据库分页查询 有时,我们需要跨表查询多张表或者join多张表进行数据库分页查询,而oracle和mssql数据库分页语句相对复杂和多样,我们希望更关注业务逻辑,此时可以使用原生sql语句配合Limit函数或OrderBy函数方式进行数据库分页查询。 对于oracle,postgresql,mysql等数据库,可以使用原生sql语句配合Limit函数进行数据库分页查询。注意,这些数据库并不支持像mssql数据库那样使用原生sql语句配合Limit函数及OrderBy函数进行数据库分页查询。 ~~~ results, err := engine.Sql("SELECT * FROM log").Limit(5, 2).Query().List() var ptlog []PtTimelineLog err = engine.Sql("SELECT * FROM log").Limit(5, 2).Find(&ptlog) ~~~ 对于postgresql,mysql数据库生成的分页查询sql语句为 ~~~ SELECT * FROM log LIMIT 5 OFFSET 2 ~~~ 在oracle数据库中同样也可以使用以上方式进行数据库分页查询,举例如下: ~~~ querySql := "QUERY_EQU_ALL_RFID" //sqlmap id deviceCode:= "210601" //设备编号 pageNumber:=2 //第2页 pageItemNumber:=10 //每页显示数量 first := (pageNumber - 1) * pageItemNumber results, err := engine.SqlMapClient(querySql, deviceCode).Limit(pageItemNumber, first).Query().List() ~~~ sqlmap中配置的sql语句如下: ~~~ SELECT ID,EQU_ID,EQU_NAME,EQU_TYPE_CODE,EQU_TYPE_NAME,COMPONENT_CODE,COMPONENT_NAME,RFID,RFID_VERIFY,ISSUE_TIME,VERIFY_TIME,POS_X,POS_Y,ACCOUNT,ACCOUNT_NAME from VIEW_EQU_ALL_RFID where EQU_TYPE_CODE=? ~~~ oracle数据库生成执行的分页查询SQL语句如下,其中xormdvCEQcJ97XQYsAcy36rehK是一个ROWNUM伪列,查询返回结果集[]map[string]interface{}中将不会存在,如果使用Find函数返回结果集,定义的结构体中无需定义此字段 ~~~ SELECT aat.* FROM (SELECT at.*,ROWNUM xormdvCEQcJ97XQYsAcy36rehK FROM (SELECT ID,EQU_ID,EQU_NAME,EQU_TYPE_CODE,EQU_TYPE_NAME,COMPONENT_CODE,COMPONENT_NAME,RFID,RFID_VERIFY,ISSUE_TIME,VERIFY_TIME,POS_X,POS_Y,ACCOUNT,ACCOUNT_NAME from VIEW_EQU_ALL_RFID where EQU_TYPE_CODE='210601') at WHERE ROWNUM <= 20) aat WHERE xormdvCEQcJ97XQYsAcy36rehK > 10 ~~~ 对于mssql数据库,由于数据库分页语句的本身的特性,可以使用原生sql语句配合Limit函数及OrderBy函数进行数据库分页查询。注意,在mssql数据库中这种方式进行数据库分页查询,Limit函数及OrderBy函数必须一起使用。 ~~~ //示例1 results, err := engine.Sql("select t_tx_counts.id,t_tx_counts.count,t_tx_code.code from t_tx_code,t_tx_counts where t_tx_code.id=t_tx_counts.id and t_tx_code.id>?", 2). OrderBy("count").Limit(5, 1).Query().List() //示例2 var results []Result err = engine.Sql("select t_tx_counts.id,t_tx_counts.count,t_tx_code.code from t_tx_code,t_tx_counts where t_tx_code.id=t_tx_counts.id and t_tx_code.id>?", 2). OrderBy("id DESC").Limit(5, 0).Find(&results) ~~~ 示例1生成的sql语句如下,其中xormv2rGnVAWh4qPT5Qntkt4PZ是一个ROW_NUMBER伪列,查询返回结果集[]map[string]interface{}中将不会存在,如果使用Find函数返回结果集,定义的结构体中无需定义此字段 ~~~ SELECT sq.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY count) AS xormv2rGnVAWh4qPT5Qntkt4PZ, T_TX_COUNTS.ID,T_TX_COUNTS.COUNT,T_TX_CODE.CODE FROM T_TX_CODE,T_TX_COUNTS WHERE T_TX_CODE.ID=T_TX_COUNTS.ID AND T_TX_CODE.ID>2) AS sq WHERE xormv2rGnVAWh4qPT5Qntkt4PZ BETWEEN 2 AND 6 ~~~ 示例2生成的sql语句如下 ~~~ SELECT TOP 5 T_TX_COUNTS.ID,T_TX_COUNTS.COUNT,T_TX_CODE.CODE FROM T_TX_CODE,T_TX_COUNTS WHERE T_TX_CODE.ID=T_TX_COUNTS.ID AND T_TX_CODE.ID>2 ORDER BY id DESC ~~~ * 方式四:使用sql builder来构建sql语句进行数据库分页查询。 sql builder相关内容请阅读原版xorm提供了一个SQL Builder库 [github.com/go-xorm/builder](https://github.com/go-xorm/builder)