SQL:选择要从存储过程返回的不同列

时间:2018-06-22 10:01:36

标签: sql sql-server stored-procedures dynamic-columns

假设我有一个包含多列的表mytable(这不是完全正确,请参见“编辑”):

mytable
id    data        description          created_at      viewed_times
1      10        'help wanted'      '20180101 04:23'       45
2      20    'customer registered'  '20180504 03:12'        1
...

我创建了一个存储过程,该过程从该表返回数据。问题在于,有时我需要它仅返回iddata列,有时我还需要其他信息,例如descriptioncreated_at等。

我的想法是创建三个伪变量@display_description@display_created_date@display_viewed_times。当虚拟变量等于1时,我显示相应的列。例如,对于命令

exec my_procedure @display_description = 1

我希望输出

id    data        description        
1      10        'help wanted'      
2      20    'customer registered'  
...

我在过程中如何实现它:

if @display_description = 1
    select id, data, description from mytable
else 
    select id, data from mytable

问题是,如果我想拥有3个开关(每列一个),则必须在if语句中编写8个条件。 (我的select语句很复杂。此外,如果要显示viewed_times之类的某些列,则必须对其进行计算。因此,编写许多if语句会使查询成为可能。非常笨拙,我想避免这种情况)

是否有一种简单的方法可以根据开关选择列?如果没有,您建议采用哪种方法从存储过程中返回不同数量的列?

编辑:对不起,我很抱歉表mytable已经包含所有列。事实并非如此,其中一些列必须在显示之前进行计算。例如,列viewed_times不存在。要显示它,我需要执行以下操作:

if @display_description = 1
    ~ several selects to calculate the column viewed_times ~
    select id, data, description from mytable join table in which I just calculated the viewed_times column
else 
    select id, data from mytable

计算这些列非常耗时,只有在需要显示这些列时,我才想这样做。

这就是为什么动态SQL可能无法工作的原因

更新:我接受了Dynamic SQL的答案,但是我做了以下事情:

if @display_viewed_times = 1
begin   
    ~ calculate column viewed_times ~
    update my_table 
    ~ add column viewed_times to the table my_table ~
end

用于每个可选列。然后我用

返回表
select * from my_table

这给了我不同的列数

2 个答案:

答案 0 :(得分:1)

一种方法是使用动态SQL。这是伪SQL,因为这里没有信息来获得完整答案。它也未经测试,因为我没有太多/任何数据可以对此进行真正的测试。

--Your input parameters
DECLARE @description bit, @createdate bit, @viewedtimes bit /*...etc...*/;

--Now the SP
DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT ' +
           STUFF(CONCAT(N','+ NCHAR(10) + N'       ' + CASE WHEN @description = 1 THEN QUOTENAME(N'description') END,
                        N','+ NCHAR(10) + N'       ' + CASE WHEN @createdate = 1 THEN QUOTENAME(N'created_at') END,
                        N','+ NCHAR(10) + N'       ' + CASE WHEN @viewedtimes = 1 THEN QUOTENAME(N'viewed_times') END),1,9,N'') + NCHAR(10) +
           N'FROM YourTable' + NCHAR(10) + 
           N'WHERE...;';
PRINT @SQL; --your best debugging friend.
EXEC sp_executesql @SQL /*N'@someParam int', @someParam = @inParam*/;

使用Dyanmic SQL时,请确保正确设置查询的参数。 不要连接字符串!

例如,正确的格式应为N'WHERE yourColumn = @yourParam AND OtherColumn = @otherParam',然后在@yourParam中提供@otherParamsp_executesql的值(正如我在评论中已演示的那样)。

请勿执行以下操作: N'WHERE yourColumn = ''' + @myParam + N''' AND otherColumn = ' + CONVERT(varchar(5),@secondParam)。这将对SQL注入开放(不是您的朋友)。

答案 1 :(得分:1)

我将存储过程更改为表值函数,并修改外部的“ select from”。

例如:

<div class="header">
</div>

please comment the above code technical -> views -> internal_layout

after call to internal_layout like this 

<t t-call="web.internal_layout">
                <t t-foreach="docs" t-as="o">
                    <div class="page" style="font-family: 'helvetica'; font-size: 8pt;">
                        <div class="header">