2009-05-17 3 views
1

У меня есть строка, которая является результатом функции, например: «1,3,16, .., ..».Charindex в SQL не дает желаемого результата

Я использовал следующий 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.

Почему SQL-запрос с charindex не дает мне никакого результата?

Возможно, я не могу понять проблему здесь, пожалуйста, помогите.

ответ

1

CHARINDEX просто возвращает сообщение, в котором символ находится внутри строки.

Так что, когда @ItemIDs установлен в '3,16', то ваш п WHERE ...

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

... эквивалентно ...

WHERE ItemID = 2 

... потому что CHARINDEX возвращает 2 после символ запятой находится в позиции 2 строки '3,16'.

Я предполагаю, что (а) у вас нет строки в таблице, где ItemID является 2 и (б) вы действительно не хотите, положение запятой, чтобы диктовать, какие строки возвращаются.

+0

(а) я не имею запись, где ItemID равен 2. (б) я хочу, чтобы запрос, чтобы получить мне запись. ПРИМЕЧАНИЕ. @ItemID могут содержать разные значения не «3,16» каждый раз. Как я могу это достичь? спасибо – pier

0

Попробуйте ВЫБРАТЬ ItemID, имя, RelDate, Цена, Статус FROM item_k WHERE ItemID в (@itemIDs)

+0

Хмм. это будет работать, если я дам 1 значение в качестве параметра. Несоответствие типа задается при вводе «3,12» в качестве параметра. – pier

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-инъекции.

Edit:
Это то, что происходит в запросе:

Сначала мы объявляем переменную для динамического запроса. Это просто переменная varchar, достаточно большая.

В переменной мы помещаем переменную @itemIDs между двумя строками для формирования запроса., Разделенные запятой значения помещается между скобками оператора in, чтобы сформировать выражение, аналогичное: where ItemID in (1,3,16)

Наконец команда exec выполняет запрос в переменной.

+0

Coudl вы pls. объясните, что именно происходит в этом запросе? – pier

+0

Я добавил объяснение выше. – Guffa

3

Вот еще одно решение. По моему опыту, когда у вас есть список ItemIds как строка значений, разделенных запятыми, вам нужна функция split. Это очень полезно.

С функцией сплита, вы можете просто сделать внутреннее соединение с результатами вызова функции разделения и передавая список 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