Сгенерированные параметры динамического добавления запроса c в предложении WHERE с синтаксической ошибкой на основе условия SQL Server 2012 - PullRequest
0 голосов
/ 28 апреля 2020

У меня запрос на SQL Сервер, используется CTE. Запрос генерируется динамически каждый раз, когда процедура запускается с несколькими параметрами в WHERE clause, которые должны быть присоединены на основе параметров, имеющих значения. Проблема в том, что есть несколько значений, которые нужно добавить в зависимости от условия. Поэтому пользователь не может передавать никакие значения, тогда WHERE clause нет. Но если пользователь передает все параметры, это любой параметр, то как мне добавить его, используя and. Из-за этого сгенерированного запроса, имеющего синтаксическую ошибку. Как мне исправить это?

declare @vflag varchar(50)=null, @udisecode varchar(20)='1141701604',  @district int=null,  @zone int=0, @block int=null,  
  @classid int=null, @className varchar(10)=null, @report varchar(20)=null, @gender varchar(6)=null,
  @religion int=null, @category int=null, @subjectid int=null, @subject varchar(30)=null,  
  @querystr varchar(MAX)=null
set @querystr='
    ;with cte1 as(
       select udise_no,student_regno,fullname,dob,domicile_yesno,admission_date,gender,class_id from tbl_personal
    ),cte2 as(
       select udise_no,student_regno,religion_id,student_category,student_caste from tbl_reservation
    ),cte3 as(
       select categoryname,ID from tbl_category
    ),cte4 as(
       select id,religion from tbl_religion
    ),cte5 as(
       select udisecode,school_name,district_id,block_id from school_master
    ),cte6 as(
       select district_id,district_name from district_master
    ),cte7 as(
       select block_id,block_name,district_id from block_master
    )

    select a.udise_no, a.fullname as studentname,a.gender,REPLACE(CONVERT(varchar,a.dob,106),'' '',''-'') as dob,
    ISNULL(d.categoryname,'''') as category,
    ISNULL(c.religion,'''') as religion,
    a.domicile_yesno as domicile,a.class_id as class,
    a.student_regno,
    schoolmaster.school_name,
    districtmaster.district_name as district,
    blockmaster.block_name
    from cte1 a

    left join cte2 b
    ON b.udise_no=a.udise_no and b.student_regno=a.student_regno

    left join cte4 c
    on c.ID=b.religion_id

    left join cte3 d
    on d.ID=b.student_category

    left join cte5 schoolmaster
    on a.udise_no=schoolmaster.udisecode

    left join cte6 districtmaster
    on districtmaster.district_id=schoolmaster.district_id

    left join cte7 blockmaster
    on blockmaster.district_id=districtmaster.district_id and 
       blockmaster.district_id=schoolmaster.district_id and
       blockmaster.block_id=schoolmaster.block_id' 


if(@district is not null OR @block is not null OR @udisecode is not null OR 
   @className is not null OR @category is not null OR @religion is not null OR
   @gender is not null)
  set @querystr += ' Where '
if(@district is not null)
  set @querystr += ' convert(varchar,schoolmaster.district_id) LIKE '''+ISNULL(convert(varchar,@district),'%')+''''
if(@block is not null)
  set @querystr += ' and convert(varchar,schoolmaster.block_id) LIKE '''+ISNULL(convert(varchar,@block),'%')+''''
if(@udisecode is not null)
  set @querystr += ' and a.udise_no LIKE '''+ISNULL(@udisecode,'%')+''''
if(@className is not null)
  set @querystr += ' and a.class_id LIKE '''+ISNULL(@className,'%')+''''
if(@category is not null)
  set @querystr += ' and CONVERT(varchar,b.student_category) LIKE '''+ISNULL(CONVERT(varchar,@category),'%')+''''
if(@religion is not null)
  set @querystr += ' and CONVERT(varchar,b.religion_id) LIKE '''+ISNULL(CONVERT(varchar,@religion),'%')+''''
if(@gender is not null)
  set @querystr += ' and a.gender LIKE '''+ISNULL(@gender,'%')+''''

set @querystr += ' order by districtmaster.district_name,blockmaster.block_name'
print(@querystr)
--exec(@querystr)

Синтаксическая ошибка:

Where and a.udise_no LIKE '1141701604' order by districtmaster.district_name,blockmaster.block_name

1 Ответ

1 голос
/ 28 апреля 2020

Люди используют where 1 = 1, потому что по своей природе они ленивы при создании динамических c SQL запросов. Если вы начинаете с where 1 = 1, тогда все ваши дополнительные предложения начинаются с AND, и вам не нужно выяснять.

Запрос должен быть

DECLARE @vflag VARCHAR(50) = NULL, 
        @udisecode VARCHAR(20) = '1141701604',
        @district INT = NULL,
        @zone INT = 0, 
        @block INT = NULL,  
        @classid INT = NULL,
        @className VARCHAR(10) = NULL, 
        @report VARCHAR(20) = NULL,
        @gender VARCHAR(6) = NULL,
        @religion INT = NULL, 
        @category INT = NULL, 
        @subjectid INT = NULL, 
        @subject VARCHAR(30) = NULL,
        @querystr VARCHAR(MAX) = NULL

SET @querystr = '
    ;with cte1 AS(
       SELECT udise_no,student_regno,fullname,dob,domicile_yesno,admission_date,gender,class_id from tbl_personal
    ),cte2 AS(
       SELECT udise_no,student_regno,religion_id,student_category,student_caste from tbl_reservation
    ),cte3 AS(
       SELECT categoryname,ID from tbl_category
    ),cte4 AS(
       SELECT id,religion from tbl_religion
    ),cte5 AS(
       SELECT udisecode,school_name,district_id,block_id from school_master
    ),cte6 AS(
       SELECT district_id,district_name from district_master
    ),cte7 AS(
       SELECT block_id,block_name,district_id from block_master
    )

    SELECT a.udise_no, a.fullname AS studentname,a.gender,REPLACE(CONVERT(VARCHAR,a.dob,106),'' '',''-'') AS dob, ISNULL(d.categoryname,'''') AS category,
            ISNULL(c.religion,'''') AS religion, a.domicile_yesno AS domicile,a.class_id AS class, a.student_regno, schoolmaster.school_name, 
            districtmaster.district_name AS district, blockmaster.block_name
    FROM cte1 a LEFT JOIN cte2 b ON b.udise_no = a.udise_no AND b.student_regno = a.student_regno
    LEFT JOIN cte4 c ON c.ID = b.religion_id
    LEFT JOIN cte3 d ON d.ID = b.student_category
    LEFT JOIN cte5 schoolmaster ON a.udise_no = schoolmaster.udisecode
    LEFT JOIN cte6 districtmaster ON districtmaster.district_id = schoolmaster.district_id
    LEFT JOIN cte7 blockmaster ON blockmaster.district_id = districtmaster.district_id AND  blockmaster.district_id = schoolmaster.district_id AND blockmaster.block_id = schoolmaster.block_id' 


IF(@district IS NOT NULL OR @block IS NOT NULL OR @udisecode IS NOT NULL OR @className IS NOT NULL OR @category IS NOT NULL OR @religion IS NOT NULL OR @gender IS NOT NULL)
    SET @querystr +=  ' WHERE 1 = 1'
IF(@district IS NOT NULL)
    SET @querystr +=  'AND convert(VARCHAR,schoolmaster.district_id) LIKE '''+ISNULL(convert(VARCHAR,@district),'%')+''''
IF(@block IS NOT NULL)
    SET @querystr +=  ' AND convert(VARCHAR,schoolmaster.block_id) LIKE '''+ISNULL(convert(VARCHAR,@block),'%')+''''
IF(@udisecode IS NOT NULL)
    SET @querystr +=  ' AND a.udise_no LIKE '''+ISNULL(@udisecode,'%')+''''
IF(@className IS NOT NULL)
    SET @querystr +=  ' AND a.class_id LIKE '''+ISNULL(@className,'%')+''''
IF(@category IS NOT NULL)
    SET @querystr +=  ' AND CONVERT(VARCHAR,b.student_category) LIKE '''+ISNULL(CONVERT(VARCHAR,@category),'%')+''''
IF(@religion IS NOT NULL)
    SET @querystr +=  ' AND CONVERT(VARCHAR,b.religion_id) LIKE '''+ISNULL(CONVERT(VARCHAR,@religion),'%')+''''
IF(@gender IS NOT NULL)
    SET @querystr +=  ' AND a.gender LIKE '''+ISNULL(@gender,'%')+''''

SET @querystr +=  ' order by districtmaster.district_name,blockmaster.block_name'
PRINT(@querystr)
EXEC (@querystr)
...