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 id
和 data
列,有时我需要其他信息,例如 description
、created_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";
假设我有一个包含多个列的 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 id
和 data
列,有时我需要其他信息,例如 description
、created_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";