即使我使用的是 SQL Server 2000,我也一直在处理一个非常相似的问题,并且能够实现我想要的。我知道这是一个老问题,但认为在此处发布它是有效的解决方案,因为应该有像我这样使用旧版本但仍需要帮助的其他人。
诀窍在于:SQL Server 不接受将表传递给 UDF,您也不能传递 T-SQL 查询,因此该函数会创建临时表,甚至调用存储过程来执行此操作。所以,相反,我创建了一个保留表,我称之为 xtList。这将保存要使用的值列表(1 列,根据需要)。
CREATE TABLE [dbo].[xtList](
[List] [varchar](1000) NULL
) ON [PRIMARY]
然后,一个存储过程来填充列表。这不是绝对必要的,但我认为这是非常有用的最佳实践。
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpCreateList]
@ListQuery varchar(2000)
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM xtList
INSERT INTO xtList
EXEC(@ListQuery)
END
现在,只需使用 xtList 以您想要的任何方式处理列表。您可以在过程中使用(用于执行多个 T-SQL 命令)、标量函数(用于检索多个字符串)或多语句表值函数(检索字符串,但就像在表中一样,每行 1 个字符串)。对于其中任何一个,您都需要游标:
DECLARE @Item varchar(100)
DECLARE cList CURSOR DYNAMIC
FOR (SELECT * FROM xtList WHERE List is not NULL)
OPEN cList
FETCH FIRST FROM cList INTO @Item
WHILE @@FETCH_STATUS = 0 BEGIN
<< desired action with values >>
FETCH NEXT FROM cList INTO @Item
END
CLOSE cList
DEALLOCATE cList
所需的操作如下所示,具体取决于创建的对象类型:
存储过程
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpProcreateExec]
(
@Cmd varchar(8000),
@ReplaceWith varchar(1000)
)
AS
BEGIN
DECLARE @Query varchar(8000)
<< cursor start >>
SET @Query = REPLACE(@Cmd,@ReplaceWith,@Item)
EXEC(@Query)
<< cursor end >>
END
/* EXAMPLES
(List A,B,C)
Query = 'SELECT x FROM table'
with EXEC xpProcreateExec(Query,'x') turns into
SELECT A FROM table
SELECT B FROM table
SELECT C FROM table
Cmd = 'EXEC procedure ''arg''' --whatchout for wrong quotes, since it executes as dynamic SQL
with EXEC xpProcreateExec(Cmd,'arg') turns into
EXEC procedure 'A'
EXEC procedure 'B'
EXEC procedure 'C'
*/
标量函数
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateStr]
(
@OriginalText varchar(8000),
@ReplaceWith varchar(1000)
)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @Result varchar(8000)
SET @Result = ''
<< cursor start >>
SET @Result = @Result + REPLACE(@OriginalText,@ReplaceWith,@Item) + char(13) + char(10)
<< cursor end >>
RETURN @Result
END
/* EXAMPLE
(List A,B,C)
Text = 'Access provided for user x'
with "SELECT dbo.xfProcreateStr(Text,'x')" turns into
'Access provided for user A
Access provided for user B
Access provided for user C'
*/
多语句表值函数
-- =============================================
-- Author: Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateInRows]
(
@OriginalText varchar(8000),
@ReplaceWith varchar(1000)
)
RETURNS
@Texts TABLE
(
Text varchar(2000)
)
AS
BEGIN
<< cursor start >>
INSERT INTO @Texts VALUES(REPLACE(@OriginalText,@ReplaceWith,@Item))
<< cursor end >>
END
/* EXAMPLE
(List A,B,C)
Text = 'Access provided for user x'
with "SELECT * FROM dbo.xfProcreateInRow(Text,'x')" returns rows
'Access provided for user A'
'Access provided for user B'
'Access provided for user C'
*/