我正在尝试使用split函数为查询添加一系列值。我也想把这些价值“或”在一起,但首先要做的事情。我正在按照我在一个使用split函数的更大查询中找到的一个例子,所以我做了一个小查询来试图弄清楚它是如何工作的。到目前为止,我得到的只是错误*“名称'选择*来自Country As sp WHERE(sp.CountryID in(SELECT [Value] FROM dbo.Split('2,22,',','))) '不是一个有效的标识符。“*我知道DynamicSQL,我不太确定这个分割函数应该如何工作。
DECLARE @Countries varchar(MAX);
DECLARE @FiltersOn bit;
DECLARE @Country int;
DECLARE @Query varchar(MAX);
Set @FiltersOn = 0;
Set @Query = 'Select * from Country As sp ';
Set @Countries ='2,22,'
IF ( @Countries IS NOT NULL )
BEGIN
IF ( @FiltersOn = 1 )
BEGIN
SET @Query = @Query + ' AND '
END
ELSE
BEGIN
SET @Query = @Query + ' WHERE '
SET @FiltersOn = 1
END
SET @Query = @Query
+ '(sp.CountryID in (SELECT [Value] FROM dbo.Split('''
+ @Countries + ''', '','')))'
END
EXEC @Query
这是国家/地区表的定义:
CREATE TABLE [dbo].[Country](
[CountryID] [int] IDENTITY(1,1) NOT NULL,
[AgentID] [int] NULL,
[Name] [varchar](50) NULL,
[CountryLookupID] [int] NOT NULL
这是拆分功能代码:
CREATE FUNCTION [dbo].[Split]
(
@String varchar(8000),
@Delimiter varchar(10)
)
RETURNS @ValueTable table ([Value] varchar(255))
BEGIN
DECLARE @NextString varchar(4000)
DECLARE @Pos int
DECLARE @NextPos int
DECLARE @DelimiterCheck varchar(1)
-- initialise
SET @NextString = ''
SET @DelimiterCheck = RIGHT(@String, 1)
-- add trailing delimiter
IF (@DelimiterCheck <> @Delimiter)
SET @String = @String + @Delimiter
-- find position of first delimiter
SET @Pos = CHARINDEX(@Delimiter, @String)
SET @NextPos = 1
-- loop while there is a delimiter in the string
WHILE (@Pos <> 0)
BEGIN
SET @NextString = SUBSTRING(@String, 1, @Pos - 1)
INSERT INTO @ValueTable ([Value]) VALUES (@NextString)
SET @String = SUBSTRING(@String, @Pos + 1, LEN(@String))
SET @NextPos = @Pos
SET @Pos = CHARINDEX(@Delimiter, @String)
END
RETURN
END
答案 0 :(得分:0)
您没有正确撰写EXEC
声明。
使用EXEC (@Query)
代替EXEC @Query
答案 1 :(得分:0)
这不是你问题的直接答案,但我可以推荐阅读这些内容,因为我发现这些解决方案在系统之前会产生问题。
我建议不要使用WHILE循环的解决方案。虽然循环不断产生性能问题,因为SQL Server没有像C#引擎那样优化循环的能力。
不确定为什么要使用动态SQL。如果你想确保没有SQL注入,请使用sp_executesql,因为它检查有害代码,但我会避免使用动态sql,除非我们不知道我们的底层数据的结构(因此需要动态sql )。
刚刚编写了一个函数,用于使用cte进行字符串拆分以保持性能。
CREATE SCHEMA Util;
GO
CREATE FUNCTION Util.String_Split (
@Text varchar(MAX),
@SplitChar char
)
RETURNS TABLE
AS
RETURN(
WITH cte AS
(
SELECT
1 AS [RowNumber],
X.Text,
X.RemainingText
FROM
(
SELECT
SUBSTRING(@Text, 1, CHARINDEX(';', @Text) - 1) AS [Text],
SUBSTRING(@Text, CHARINDEX(';', @Text) + 1, LEN(@Text) - CHARINDEX(';', @Text)) AS [RemainingText]
) X
UNION ALL
SELECT
cte.RowNumber + 1,
X.Text,
X.RemainingText
FROM
cte
CROSS APPLY (
SELECT
SUBSTRING(cte.RemainingText, 1, ISNULL(NULLIF(CHARINDEX(';', cte.RemainingText) - 1, -1), LEN(cte.RemainingText))) AS [Text],
CASE
WHEN CHARINDEX(';', cte.RemainingText) = 0 THEN
''
ELSE
SUBSTRING(cte.RemainingText, CHARINDEX(';', cte.RemainingText) + 1, LEN(cte.RemainingText))
END AS [RemainingText]
) X
WHERE
X.Text ''
)
SELECT
cte.Text
FROM
cte
WHERE
cte.Text IS NOT NULL
);
然后,您可以使用此调用调用不使用动态部分进行查询:
SELECT
*
FROM
Country sp
WHERE
@Countries IS NULL
OR
sp.CountryId IN (
SELECT * FROM Util.String_Split(@Countries, ',')
)