SQL中的Charindex没有给出所需的结果

时间:2009-05-17 23:38:12

标签: sql sql-server tsql

我有一个字符串,它是函数的输出,例如:“1,3,16,..,..”。

我使用了以下SQL查询并在Visual Studio的查询构建器中运行它,它没有给我任何语法错误。

SELECT ItemID, Name, RelDate, Price, Status FROM item_k WHERE (ItemID = cast(charindex(',', @itemIDs) as int))

我给了3,16作为@itemID参数值,但它没有给出所需的结果。

然后我使用了以下SQL查询(没有charindex):

SELECT ItemID, Name, RelDate, Price, Status FROM item_k WHERE (ItemID = @itemIDs)

我给了3作为@itemID参数值,我得到了一个结果。 我还给了16个(在另一个场合)作为@itemID参数值,我得到了一个结果。我得出结论,ItemID 3和& 16。

为什么带有charindex的SQL查询不能给我任何结果?

我似乎无法在这里找出问题,请帮忙。

4 个答案:

答案 0 :(得分:3)

这是另一种解决方案。根据我的经验,当您将ItemId列表作为逗号分隔值的字符串时,您需要一个split函数。这非常有用。

使用split函数,您可以简单地使用调用split函数的结果进行INNER JOIN,并传递ItemIds和相关分隔符的列表,如下所示:

DECLARE @ItemIDs varchar(100)
SET @ItemIDs = '1,3,16,22,34,35'

SELECT 
     ItemID, Name, RelDate, Price, Status 
FROM item_k
     INNER JOIN dbo.UTILfn_Split(@ItemIDs,',') itemIds 
       ON itemIds.Value = item_k.ItemID

虽然这可能看起来很复杂,但它是更优雅和可维护的解决方案。以下是用于创建 dbo.UTILfn_Split 功能的代码。你需要先运行它:

IF EXISTS (SELECT * FROM sysobjects WHERE id = 
object_id(N'[dbo].[UTILfn_Split]') AND xtype IN (N'FN', N'IF', N'TF'))
DROP FUNCTION [dbo].[UTILfn_Split]
GO

CREATE FUNCTION dbo.UTILfn_Split
(
    @String nvarchar (4000),
    @Delimiter nvarchar (10)
)
RETURNS @ValueTable TABLE ([Value] nvarchar(4000))
BEGIN
 DECLARE @NextString nvarchar(4000)
 DECLARE @Pos int
 DECLARE @NextPos int
 DECLARE @CommaCheck nvarchar(1)

 --Initialize
 SET @NextString = ''
 SET @CommaCheck = RIGHT(@String,1)  
 --Check for trailing Comma, if not exists, INSERT
 --if (@CommaCheck <> @Delimiter )
 SET @String = @String + @Delimiter

 --Get position of first Comma
 SET @Pos = CHARINDEX(@Delimiter,@String)
 SET @NextPos = 1

 --Loop while there is still a comma in the String of levels
 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

答案 1 :(得分:1)

CHARINDEX只返回在字符串中找到字符的帖子。

因此,当@ItemIDs设置为'3,16'时,您的WHERE条款......

WHERE (ItemID = CAST(CHARINDEX(',', @ItemIDs) AS INT))

......等同于......

WHERE ItemID = 2

...因为CHARINDEX返回2,因为逗号字符位于字符串'3,16'的第2位。

我猜是(a)您的表格中没有ItemID2的行,而(b)

答案 2 :(得分:1)

您可以使用in运算符动态创建查询:

declare @Sql varchar(1000)
set @Sql = 'select ItemID, Name, RelDate, Price, Status from item_k where ItemID in (' + @itemIDs + ')'
exec(@Sql)

但要小心你发送到程序中的内容。与任何动态SQL一样,如果数据来自用户输入而未经验证,则该过程对SQL注入是开放的。

编辑:
这就是查询中发生的情况:

首先,我们声明一个变量来保存动态查询。这只是一个足够大的varchar变量。

在变量中,我们将@itemIDs变量放在两个字符串之间以形成查询。逗号分隔值放在in运算符的括号之间,以形成类似于:where ItemID in (1,3,16)的表达式

最后,exec命令在变量中执行查询。

答案 3 :(得分:0)

尝试 SELECT ItemID,Name,RelDate,Price,Status FROM item_k WHERE ItemID in(@itemIDs)