我有以下按预期运行的存储过程:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[view_proc]
(@startdatetime DATETIME,
@enddatetime DATETIME,
@ids VARCHAR(MAX)
)
AS
BEGIN
SELECT *
FROM
(SELECT
[sr_datetime], [sr_id], [sr_value], [sr_dst], [sr_source]
FROM
[Powerlink].[dbo].[scada_data]
WHERE
sr_id IN ('M001007', 'M001008', 'M001020', 'M001021')
AND sr_datetime >= @startdatetime
AND sr_datetime <= @enddatetime) AS SourceTable
PIVOT
(MAX(sr_value)
FOR [sr_id] IN (M001007, M001008, M001020, M001021)
) AS PVT
ORDER BY
sr_datetime
END
我使用以下行运行此过程:
EXEC [dbo].[view_proc]
@startdatetime = '2018-01-01 01:00:00',
@enddatetime = '2018-01-01 02:00:00',
@ids = 'M001007,M001008,M001020,M001021'
但是,当前该过程不使用@ids
和@startdatetime
参数更改查询的方式来使用@enddatetime
参数更改查询。
我的问题是,修改存储过程以使其接受标记列表作为参数的最简单方法是什么,它将用于修改现有查询的结果。
我已经研究过定义一个自定义类型以用作参数,但是我无法弄清楚在调用过程时必须使用哪种语法来表示数据。
任何帮助将不胜感激。
欢呼
答案 0 :(得分:0)
最好的方法是使用Table-Valued Parameters
您的情况应该是
CREATE TYPE list_of_ids AS TABLE -- probably should choose a better name
( id VARCHAR(50) );
GO
ALTER PROCEDURE [dbo].[view_proc]
(
@startdatetime datetime,
@enddatetime datetime,
@ids list_of_ids READONLY
)
请记住,@ ids是只读的,但是您可以像常规表一样使用它。
如果您有很多ids(10000+),建议您先尝试将其插入到临时表中,可能将其插入索引中,然后在联接或WHERE中使用它。
答案 1 :(得分:0)
一个正在工作的家伙给了我以下函数,该函数采用一串用逗号分隔的值并返回一个表:
USE [Powerlink]
GO
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 30/08/2018 1:49:26 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split] (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
这使我可以使用以下代码调用存储过程:
EXEC [dbo].[view_proc]
@startdatetime = '2018-01-02 00:00:00',
@enddatetime = '2018-01-31 23:59:59',
@ids = 'M001007,M001008,M001020,M001021'
这是存储过程中的用法:
USE [Powerlink]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[view_proc]
(
@startdatetime varchar(32)= '2018-01-01 01:00:00',
@enddatetime varchar(32)= '2018-01-01 02:00:00',
@ids varchar (max) = 'M001007,M001008,M001020,M001021'
)
AS
BEGIN
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
SELECT s AS ID INTO #IDS FROM dbo.Split(',',@ids)
select @cols = STUFF((SELECT ',' + QUOTENAME(ID)
FROM #IDS
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query =
'SELECT *
FROM
(
SELECT [sr_datetime]
,[sr_id]
,[sr_value]
,[sr_dst]
,[sr_source]
FROM [Powerlink].[dbo].[scada_data]
WHERE sr_id IN (SELECT * FROM #IDS)
AND sr_datetime >= '''+ @startdatetime +'''
AND sr_datetime <= '''+ @enddatetime +'''
) AS SourceTable
PIVOT(
max(sr_value)
for [sr_id] in (' + @cols + N')
) as PVT ORDER BY sr_datetime'
exec sp_executesql @query;
DROP TABLE #IDS
END