【问题标题】:Fetch more SELECT data based on input根据输入获取更多 SELECT 数据
【发布时间】:2021-08-28 18:17:01
【问题描述】:

似乎是一个简单的答案,但与我发现的情况相去甚远,使用存储过程可能不可行。

只是想问一下,因为可能有一个优雅的解决方案.... (顺便说一句:我在 SQL Server 2014 上运行我的数据库)

我有一个非常简单的选择

select companyID, companyName 
from tblCompanies

但在某些情况下,我需要获取更大的数据集

select companyID, companyName, companyAddress, companyCountry 
from tblCompanies

当然这可以通过创建多个存储过程来完成

  • getCompaniesLite
  • getCompaniesBasic
  • getCompaniesFull 等

也可以传递一个参数并使用 IF-ELSE 在完全不同的 SELECTS 中进行选择。

不过,这两种方法看起来都很麻烦,存在大量重复和可维护性问题..

也许有一种方法可以根据输入值获取特定列,例如像这样:

select 
    companyID, companyName, 
    case when @FULL = 1 then companyAddress end 
from tblCompanies

【问题讨论】:

  • 如果您所做的只是返回表列的子集,您的存储过程的粒度可能是错误的。

标签: sql sql-server stored-procedures optimization


【解决方案1】:

看起来你想多虑了。你会节省多少时间。这个样本公司大概是毫秒?但是请考虑更大的下游,以了解您系统的其余部分。由于数据缓存,在不同时间做一些定时查询并记录统计信息。因此,有一天对您将调用的实际查询进行缩写,另一天(或同一天晚些时候)对所有列进行。您真正节省了多少。

此外,获取更复杂/详细/JOIN 查询并执行类似操作。您节省了多少时间。

现在,想想界面。仅仅因为您有 10 个可用字段并且只想显示 2 个,这足以让用户界面仅显示这些字段。但是,如果用户更改为详细视图,您已经有了显示所有 10 个字段的数据,而无需返回数据库再次查询,这并没有破坏较小集仅节省一两秒的目的。

从维护的角度来看,我认为您为此寻找的东西不值得。

现在,如果有一些表包含机密数据,那么是的,我将从非机密的完整数据查询与包含机密数据的完整数据开始,但这些将视具体情况而定无论如何。

【讨论】:

    【解决方案2】:

    如果您只需按照示例中的说明在不同的列中获取结果,那么最简单的方法可能是根据需要简单地生成尽可能多的视图而不使用过程,但这在某种程度上取决于其余的您需要在逻辑中执行的操作。

    CompaniesBasic_View

    SELECT companyID, companyName
    FROM tblCompanies
    

    CompaniesLite_View(非相关)

    SELECT companyID, companyName, companyAddress
    FROM tblCompanies
    

    CompaniesFull_View(非相关)

    SELECT companyID, companyName, companyAddress, companyCountry 
    FROM tblCompanies
    

    如果您认为这样可以让您更轻松地进行维护,您甚至可以生成相对于前一个视图的每个视图。这样,当您向基本视图添加新列时,它们将直接出现在它们的相对视图中。 (权衡此选项的优缺点,并根据查询的复杂性注意性能)。

    CompaniesBasic_View

    SELECT companyID, companyName
    FROM tblCompanies
    

    CompaniesLite_View(相对)

    SELECT cb.*, tblCompanies.companyAddress
    FROM CompaniesBasic_View cb, tblCompanies
    WHERE cb.companyID = tblCompanies.companyID
    

    CompaniesFull_View(相对)

    SELECT cl.*, tblCompanies.companyCountry
    FROM CompaniesLite_View cl, tblCompanies
    WHERE cl.companyID = tblCompanies.companyID
    

    以后,如果您需要执行更复杂的操作,您可以在存储过程中使用这些视图。为此,只需将所需视图的名称作为参数传递并直接通过 EXEC 执行即可。

    CREATE PROCEDURE [dbo].[DoSomethingWithCompanies] (
        @myView Varchar(50)
    ) AS
    BEGIN
        SET @myQuery = 'SELECT * FROM ' + @myView ;
        EXEC @myQuery;
    
        -- Do things
    END;
    

    【讨论】:

    • 我相信这会导致更多的噩梦维护。特别是如果编写查询并且需要使用连接等进行优化。最好只抓住几个额外的列并在生产中忽略它们而不是尝试维护版本。此外,如果未针对系统表验证/限定为已知合法视图,则将视图变量传递给存储过程并执行可能会很危险。
    猜你喜欢
    • 2016-11-16
    • 2014-04-22
    • 1970-01-01
    • 2023-04-04
    • 2020-08-11
    • 2017-03-27
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多