限制在服务器端返回的行数(强制限制)

问题描述:

所以我们有一段软件,它有一个写得不好的SQL语句,导致表中的每一行都返回。表中有几百万行,所以这会导致严重的内存问题和客户机上的崩溃。供应商正在为这个问题创建一个补丁,但它仍然是几个星期。与此同时,我们试图找出一种限制在服务器端返回的结果数量的方法,只是将其作为临时修复。限制在服务器端返回的行数(强制限制)

我没有真正希望有一个解决方案,我环顾四周,并没有真正看到这样做的任何方式,但我希望有人可能有一个想法。

预先感谢您。

编辑

我忘了一个重要信息,我们的源代码不能访问,所以我们不能在形成SQL语句中的客户端进行更改。没有真正的服务器端组件,客户端只是直接访问数据库。任何解决方案基本上都需要一个过程,触发器或某种SQL-Server 2008设置/命令。

+0

将是临时的解决办法然而中断应用程序?你知道如何使用这些数据吗? – Paddy 2010-05-20 13:37:32

+2

重命名表并将其替换为执行'SELECT TOP x * FROM new_name_of_the_table'的视图。但是请注意,应用程序执行的数据操作(INSERT,UPDATE,DELETE)将会失败。 – Heinzi 2010-05-20 13:41:03

+0

@Heinzi很遗憾,我们需要能够插入,更新和删除。 – tplaner 2010-05-20 13:43:27

一个可能的解决方案可能是

  • 与原表名重命名违规表
  • 创建updatable view
  • 做一个SELECT TOP x * FROM OffendingTable作为您的视图定义

因此,客户端在选择数据时并不知道更改。


使用query governor

如果你不介意在所有的有问题的查询没有返回数据,查询管理器允许你这样做。

+0

非常好的建议,类似于Heinzi的评论,然而在应用程序中插入,更新和删除语句不起作用。 – tplaner 2010-05-20 13:47:07

+0

@evolve,它变得更加困难,但你应该阅读可更新的视图。我不知道你的要求是否可能,但我相信。 – 2010-05-20 13:56:38

+0

这几乎奏效,插入/更新/删除工作没有问题,但是,如果你做SELECT 100 * FROM {table}它总是返回顶部相同的前100,它并没有基于正在执行的查询的前100。有时他们在需要工作的查询中有WHERE语句。尽管如此。 – tplaner 2010-05-20 14:45:44

必须有一个命令。

我知道在MYSQL中是“LIMIT(firstindex,lastindex)”在sql语句的末尾。

我想我在MSSQL听说你可以这样写:

选择TOP 10,20 ......或者像这样

这将意味着你选择20排,10年初我认为

您可以使用select顶部

SELECT TOP 50%* FROM人(http://www.w3schools.com/sql/sql_top.asp

不要这样分页会帮你

CREATE PROCEDURE [dbo].[GetRequestedRecordByPage] 
@FromList nvarchar(200)    -- Table Name 
,@SortingCol nvarchar(200)   -- Sorting column Name 
,@SelectList nvarchar(200) = '*'   -- Select columns list 
,@WhereClause nvarchar(200) = ''  -- Where clause i.e condition 
,@PageNum int = 1       -- Requested page number 
,@PageSize int = 5     -- No of record in page 
,@TotalNoOfRecord int output   -- Total no of selected records 
AS 
Begin 
    SET NOCOUNT ON 
    DECLARE @Query nvarchar(max)   -- query going to be execute 

    IF rtrim(ltrim(@WhereClause)) <> '' 
    BEGIN 
     SET @Query ='SELECT @TotalNoOfRecord = COUNT(*) 
         FROM  ' + @FromList + ' 
     WHERE ' + @WhereClause 
    END 
    ELSE 
    BEGIN 
     SET @Query ='SELECT @TotalNoOfRecord = COUNT(*) 
         FROM  ' + @FromList 
    END 

    /* Count no. of record */ 
     EXEC sp_executeSQL 
     @Query, 
     @params = N'@TotalNoOfRecord INT OUTPUT', 
     = @TotalNoOfRecord OUTPUT 

DECLARE @lbound int, @ubound int 




/* Calculating upper and lower bound */ 
     SET @lbound = ((@PageNum - 1) * @PageSize) 
     SET @ubound = @lbound + @PageSize + 1 


/* Get list of record(s) */ 
     SELECT @Query = '' 
     SELECT @Query = 'SELECT * 
          FROM ( 
SELECT ROW_NUMBER() OVER(ORDER BY ' + @SortingCol + ') AS rownumber,' [email protected] + 
             ' FROM ' + @FromList 

     IF rtrim(ltrim(@WhereClause)) <> '' 
     BEGIN 
      SELECT @Query = @Query + ' WHERE ' + @WhereClause 
     END 

      SELECT @Query = @Query + ' ) AS tbl 
WHERE rownumber > ' + CONVERT(varchar(9), @lbound) + 
     ' AND rownumber < ' + CONVERT(varchar(9), @ubound) 

     EXEC (@Query)     
End 
+3

听起来好像他没有访问SQL – 2010-05-20 13:38:38

如果客户端使用TCP连接到数据库,则可以在服务器端的客户端和数据库服务器之间插入一个大多数透明的TCP代理服务器。然后,您可以重写来自客户端的任何违规查询(使用TOP或改进查询的一些方法)。

然后,您将SQL Server配置为在不同的端口上运行,启动您的代理服务于原始端口并将其连接到新端口上的SQL服务器。如果您知道客户端的始发IP地址,则可以使用端口转发,以便您可以将它们仅指向代理,并使数据库服务器保持原样。

我可以在一个小时内编写并测试它,但它确实需要一些套接字编程的知识。

+0

+1。作为一个ubergeek解决方案,这将是很酷的。我怀疑它在一个小时内是可行的,但它肯定是可行的。 – 2010-05-20 14:18:42

+0

很酷的解决方案,虽然不太合理。 – tplaner 2010-05-20 14:22:03

+0

@Evolve,我已将此解决方案用于其他类型的生产系统。无可否认,我并没有将它用于数据库系统,但我会这样做。 – 2010-05-20 14:41:35

你可以从表中删除所有,但X记录并将其存储在别处