0

我在描述列中有记录,其中包含以下内容:

“发现服务器aaa-aaa-aaa坏了,晚上8点换成服务器bbb-bbb-bbb”

我想做一些看起来像这样的事情:

SET @serverArray = empty    
SELECT Description into @serverArray  
WHERE Description like '%-%-%'
FROM Operations

ForEach ROW in @serverArray
{
    sp_HardwareScan (ROW)
}

因此,我的示例将执行:

EXEC sp_HardwareScan (aaa-aaa-aaa)

EXEC sp_HardwareScan (bbb-bbb-bbb)
4

1 回答 1

2

SQL Server 中没有数组这样的东西,通常在考虑循环处理事物时,您应该停下来考虑一下。也就是说,这并不总是可能的,这取决于您在循环的每次迭代中需要做什么。这是每行调用一个存储过程的简单方法,而不会创建混乱的 while 循环或游标结构。然而,这并没有解析出描述中只是aaa-aaa-aaabbb-bbb-bbb......最初并不清楚的部分。为什么这些不作为单独的列存储,而不是在一个大字符串中聚集在一起?为什么要从 SQL Server 内部进行这种“硬件扫描”?听起来更像是 PowerShell、C# 等的工作。

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'EXEC sp_HardwareScan ''' + REPLACE(Description,'''','''''') + ''';
'
  FROM dbo.Operations
  WHERE Description LIKE '%-%-%';

PRINT @sql;

-- EXEC sp_executesql @sql;

既然我现在明白每行需要多个过程调用,那么首先创建一个拆分函数怎么样:

CREATE FUNCTION [dbo].[SplitString]
    (
        @List NVARCHAR(MAX),
        @Delim VARCHAR(255)
    )
    RETURNS TABLE
    AS
        RETURN ( SELECT [Value] FROM 
          ( 
            SELECT 
              [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
              CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
            FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
              FROM sys.all_objects) AS x
              WHERE Number <= LEN(@List)
              AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
          ) AS y
        );

现在您可以使用外部应用中的函数来获取每个字符串中需要传递给存储过程的部分。

SET NOCOUNT ON;
        
DECLARE @x TABLE(Description VARCHAR(MAX));

INSERT @x VALUES('Server c-4-5h was offline & replaced with R2-D2-C3P0 at 5AM'),
('Server aaa-aaa-aaa was broken & replaced with server bbb-bbb-bbb at 8pm');

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'EXEC sp_HardwareScan ''' + REPLACE(Value, '''', '''''') + ''';
'
FROM @x AS x OUTER APPLY dbo.SplitString(REPLACE(x.Description,' ',';'), ';') AS y
WHERE y.Value LIKE '%-%-%';

PRINT @sql;

-- EXEC sp_executesql @sql;

结果:

EXEC sp_HardwareScan 'c-4-5h';
EXEC sp_HardwareScan 'R2-D2-C3P0';
EXEC sp_HardwareScan 'aaa-aaa-aaa';
EXEC sp_HardwareScan 'bbb-bbb-bbb';

只需替换@xdbo.Operations对您的真实表进行测试(始终指定模式)。

有关拆分函数的更多信息,为什么(并证明)while 循环和递归 CTE 不能扩展,以及更好的替代方案,如果拆分来自应用程序层的字符串:

但是,在 SQL Server 2016 或更高版本上,您应该查看STRING_SPLIT()and STRING_AGG()

此外,停止使用sp_存储过程的前缀

于 2013-11-13T18:39:08.507 回答