【问题标题】:Limit the number of rows returned on the server side (forced limit)限制服务器端返回的行数(强制限制)
【发布时间】:2010-05-20 13:32:15
【问题描述】:

所以我们有一个软件,它的 SQL 语句写得不好,导致表中的每一行都被返回。表中有几百万行,因此这会导致我们的客户端机器出现严重的内存问题和崩溃。供应商正在为该问题创建补丁程序,但仍需几周时间。同时,我们试图找出一种方法来限制服务器端返回的结果数量,作为临时修复。

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

提前谢谢你。

编辑

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

【问题讨论】:

  • 这个临时修复会破坏应用程序吗?你知道这些数据是如何被使用的吗?
  • 重命名表并将其替换为执行SELECT TOP x * FROM new_name_of_the_table 的视图。但是请注意,应用程序执行的数据操作(INSERT、UPDATE、DELETE)之后会失败。
  • @Heinzi 不幸的是,我们需要能够插入、更新和删除。
  • 为什么在Client应用程序中形成SQL语句?如果 SQL 是在客户端应用程序中形成的,而您没有这方面的源代码,我看不出您将如何限制返回的行数。
  • @Ardman 因此我问这个问题,我想知道是否有设置或方法对数据库端设置硬限制。

标签: sql-server sql-server-2008 client-server


【解决方案1】:

一种可能的解决方案是

  • 重命名有问题的表
  • 使用原始表名创建updatable view
  • 使用SELECT TOP x * FROM OffendingTable 作为视图定义

因此,客户端在选择数据时不会意识到更改。


使用query governor

如果您不介意对有问题的查询不返回任何数据,查询调控器允许您这样做。

【讨论】:

  • 很好的建议,类似于 Heinzi 的评论,但是在应用程序中插入、更新和删除语句将不起作用。
  • @evolve,它变得更加困难,但您应该阅读可更新视图。我不知道是否可以满足您的要求,但我相信是的。
  • 这几乎成功了,插入/更新/删除工作没有问题,但是如果你执行 SELECT top 100 * FROM {table} 它总是返回前 100 名,它不会基于顶部100 关闭正在执行的查询。有时他们在查询中有 WHERE 语句需要工作。不过这么近。
  • @evolve,因为没有任何类型的事件可以让您在将整个结果集返回给客户之前“按摩”整个结果集,所以 Marcus Adams 给出的答案是唯一可以真正做到的工作。
  • 同意,不过感谢您的建议,因为这是我问题的最佳解决方案,我将其标记为已接受。
【解决方案2】:

必须有一个命令。

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

我想我听说你可以在 MSSQL 中写:

选择 TOP 10,20 ... 或类似的东西

这意味着您选择 20 行,我认为以 10 开头

【讨论】:

    【解决方案3】:

    你可以使用选择顶部

    SELECT TOP 50 PERCENT * FROM Persons(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,' +@SelectList  +   
                                            ' 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
    

    【讨论】:

    • 听起来好像他无权访问SQL
    【解决方案4】:

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

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

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

    【讨论】:

    • +1。作为一个超级解决方案,这会很酷。我怀疑它在一个小时内是否可行,但它肯定是可行的。
    • 很酷的解决方案,但不合理。
    • @Evolve,我已经将此解决方案用于其他类型的生产系统。诚然,我没有将它用于数据库系统,但我会。
    【解决方案5】:

    您可以从表中删除除 X 之外的所有记录并将它们存储在其他位置

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 2017-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多