将使用 exec 填充表的存储过程转换为标量值函数
Posted
技术标签:
【中文标题】将使用 exec 填充表的存储过程转换为标量值函数【英文标题】:Convert stored procedure which uses exec to populate table to scalar-valued function 【发布时间】:2016-11-23 21:20:26 【问题描述】:我有这个存储过程:
ALTER procedure [dbo].[sp_checker2]
(@Item varchar(70), @location varchar(8))
as
declare @Query varchar(2000)
set @location = 'XXX909'
declare @Table Table (Qty int)
set @Query = 'select TOP 1 * from openquery(xxxx,''SELECT NVL(b.t$st,0) from server.XXXXXID0001 a left join
server.XXXXXID0002 b on a.t$item = b.t$item where b.t$cloc = '''''+ @location + ''''' and trim(a.t$item)='''''+ @Item + ''''''')'
insert into @Table exec (@Query)
if not exists (select * from @Table )
begin
set @Query = 'select TOP 1 * from openquery(xxxx,''SELECT NVL(b.t$st,0) from server.XXXXXID0001 a
left join server.XXXXXID0002 b on a.t$item = b.t$item where trim(a.t$item) = '''''+ @Item + ''''''' )'
insert into @Table exec (@Query)
end
select * from @Table
问题是我正在寻找这样的查询SELECT
:
SELECT
column1, column2, column3, column4,
(EXEC [dbo].[sp_checker2] 'param1=value of column3', 'param2=another value') AS column5
FROM
table
WHERE
column1 = 'data1'
AND column2 = 'data2'
ORDER BY
column3
我知道在 SQL Server 的 SELECT
语句中执行存储过程是不可能的,我的替代方法是将存储过程转换为函数,但在存储过程内部我有一个 exec
到将数据插入表变量。有没有办法可以将此存储过程转换为函数?
附:我只在变量表中保存一行,即:如果项目存在,则保存其库存:“6500”
【问题讨论】:
旁注:您应该不为您的存储过程使用sp_
前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_
并使用其他东西作为前缀 - 或者根本不使用前缀!
谢谢@marc_s,我会在接下来的手术中考虑这个重要的事实。
您的查询中有前 1 个,但它们没有排序依据。这意味着无法确定将返回哪一行。
【参考方案1】:
很难。在函数中不可能执行动态 SQL。我认为只有改变 WHERE 标准才有可能。您将能够更好地评估这对性能的影响。
CREATE FUNCTION [dbo].[f_checker2] (@item varchar(70),
@location varchar(8))
RETURNS @result TABLE (
Qty int
)
AS
BEGIN
INSERT
INTO @result
select TOP(1) qty
from openquery(xxxx, 'SELECT NVL(b.t$st,0) AS qty,
b.t$cloc AS location,
trim(a.t$item) AS item
from server.XXXXXID0001 a
left join server.XXXXXID0002 b
on a.t$item = b.t$item')
where location = @location
and item = @item
if not exists (select * from @result)
INSERT
INTO @result
select TOP(1) qty
from openquery(xxxx, 'SELECT NVL(b.t$st,0) AS qty,
b.t$cloc AS location,
trim(a.t$item) AS item
from server.XXXXXID0001 a
left join server.XXXXXID0002 b
on a.t$item = b.t$item')
where item = @item
RETURN
END
GO
【讨论】:
这是一个多语句表值函数,在这里性能会很差。 它成功了,但需要 10 分 17 秒才能完成。 @fbcomps 是否有进一步优化的机会?我非常感谢您的努力 完整的查询不可能在存储过程中运行,还是将其集成到视图中?以上是关于将使用 exec 填充表的存储过程转换为标量值函数的主要内容,如果未能解决你的问题,请参考以下文章