2016-08-17 2 views
2

다음과 같은 상황이 있습니다. 효율적으로 코드를 작성하는 방법입니다. 더 PARAM이 ')'IN 절 내의 여러 IF 문으로 동적 쿼리를 피하는 방법

근처의 구문이 잘못 추가되지 않은 경우 위의 문에서 오류가 발생하는 경우

DECLARE @sql VARCHAR(MAX) = '' 
DECLARE @where VARCHAR(MAX) = '' 

IF @is_clean_label = 1 
    SET @where = @where+ N'Clean Label,' 

IF @Is_KeyInterview = 1 
    SET @where = @where+N'Key Interview,' 

IF @Is_SpecialReport = 1 
    SET @where = @where+N'Special Report,' 

SET @sql = N' SELECT * FROM TABLE WHERE Name in ('[email protected]+')' 

EXEC (@sql) 

.

조건이 적용되지 않으면 모든 값을 반환해야합니다.

동적 SQL을 피할 수 있습니까?

+0

귀하의 @where는 앞에 ','; SQL에 추가하기 전에 초기 쉼표를 제거하는 논리를 작성하십시오. – techspider

+0

문자열 다음에 이동해야하며 값의 일부가 아니어야합니다. 문자열에 값을 넣으려면 '세 번 사용하십시오. 예를 들어, + N ', Clean Label'이 아니어야합니다. + '' 'Clean Label' '+', ''여야합니다. 또한 다른 사람이 말한대로 문자열을 어디에서나 끝내거나 끝내십시오. 찾으려면 CHARINDEX를 사용하고 줄을 자르기 위해서는 SUBSTRING을 사용하십시오. –

답변

1

당신은 거의 당신이 경우 문으로 원하는을 할 수있는 위치를 본질적으로 직접 where 절에 다음 논리를 당신의 IF를 이동할 수 있습니다 절.

SELECT * 
FROM 
    TableName 
WHERE 
    (CASE 
     WHEN @is_clean_label = 1 AND Name = 'Clean Label' THEN 1 
     ELSE 0 
    END) = 1 
    OR 
    (CASE 
     WHEN @Is_KeyInterview = 1 AND Name = 'Key Interview' THEN 1 
     ELSE 0 
    END) = 1 
    OR 
    (CASE 
     WHEN @Is_SpecialReport = 1 AND Name = 'Special Report' THEN 1 
     ELSE 0 
    END) = 1 
    OR 
    (CASE 
     WHEN (COALESCE(@Is_SpecialReport,0) + COALESCE(@Is_KeyInterview,0) + COALESCE(@Is_SpecialReport,0)) = 0 THEN 1 
     ELSE 0 
    END) = 1 

나는 또한 종종 John이 쓴 테이블 경로를 사용 하겠지만 여러모로 유용하기 때문에이 기술을 보여주는 것이 중요하다고 생각합니다. 나는 또한 다른 의견들 중 일부가 진정으로 필요하지 않을 때 동적 SQL로부터 멀리 떨어져 있음에 동의한다.

0

귀하의 @where 변수에는 연결 논리로 인해 앞에 comma이 포함됩니다.

첫 번째 comma을 제거하면 도움이됩니다.

SET @where = STUFF(@where, 1, 1, '') 
SET @sql = N' SELECT * FROM TABLE WHERE Name in ('[email protected]+')' 
0

아마도 필요가 동적 이 스크립트 몇 가지 문제가 있습니다

Declare @InList Table (KeyVal varchar(50),Include int) 

Insert Into @InList 
values ('Clean Label', @is_clean_label), 
     ('Key Interview', @Is_KeyInterview), 
     ('Special Report', @Is_SpecialReport) 

SELECT * 
FROM TABLE 
WHERE Name IN (SELECT KeyVal 
       FROM @InList 
       WHERE Include = (SELECT MAX(sign(Include)) FROM @InList)) 
+0

조건을 적용하지 않으면 모든 값을 반환해야합니다! – Ragul

+0

@Ragul 원래 질문에 추가 요구 사항을 추가 할 수 있습니다. – iamdave

+0

@Ragul 충분히 그렇지만 요구 사항에 명시되지 않았습니다. "!"의 가치가 있는지 확신하지 못했습니다. –

0

없는 선택을 모두 포함하도록 업데이트 갈 수 있습니다.

먼저, in 목록의 쉼표 앞.

DECLARE @sql NVARCHAR(MAX) = '' 
DECLARE @where NVARCHAR(MAX) 

IF @is_clean_label = 1 
SET @where = isnull(@where + ',','')+ N'''Clean Label''' 

IF @Is_KeyInterview = 1 
SET @where = isnull(@where + ',','')+ N'''Key Interview''' 

IF @Is_SpecialReport = 1 
SET @where = isnull(@where + ',','')+ N'''Special Report''' 

SET @sql = N' SELECT * FROM TABLE' 
      + case when @where <> '' 
        then ' WHERE Name in ('[email protected]+')' 
        else '' 
        end 
EXEC (@sql) 
1

첫째, 좋은 일을하려고 밖으로 도달 : 플래그가

그리고 셋째

, 당신도 당신의 in 목록에 작은 따옴표를 추가하지 않는 설정되지 않은 경우

둘째, 당신은 취급하지 않습니다 비 동적 SQL 방식을 찾으십시오.

아래의 "속임수"는 룩업 테이블의 수를 고려한 것입니다.

IMHO, 동적 SQL 응답을 모두 포함하는 "try this"를 무시하십시오. 문제가 동적 SQL없이 해결 될 수 있다면 IMHO 여야합니다. 여기에서 몇 가지 문제점에 관해 읽을 수 있습니다 : http://sqlmag.com/database-performance-tuning/don-t-fear-dynamic-sql 사용하는 경우에도 사용하기에 알맞은 방법과 바보 같은 방법이 있습니다.

IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL 
    begin 
      drop table #TableOne 
    end 


    CREATE TABLE #TableOne 
    ( 
    SurrogateKeyIDENTITY int not null IDENTITY (1,1) , 
    MyLabel varchar(16) 
    ) 

    Insert into #TableOne (MyLabel) select 'Clean Label' UNION ALL select 'Clean Label' UNION ALL select 'Key Interview' UNION ALL select 'Key Interview' UNION ALL select 'Special Report' UNION ALL select 'Special Report' UNION ALL select 'NotAMatch' UNION ALL select 'NotAMatch' 


Declare @LookupMatchTable Table (KeyVal varchar(50)) 
if(1=1) /* use your bool flags here */ 
begin 
    Insert Into @LookupMatchTable (KeyVal) Select 'Clean Label' 
end 
if(1=1) /* use your bool flags here */ 
begin 
    Insert Into @LookupMatchTable (KeyVal) Select 'Key Interview' 
end 
if(1=1) /* use your bool flags here */ 
begin 
    Insert Into @LookupMatchTable (KeyVal) Select 'Special Report' 
end 

declare @LookupMatchTableCount int 
select @LookupMatchTableCount = (select count(*) from @LookupMatchTable) 


SELECT * FROM #TableOne t1 WHERE (@LookupMatchTableCount = 0 OR EXISTS (Select KeyVal from @LookupMatchTable lmt where lmt.KeyVal = t1.MyLabel)) 

/* now show if there are no entries in the look up table, everything comes back */ 
delete from @LookupMatchTable 
select @LookupMatchTableCount = (select count(*) from @LookupMatchTable) 
SELECT * FROM #TableOne t1 WHERE (@LookupMatchTableCount = 0 OR EXISTS (Select KeyVal from @LookupMatchTable lmt where lmt.KeyVal = t1.MyLabel)) 


/* now show that if there is something in the lookup table that doesn't match the "real" table......no rows returned */ 
delete from @LookupMatchTable 
    Insert Into @LookupMatchTable (KeyVal) Select 'No Match Whatsoever' 
select @LookupMatchTableCount = (select count(*) from @LookupMatchTable) 
SELECT * FROM #TableOne t1 WHERE (@LookupMatchTableCount = 0 OR EXISTS (Select KeyVal from @LookupMatchTable lmt where lmt.KeyVal = t1.MyLabel)) 




    IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL 
    begin 
      drop table #TableOne 
    end 
0

그냥 동적 SQL을 잊어 버렸습니다. 아래 쿼리로 이동하여 변경 사항이 필요한지 알려주십시오.

select * from TABLE 
where (Name ='Clean Label' or @is_clean_label=0) 
and ((Name ='Key Interview' or @Is_KeyInterview=0)) 
and ((Name ='Special Report' or @Is_SpecialReport=0))