SQL: select 从存储过程返回的不同列

SQL: select different columns to be returned from a stored procedure

假设我有一个包含多个列的 table 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
...

我创建了一个存储过程,其中 returns 来自这个 table 的数据。问题是有时我只需要 return 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语句会使查询非常笨拙,我想避免这种情况)

是否有基于开关的 select 列的简单方法?如果不是,您会推荐什么方法来 return 来自存储过程的不同列数?

编辑:抱歉,我很遗憾 table 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 可能不起作用的原因

更新:我接受了动态 SQL 的答案,但我所做的是以下内容:

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

对于每个可选列。然后我 return table 使用

select * from my_table

这会根据开关提供不同数量的列

一种方法是使用动态 SQL。这是伪SQL,因为这里缺少信息来获得完整的答案。它也未经测试,因为我没有 much/any 数据来真正 运行 这个反对。

--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*/;

确保在使用动态 SQL 时正确设置查询参数。 不要 连接你的字符串!!!

例如,正确的格式是 N'WHERE yourColumn = @yourParam AND OtherColumn = @otherParam',然后在 sp_executesql 中提供 @yourParam@otherParam 的值(正如我在评论中所展示的那样) .

但是,不要这样做: N'WHERE yourColumn = ''' + @myParam + N''' AND otherColumn = ' + CONVERT(varchar(5),@secondParam)。这将对 SQL 注入开放(这不是你的朋友)。

我会将存储过程更改为 table 值函数并修改外部 "select from".

例如:

if($value1 === 1)
  $sql = "SELECT c1, c2 FROM dbo.my_udf";
elseif($value1 ===2)
  $sql = "SELECT c1, c3, c4 FROM dbo.my_udf";