DECLARE @temp AS TABLE (id INT, NAME VARCHAR(20) )
DECLARE @str VARCHAR(20) = '1,2'
INSERT INTO @temp (id, NAME)
VALUES (1, ''), (2, ''), (2, '')
SELECT *
FROM @temp a
WHERE id IN ((SELECT String FROM dbo.FN_SplitStrings(@str,',')))
运行此
时出现以下错误将varchar值“1,2”转换为数据类型时转换失败 中间体
代码:
CREATE function [dbo].[FN_SplitStrings]
(
@StringToSplit varchar(8000),
@Separator varchar(128)
)
RETURN TABLE
AS
RETURN
with indices as
(
select
0 S, 1 E
union all
select
E, charindex(@Separator, @StringToSplit, E) + len(@Separator)
from
indices
where E > S
)
select
substring(@StringToSplit,S, case when E > len(@Separator)
then e-s-len(@Separator) else len(@StringToSplit) - s + 1 end) String ,
S StartIndex
from
indices
where
S > 0
答案 0 :(得分:0)
试试这个。这种拆分可以在没有功能的情况下使用
DECLARE @temp AS TABLE
(
id INT,
NAME VARCHAR(20)
)
DECLARE @str VARCHAR(20)='1,2'
INSERT INTO @temp
( id, NAME )
VALUES ( 1, '' ),
( 2, ''),
( 2, '')
SELECT * FROM @temp a
WHERE id IN
(
SELECT LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'KeyWords'
FROM
(
-- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
SELECT CAST ('<M>' + REPLACE(@str, ',', '</M><M>') + '</M>' AS XML) AS Data
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
编辑:
你在拆分功能方面遇到了一些问题。
<强>功能强>
ALTER FUNCTION dbo.FN_SplitStrings(@StringToSplit varchar(8000),@Separator char(1))
RETURNS table
AS
RETURN (
WITH splitter_cte AS (
SELECT CHARINDEX(@Separator, @StringToSplit) as pos, 0 as lastPos
UNION ALL
SELECT CHARINDEX(@Separator, @StringToSplit, pos + 1), pos
FROM splitter_cte
WHERE pos > 0
)
SELECT SUBSTRING(@StringToSplit, lastPos + 1,
case when pos = 0 then 80000
else pos - lastPos -1 end) as String
FROM splitter_cte
)
<强>查询强>
DECLARE @temp AS TABLE (id INT, NAME VARCHAR(20) )
DECLARE @str VARCHAR(20) = '1,2'
INSERT INTO @temp (id, NAME)
VALUES (1, ''), (2, ''), (2, '')
SELECT *
FROM @temp a
WHERE id IN ((SELECT String FROM dbo.FN_SplitStrings(@str,',')))
答案 1 :(得分:0)
原因是数据类型的混合以及您的函数是内联表值函数的事实,这意味着它在查询优化发生之前嵌入到查询中。
如果您从函数中删除where S > 0
并使用1,2
执行该函数,则该函数的结果为:
String
------
1,2
1
2
注意值为1,2
的第一行。
当优化器使用您的查询完成其工作时,在评估函数的where子句之前完成与列id
的比较。在该比较中,您对int
进行了隐式转换,1,2
无法转换为int
。
要解决此问题,您可以确保split函数的String列始终为int
(并且可能更改过程中列的名称)。
select
cast(substring(@StringToSplit,S, case when E > len(@Separator)
then e-s-len(@Separator)
else len(@StringToSplit) - s + 1
end) as int) String ,