在sql查询/存储过程中将字符串列表转换为int列表

时间:2014-09-23 09:59:26

标签: sql sql-server sql-server-2008 stored-procedures sql-server-2008-r2

我有这个存储过程:

exec SearchResume @KeywordSearch=N'', @GreaterThanDate='2013-09-22 00:00:00', 
@CityIDs=N'0,56,31,271,117,327,3,328,228',
@ProvinceIDs=N'0,1,12,13', 
@CountryIDs=N'1', 
@IndustryIDs=N'0,2,3,4,38,113,114,115,116,117'

哪个不返回任何结果,因为id在nvarchar中,但实际值是整数。

现在,当我使用手动的int值列表测试实际的SP时,我能够得到结果,这是一个例子:

    SELECT DISTINCT
        UserID,
        ResumeID,
        CASE  a.Confidential WHEN 1 THEN 'Confidential' ELSE LastName + ',' + FirstName END as 'Name',
        a.Description 'ResumeTitle',
        CurrentTitle,
        ModifiedDate,
        CASE ISNULL(b.SalaryRangeID, '0') WHEN '0' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END 'Salary',
        h.Description 'Relocate',
        i.Description + '-' + j.Description + '-' + k.Description 'Location'
    FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
    LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
    JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
    JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
    JOIN JobType g ON b.JobTypeID = g.JobTypeID
    JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
    JOIN City i ON b.CityID = i.CityID
    JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
    JOIN Country k ON k.CountryID = b.CountryID
    WHERE (b.CityID IN (0,56,31,125,229,5,219,8,228))
    AND (b.StateProvinceID IN (0,1,13))
    AND (b.CountryID IN (1))
    AND (b.IndustryPreferenceID IN (0,2,3,4,5,6,115,116,117))

我想知道如何发送int值列表,而不是nvarchar值列表,因为您可以看到查询无法正常工作。

提前致谢,Laziale

更新:

原始SP:

ALTER PROCEDURE [dbo].[SearchResume]
     @KeywordSearch nvarchar(500),
     @GreaterThanDate datetime,
     @CityIDs nvarchar(500),
     @ProvinceIDs nvarchar(500),
     @CountryIDs nvarchar(500),
     @IndustryIDs nvarchar(500)

AS
BEGIN

DECLARE @sql as nvarchar(4000)

SET @sql = 'SELECT DISTINCT
                UserID,
                ResumeID,
                CASE  a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
                a.Description ''ResumeTitle'',
                CurrentTitle,
                ModifiedDate,
                CurrentEmployerName,
                PersonalDescription,
                CareerObjectives,
                CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
                e.Description ''EducationLevel'',
                f.Description ''CareerLevel'',
                g.Description ''JobType'',
                h.Description ''Relocate'',
                i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
            FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
            LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
            JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
            JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
            JOIN JobType g ON b.JobTypeID = g.JobTypeID
            JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
            JOIN City i ON b.CityID = i.CityID
            JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
            JOIN Country k ON k.CountryID = b.CountryID
            WHERE ( (ModifiedDate > ''' + CAST(@GreaterThanDate as nvarchar(55)) + ''')


                    '
IF (LEN(@CityIDs) >0)
BEGIN
    SET @sql = @sql + 'AND (b.CityID IN (' + @CityIDs + '))'
END
IF (LEN(@ProvinceIDs) >0)
BEGIN
    SET @sql = @sql + 'AND (b.StateProvinceID IN (' + @ProvinceIDs + '))'
END
IF (LEN(@CountryIDs) >0)
BEGIN
    SET @sql = @sql + 'AND (b.CountryID IN (' + @CountryIDs + '))'
END
IF (LEN(@IndustryIDs) >0)
BEGIN
    SET @sql = @sql + 'AND (b.IndustryPreferenceID IN (' + @IndustryIDs + '))'
END

IF (LEN(@KeywordSearch) > 0)
BEGIN
    SET @sql = @sql + ' AND (' + @KeywordSearch + ')'
END

SET @sql = @sql + ') ORDER BY ModifiedDate desc'

--select @sql
exec sp_executesql @sql

END

3 个答案:

答案 0 :(得分:0)

DECLARE @SQL AS NVARCHAR(MAX)

SET @SQL = 'SELECT DISTINCT
        UserID,
        ResumeID,
        CASE  a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' + FirstName END as ''Name'',
        a.Description ''ResumeTitle'',
        CurrentTitle,
        ModifiedDate,
        CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as nvarchar(8)) ELSE c.Description END ''Salary'',
        h.Description ''Relocate'',
        i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
    FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
    LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
    JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
    JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
    JOIN JobType g ON b.JobTypeID = g.JobTypeID
    JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
    JOIN City i ON b.CityID = i.CityID
    JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
    JOIN Country k ON k.CountryID = b.CountryID
    WHERE (b.CityID IN (' + @CityIDs + '))
    AND (b.StateProvinceID IN (' + @ProvinceIDs + '))
    AND (b.CountryID IN (' + @CountryIDs + '))
    AND (b.IndustryPreferenceID IN (' + @IndustryIDs + '))'

EXEC @SQL

答案 1 :(得分:0)

您可以对进入商店程序的ID进行拆分。所以考虑这个分裂函数:

CREATE FUNCTION [dbo].[Split]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE 
AS
RETURN 
(
    WITH Split(stpos,endpos) 
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)

然后你可以写下你的where语句:

WHERE
    EXISTS(SELECT NULL FROM dbo.Split(@CityIDs,',') AS city 
               WHERE city.Data=b.CityID)
    AND EXISTS(SELECT NULL FROM dbo.Split(@ProvinceIDs,',') AS Province 
               WHERE Province.Data=b.StateProvinceID)
    AND EXISTS(SELECT NULL FROM dbo.Split(@CountryIDs,',') AS Country 
               WHERE Country.Data=b.CountryID)
    AND EXISTS(SELECT NULL FROM dbo.Split(@IndustryIDs,',') AS Industry 
               WHERE Industry.Data=b.IndustryPreferenceID)

答案 2 :(得分:0)

您可以创建一个表值函数,它接受nVarChar并为每个值创建一个新记录,您可以在其中告诉它分隔符。我的示例返回一个包含单个Value列的表,然后您可以将其用作IN Selection的子查询:

Create  FUNCTION [dbo].[fnSplitVariable]
(
    @List nvarchar(2000),
    @delimiter nvarchar(5)
)  
RETURNS @RtnValue table 
(

    Id int identity(1,1),
    Variable varchar(15),
    Value nvarchar(100)
) 
AS  
BEGIN
Declare @Count int
set @Count = 1
    While (Charindex(@delimiter,@List)>0)
    Begin 
        Insert Into @RtnValue (Value, Variable)
        Select 
            Value = ltrim(rtrim(Substring(@List,1,Charindex(@delimiter,@List)-1))),
        Variable = 'V' + convert(varchar,@Count)
            Set @List = Substring(@List,Charindex(@delimiter,@List)+len(@delimiter),len(@List))
        Set @Count = @Count + 1
    End  

    Insert Into @RtnValue (Value, Variable)
        Select Value = ltrim(rtrim(@List)), Variable = 'V' + convert(varchar,@Count)

        Return
END

然后在您的where语句中,您可以执行以下操作:

WHERE (b.CityID IN (Select Value from fnSplitVariable(@CityIDs, ','))

我已经包含了原始程序,并对其进行了更新以使用上述功能:

ALTER PROCEDURE [dbo].[SearchResume]
     @KeywordSearch nvarchar(500),
     @GreaterThanDate datetime,
     @CityIDs nvarchar(500),
     @ProvinceIDs nvarchar(500),
     @CountryIDs nvarchar(500),
     @IndustryIDs nvarchar(500)

AS
BEGIN

DECLARE @sql as nvarchar(4000)

SET @sql = N'
       DECLARE      @KeywordSearch nvarchar(500),
                    @CityIDs nvarchar(500),
                    @ProvinceIDs nvarchar(500),
                    @CountryIDs nvarchar(500),
                    @IndustryIDs nvarchar(500) 

       SET @KeywordSearch = '''+@KeywordSearch+'''
       SET @CityIDs = '''+@CityIDs+'''
       SET @ProvinceIDs = '''+@ProvinceIDs+'''
       SET @CountryIDs = '''+@CountryIDs+'''
       SET @IndustryIDs = '''+@IndustryIDs+'''
SELECT DISTINCT
                UserID,
                ResumeID,
                CASE  a.Confidential WHEN 1 THEN ''Confidential'' ELSE LastName + '','' +      FirstName END as ''Name'',
                a.Description ''ResumeTitle'',
                CurrentTitle,
                ModifiedDate,
                CurrentEmployerName,
                PersonalDescription,
                CareerObjectives,
                CASE ISNULL(b.SalaryRangeID, ''0'') WHEN ''0'' THEN CAST(SalarySpecific as   nvarchar(8)) ELSE c.Description END ''Salary'',
                e.Description ''EducationLevel'',
                f.Description ''CareerLevel'',
                g.Description ''JobType'',
                h.Description ''Relocate'',
                i.Description + ''-'' + j.Description + ''-'' + k.Description ''Location''
            FROM dbo.Resume a JOIN dbo.Candidate b ON a.CandidateID = b.CandidateID
            LEFT OUTER JOIN SalaryRange c ON b.SalaryRangeID = c.SalaryRangeID
            JOIN EducationLevel e ON b.EducationLevelID = e.EducationLevelID
            JOIN CareerLevel f ON b.CareerLevelID = f.CareerLevelID
            JOIN JobType g ON b.JobTypeID = g.JobTypeID
            JOIN WillingToRelocate h ON b.WillingToRelocateID = h.WillingToRelocateID
            JOIN City i ON b.CityID = i.CityID
            JOIN StateProvince j ON j.StateProvinceID = b.StateProvinceID
            JOIN Country k ON k.CountryID = b.CountryID
            WHERE ( (ModifiedDate > ''' + CAST(@GreaterThanDate as nvarchar(55)) + ''')


                    '
IF (LEN(@CityIDs) >0)
BEGIN
    SET @sql = @sql + N'AND (b.CityID IN (Select Value from fnSplitVariable(@CityIDs,'','')  ))'
END
IF (LEN(@ProvinceIDs) >0)
BEGIN
    SET @sql = @sql + N'AND (b.StateProvinceID IN (Select Value from    fnSplitVariable(@ProvinceIDs,'','') ))'
END
IF (LEN(@CountryIDs) >0)
BEGIN
    SET @sql = @sql + N'AND (b.CountryID IN (Select Value from fnSplitVariable(@CountryIDs,'','')    ))'
END
IF (LEN(@IndustryIDs) >0)
BEGIN
    SET @sql = @sql + N'AND (b.IndustryPreferenceID IN (Select Value from fnSplitVariable(@IndustryIDs,'','') ))'
END

IF (LEN(@KeywordSearch) > 0)
BEGIN
    SET @sql = @sql + N' AND (' + @KeywordSearch + ')'
END

SET @sql = @sql + N') ORDER BY ModifiedDate desc'

--select @sql
exec sp_executesql @sql

END