ГДЕ ... В ... Проблема с хранимой процедурой SQL Server - PullRequest
1 голос
/ 25 октября 2011

Мне нужно реализовать запрос SELECT ... FROM ... WHERE .. IN в моей хранимой процедуре.

Ниже приведен код из моей хранимой процедуры

ALTER PROCEDURE [dbo].[SP_GetQuestionSetMultiCat] 
    -- Add the parameters for the stored procedure here
    @PIN varchar(50),
    @CatIds varchar(50),
    @Range int,
    @Que_Type varchar(50)

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    declare @qtId as int;
    select @qtId = Que_Type_Id from dbo.QuestionType_Tbl where Que_Type=@Que_Type;


    -- Insert statements for procedure here

        Select Top(@Range) 
            QId,
            Que_Type_Id,
            Que_Level_Id,
            Que_Category_Id, 
            Que,
            Opt1,
            Opt2,
            Opt3,
            Opt4,
            Ans 
        From 
            dbo.Que_Tbl 
        Where 
            (Que_Category_Id in (cast(@CatIds as varchar)))
            and (Que_Type_Id=@qtId) 
            and (Qid not in (Select Que_Id From dbo.UserQuestion_Mapping where PIN=@PIN and Que_typeID=@qtId))


END

Посмотрите на условие where.Que_Category_Id имеет тип int.То, что я хочу выполнить, -

Where Que_Category_Id in (1,2,3,4)

Входные значения, которые я передаю, - это строка, преобразованная из моего кода C #.

Когда я выполняю этот запрос, как -

exec SP_GetQuestionSetMultiCat '666777','4,5,6',5,'Practice'

выдает ошибку -

Преобразование не удалось при преобразовании значения varchar '{4,5,6}' в тип данных int.

Кто-нибудь может мне помочь, как решитьЭта проблема.

Спасибо, что поделились своим драгоценным временем.

1 Ответ

4 голосов
/ 25 октября 2011

1) Conversion failed when converting the varchar value '{4,5,6}' to data type int.

Причиной этой ошибки является приоритет типа данных .INT тип данных имеет «более высокий» приоритет, чем VARCHAR тип данных (16-INT против 27-VARCHAR).Итак, SQL Server пытается преобразовать '{4,5,6}' в INT, а не наоборот.

2) Вместо этого я бы преобразовал @CatIds в XML, а затем в табличную переменную (@IDs) использование узла (...) метод :

SET ANSI_WARNINGS ON;

DECLARE @CatIds VARCHAR(50) = '4,5,6';

DECLARE @x XML;
SET     @x = '<node>' + REPLACE(@CatIds, ',', '</node> <node>') + '</node>';
DECLARE @IDs TABLE
(
    ID INT PRIMARY KEY
);
INSERT  @IDs(ID)
SELECT  t.c.value('.', 'INT')
FROM    @x.nodes('/node') t(c);

--Test    
SELECT  *
FROM    @IDs

3) Следующий шаг - переписать запрос, используя IN (SELECT ID FROM @IDs) вместо in (cast(@CatIds as varchar)):

SET ANSI_WARNINGS ON;

ALTER PROCEDURE [dbo].[SP_GetQuestionSetMultiCat] 
    -- Add the parameters for the stored procedure here
    @PIN varchar(50),
    @CatIds varchar(50),
    @Range int,
    @Que_Type varchar(50)

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    declare @qtId as int;
    select @qtId = Que_Type_Id from dbo.QuestionType_Tbl where Que_Type=@Que_Type;

    --Start: New T-SQL code
    DECLARE @x XML;
    SET     @x = '<node>' + REPLACE(@CatIds, ',', '</node> <node>') + '</node>';
    DECLARE @IDs TABLE
    (
        ID INT PRIMARY KEY
    );
    INSERT  @IDs(ID)
    SELECT  t.c.value('.', 'INT')
    FROM    @x.nodes('/node') t(c);
    --End

    -- Insert statements for procedure here

        Select Top(@Range) 
            QId,
            Que_Type_Id,
            Que_Level_Id,
            Que_Category_Id, 
            Que,
            Opt1,
            Opt2,
            Opt3,
            Opt4,
            Ans 
        From 
            dbo.Que_Tbl 
        Where 
            --The search condition is rewritten using IN(subquery)
            Que_Category_Id in (SELECT ID FROM @IDs)
            and (Que_Type_Id=@qtId) 
            and (Qid not in (Select Que_Id From dbo.UserQuestion_Mapping where PIN=@PIN and Que_typeID=@qtId))


END

4) Вызов хранимой процедуры:

exec SP_GetQuestionSetMultiCat '666777','4,5,6',5,'Practice'
...