如何在新的 Rails 和 SQL Server 适配器版本:7.1.0 中成功使用带有子查询的 limit() 方法

问题描述 投票:0回答:1

实际行为

似乎

limit()
没有添加到生成的子查询中,它实际上是一个
Model::ActiveRecord_Relation
,而是尝试执行抛出错误的“

ActiveRecord::StatementInvalid 异常表不存在并返回nil

代码以及如何获取问题

class Doc < ApplicationRecord
  has_many :doc_dirs

  has_many :dirs, through: :doc_dirs

  default_scope -> { where(inactive: false, is_version_1: true)}

  scope :doc_collection, -> do
    str_sql = "( SELECT * FROM [D_docs] ) [D_docs]"
    doc_collec = Doc.from(str_sql).limit(10)
    # byebug
    doc_collec
  end
end

在 Rails 控制台上,如果您在结果

doc_collec = from(sql)
doc_collec

之间添加调试

运行

doc_collec = from(sql).to_sql
你会得到:

ActiveRecord::StatementInvalid 异常:表 '( SELECT * FROM [D_docs] ) [D_docs]' 不存在

应该注意的是

Doc.from(str_sql).to_sql
给出:
SELECT [D_docs].* FROM ( SELECT * FROM [D_docs] ) [D_docs]
一个正确且没有错误的查询和较旧的 Rails 版本 (6.1.7) 和 SQL Server 适配器版本 6.x.x 成功生成了我们想要获取的查询

SELECT [D_docs].* FROM ( SELECT * FROM [D_docs] ) [D_docs] OFFSET 0 FETCH NEXT 10 ROWS ONLY

Doc.from(str_sql).order(:pkid)
按预期工作

详情

  • Rails 版本
    7.1.2
  • SQL Server 适配器版本
    7.1.0
  • TinyTDS版本
    2.1.x

doc_collec.to_sql 应该是:

SELECT [D_docs].* FROM ( SELECT * FROM [D_docs] ) [D_docs] OFFSET 0 FETCH NEXT 10 ROWS ONLY
ruby-on-rails sql-server activerecord tiny-tds
1个回答
0
投票

您的问题不清楚:

  • [D_docs]
    是什么,因为看起来该表不存在?
  • 既然选择了整个表,为什么还需要子查询?
  • 您打算如何使用别名
    [D_docs]
    来使用它?

根据您的帖子,我做出以下假设(因为这是如上所述生成 SQL 代码的唯一方法)

class Doc < ApplicationRecord
  self.table_name = "D_docs"
end

话虽这么说,我们可以构建您想要的功能,如下所示:

 scope :doc_collection, -> do
    Doc.from(
      Arel::Nodes::TableAlias.new(
        Doc.all.arel,
        self.table_name)
    ).limit(10)
  end

这将导致:

SELECT 
  [D_docs].*
FROM 
  (SELECT 
     [D_docs].*
   FROM
     [D_docs]
  ) [D_docs] 
OFFSET 0 ROWS 
FETCH NEXT 10 ROWS ONLY

如果

D_Docs
不是实际的表名,那么任何运行的 SQL 都会很奇怪,但是我们可以按如下方式修改上面的内容:

 scope :doc_collection, -> do
    d_doc = Arel::Table.new('D_docs')
    Doc.from(
      Arel::Nodes::TableAlias.new(
        d_doc.project(d_doc[Arel.star]),
        self.table_name)
    ).limit(10)
  end

这会导致

SELECT 
  [docs].*
FROM 
  (SELECT 
     [D_docs].*
   FROM
     [D_docs]
  ) [docs] 
OFFSET 0 ROWS 
FETCH NEXT 10 ROWS ONLY
© www.soinside.com 2019 - 2024. All rights reserved.