Sql server SQL Server 2012按未知列的分页顺序

Sql server SQL Server 2012按未知列的分页顺序,sql-server,database,sql-server-2012,Sql Server,Database,Sql Server 2012,我正在尝试创建一个查询,返回通用表中的行分页,因为调用此查询的调用将在更多的表和数据库上工作;我正在使用的程序在代码的不同部分构建了查询,数据库接收的唯一可变参数是@myTable、@offset和@row 最初,我尝试对这样一个表进行查询 SELECT * FROM myTable ORDER BY myPKColumn OFFSET @offset ROWS FETCH NEXT @row ROWS ONLY; 使用@offset=0和@row=10,将前10行ASC返回给我 到目前为止,

我正在尝试创建一个查询,返回通用表中的行分页,因为调用此查询的调用将在更多的表和数据库上工作;我正在使用的程序在代码的不同部分构建了查询,数据库接收的唯一可变参数是@myTable@offset@row

最初,我尝试对这样一个表进行查询

SELECT * FROM myTable ORDER BY myPKColumn
OFFSET @offset ROWS
FETCH NEXT @row ROWS ONLY;
使用@offset=0和@row=10,将前10行ASC返回给我

到目前为止,它可以正常工作,但如果我需要对每个表使用此查询,那么在ORDERBY子句中指定列时就会遇到问题;为了避免这个问题,我尝试了这个查询

SELECT * FROM @myTable ORDER BY (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME=@myTable and CONSTRAINT_NAME like 'PK_%')
OFFSET @offset ROWS
FETCH NEXT @row ROWS ONLY;
这是因为我从项目结构中知道,我可以调用的所有表都有一个主键

查询工作正常,但结果有点奇怪:如果我传递与前一个查询相同的参数,结果是从11到2 DESC的行

另外,更改偏移值时,我计算出了这种奇怪的关系:

如果[@偏移量

结果是没有第一行的第一个(@row+1)描述

(在这种情况下,@row和@offset之间的所有行将永远不会被检索)

否则 >

结果是从(@offset+1)开始的第一个@行

示例:

   @offset = 90 and @row = 10 return rows from 13 to 2

   @offset = 91 and @row = 10 return rows from 92 to 101

   @offset = 101 and @row = 10 return rows from 102 to 111
我尝试了一些小的变化,比如在第二个select之外指定OBJECT_ID(…)或OBJECT_NAME(OBJECT_ID(…),但没有任何更改;此外,我还尝试使用debug选项,但我没有使用它的权限

你知道是什么导致了这种奇怪的结果吗

附言:很抱歉我的英语不好,而且这是我的第一篇文章,所以,如果我遗漏了什么,我会毫无问题地编辑

编辑:

我找到了一种合乎逻辑的方法,但它不起作用:

我发现写一个查询

SELECT * FROM myTable ORDER BY 5 asc;
考虑到第5列的值,将我的行排序为上升

所以我提出了一个问题:

select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'myTable' and COLUMN_NAME = (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='myTable' and CONSTRAINT_NAME like 'PK_%')
返回带有主键的列的位置(不幸的是,对于我来说,有很多表不在第一个位置);返回的值是正确的(我已经验证了很多表,并且总是有效)

那么,下一步,如果我运行查询

select * from mytable ORDER BY (select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'myTable' and COLUMN_NAME = (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='myTable' and CONSTRAINT_NAME like 'PK_%' )) asc;
select * from mytable ORDER BY (select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'myTable' and COLUMN_NAME = (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='myTable' and CONSTRAINT_NAME like 'PK_%' )) asc
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;
解决一个小问题:我可以声明asc或desc,但结果总是asc(这不是一个真正的问题,因为之前说过的顺序在我的案例中并不重要)

现在才是真正的问题

最后一步是查询

select * from mytable ORDER BY (select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'myTable' and COLUMN_NAME = (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='myTable' and CONSTRAINT_NAME like 'PK_%' )) asc;
select * from mytable ORDER BY (select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'myTable' and COLUMN_NAME = (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='myTable' and CONSTRAINT_NAME like 'PK_%' )) asc
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;
在这里,编辑之前的问题没有改变:结果是从11到2的行

为了避免错误可能是返回的数字的字符串解释,我在int中添加了一个cast

SELECT * FROM myTable
ORDER BY CAST((select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'myTable' and COLUMN_NAME = (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='myTable' and CONSTRAINT_NAME like 'PK_%' ))AS int) asc 
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;
但一切都没有改变


在添加偏移量/提取量之前,新查询似乎可以正常工作。

在排序依据中不能有动态列。
排序依据(选择列名称)
生成一个非确定性顺序,因为行是按列名称排序的,所有行的顺序相同。因此,引擎基本上可以按任何顺序返回任何行,因此查询之间的偏移没有关系,这解释了结果。(您也不能在
FROM
中使用动态表名,因此我不清楚您的查询是如何工作的,除非您进行文本替换,或者它是一个表变量。)。order by对于查询来说并不重要,但是如果没有偏移量FETCh就无法工作;因此我决定使用主键,我确信它可以在我需要工作的每个表中找到。对于查询,可能我滥用了@;我的意思是,上面的程序可以从pippo order by传递一个类似SELECT*的查询(…WHERE TABLE_NAME='pippo'和CONSTRAINT_NAME(如'PK_%')偏移量为0的行仅获取接下来的50行;或类似SELECT*的查询从pluto ORDER BY(…WHERE TABLE_NAME='pluto'和CONSTRAINT_NAME(如'PK_%'))偏移50行仅获取接下来的20行;这种方法不起作用,也无法起作用。您的查询有效地按“myPKColumn”排序,这与按myPKColumn排序不同。前者的“顺序”所有行按同一字符串排序,后一行按实际列内容排序。要在运行时按不同列排序,需要使用动态SQL,首先确定列名,然后在该列上使用
order by
构建一个新查询。新尝试失败的原因与上一次尝试失败的原因大致相同-有一个特定的规定用于表示列序号的
ORDER BY
子句中的整数常量。任何其他类型的表达式,包括子查询等,都使用该表达式返回的值作为排序值。
按5排序
SELECT
子句中的第五列排序。
当1=1时按大小写排序,然后按5结束
排序t因为每一行都被分配了值
5
,用于排序,所以它可以任意行。
ORDER BY
仅当列号是整数文本时才起作用。如果尝试其他变体(如
(CAST(1 AS INT))
@var
,将
@var
设置为常量
1
,等等。)想一想就想一想,但如果没有动态SQL,这真的是做不到的。