我有下表值UDF:
CREATE FUNCTION [dbo].[funParseRestParams](
@Params NVARCHAR(MAX),
@Delim VARCHAR(100))
RETURNS TABLE
AS
RETURN (
SELECT
LTRIM(RTRIM(SUBSTRING([Argument], 1, CHARINDEX('=', [Argument], 1) - 1))) Parameter,
LTRIM(RTRIM(SUBSTRING([Argument], CHARINDEX('=', [Argument], 1) + 1, LEN([Argument]) - CHARINDEX('=', [Argument], 1)))) Value
FROM (
SELECT
LTRIM(RTRIM(SUBSTRING(@Params, [Number], CHARINDEX(@Delim, @Params + @Delim, [Number]) - [Number]))) [Argument]
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY name) [Number]
FROM sys.all_objects) AS x
WHERE Number <= LEN(@Params) AND SUBSTRING(@Delim + @Params, [Number], LEN(@Delim)) = @Delim) AS y);
GO
我使用ReportServer.dbo.ExecutionLogStorage
中的参数字符串在游标中运行它。参数看起来像这样:“有些%20Param%20Name = Hello&amp; Some%20Other%20Param = NoLuck”
当我在这样的游标中运行该函数时:
SELECT * FROM Reports.dbo.funParseRestParams(@Param, '&')
一切都很好,但是当我添加where子句时:
SELECT * FROM Reports.dbo.funParseRestParams(@Param, '&') R
WHERE R.[Parameter] = 'AccessType'
我每次都会收到以下错误消息:
Msg 537, Level 16, State 3, Line 13
Invalid length parameter passed to the LEFT or SUBSTRING function.
那么为什么我的where子句会杀死这个函数?
编辑:添加额外的东西。您可以将以下代码粘贴到SQL Server中以复制此错误。仅当使用“first”列(where子句中的Parameter列)时才会出现此错误。使用where子句中的“second”值列不会导致错误。您可以删除下面的评论,以查看此操作:
DECLARE @Params NVARCHAR(MAX)
DECLARE @Delim VARCHAR(1)
SET @Params = 'Greeting=Hello&Name=George&Dessert=Jello'
SET @Delim = '&'
SELECT * FROM (
SELECT
LTRIM(RTRIM(SUBSTRING([Argument], 1, CHARINDEX('=', [Argument], 1) - 1))) Parameter,
LTRIM(RTRIM(SUBSTRING([Argument], CHARINDEX('=', [Argument], 1) + 1, LEN([Argument]) - CHARINDEX('=', [Argument], 1)))) Value
FROM (
SELECT
LTRIM(RTRIM(SUBSTRING(@Params, [Number], CHARINDEX(@Delim, @Params + @Delim, [Number]) - [Number]))) [Argument]
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY name) [Number]
FROM sys.all_objects) AS x
WHERE [Number] <= LEN(@Params) AND SUBSTRING(@Delim + @Params, [Number], LEN(@Delim)) = @Delim) AS y
) R
--WHERE R.Parameter = 'AccessType'
--WHERE R.Parameter = 'Greeting'
--WHERE R.Value = 'Bananas'
--WHERE R.Value = 'Jello'
答案 0 :(得分:0)
您可能希望考虑以下内容:
CREATE FUNCTION dbo.SplitStrings_Moden
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS ( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1),
E2(N) AS (SELECT 1 FROM E1 a, E1 b),
E4(N) AS (SELECT 1 FROM E2 a, E2 b),
E42(N) AS (SELECT 1 FROM E4 a, E2 b),
cteTally(N) AS (SELECT 0 UNION ALL SELECT TOP (DATALENGTH(ISNULL(@List,1)))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E42),
cteStart(N1) AS (SELECT t.N+1 FROM cteTally t
WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0))
SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000))
FROM cteStart s;
此代码归功于Jeff Moden here。该网站还有其他方法。可能值得采用经过严格审查的解决方案(您也必须自己审核),而不是试图重新发明轮子并且不得不花费过多的时间来调试它。
答案 1 :(得分:0)
我放弃了MSDN来搜索答案,我得到了答案。我仍在查看细节,但出于某种原因,以下工作原件没有。第一个子查询的第二行被更改:
DECLARE @Params NVARCHAR(MAX)
DECLARE @Delim VARCHAR(1)
SET @Params = 'Greeting=Hello&Name=George&Dessert=Jello'
SET @Delim = '&'
SELECT * FROM (
SELECT
LTRIM(RTRIM(SUBSTRING([Argument], 0, CHARINDEX('=', [Argument], 1) ))) Parameter,
LTRIM(RTRIM(SUBSTRING([Argument], CHARINDEX('=', [Argument], 1) + 1, LEN([Argument]) - CHARINDEX('=', [Argument], 1)))) Value
FROM (
SELECT
LTRIM(RTRIM(SUBSTRING(@Params, [Number], CHARINDEX(@Delim, @Params + @Delim, [Number]) - [Number]))) [Argument]
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY name) [Number]
FROM sys.all_objects) AS x
WHERE [Number] <= LEN(@Params) AND SUBSTRING(@Delim + @Params, [Number], LEN(@Delim)) = @Delim) AS y
) R
--WHERE R.Parameter = 'AccessType'
WHERE R.Parameter = 'Greeting'
--WHERE R.Value = 'Bananas'
--WHERE R.Value = 'Jello'