Dynamic WHERE clause

  • Dear all,

    I having a table "Employee", with field "EmpID" & "EmpName".

    Currently there are 3 records:

    EmpID: 1

    EmpName: Ashly

    EmpID: 2

    EmpName: Bob

    EmpID: 3

    EmpName: Charles

    Q1: How should I write a stored procedure (sp_GetName) to select EmpName = "Bob" OR EmpName = "Charles"?

    Q2: After retrieve record EmpName = "Bob" OR EmpName = "Charles", I need to insert these records into another table (TableName: TempEmployee)

    Urgently required help. 🙂

  • A1)

    create procedure Emp_name_proc

    (

    @emp_id int

    )

    as

    begin

    select EmpName from Employee/*with lock options*/

    where EmpID = @emp_id

    end

    A2)

    insert into TempEmployee

    exec Emp_name_proc 2

    And it’s not advisable to create the procedure with SP_

    Because it’s also reflects/access to other DB

  • arun.sas (8/13/2009)


    A1)

    create procedure Emp_name_proc

    (

    @emp_id int

    )

    as

    begin

    select EmpName from Employee/*with lock options*/

    where EmpID = @emp_id

    end

    A2)

    insert into TempEmployee

    exec Emp_name_proc 2

    And it’s not advisable to create the procedure with SP_

    Because it’s also reflects/access to other DB

    If I just use "exec Emp_name_proc 2", it will return me just "Bob", I need the "Charles" result as well 🙂

  • create procedure Emp_name_proc

    (

    @emp_id int

    )

    as

    begin

    1) output like

    ‘Bob’

    ‘Charles’

    select EmpName from Employee/*with lock options*/

    where EmpID = @emp_id

    union

    select EmpName from Employee/*with lock options*/

    where EmpID = @emp_id+1

    2) output like ‘Bob,Charles’

    declare @concat nvarchar(1000)

    select @concat= COALESCE(@concat+',' , '')+ EmpName from Employee/*with lock options*/

    where EmpID in(@emp_id,@emp_id+1)

    select @concat

    end

  • arun.sas (8/13/2009)


    create procedure Emp_name_proc

    (

    @emp_id int

    )

    as

    begin

    1) output like

    ‘Bob’

    ‘Charles’

    select EmpName from Employee/*with lock options*/

    where EmpID = @emp_id

    union

    select EmpName from Employee/*with lock options*/

    where EmpID = @emp_id+1

    2) output like ‘Bob,Charles’

    declare @concat nvarchar(1000)

    select @concat= COALESCE(@concat+',' , '')+ EmpName from Employee/*with lock options*/

    where EmpID in(@emp_id,@emp_id+1)

    select @concat

    end

    I think my question is misleading.

    I wish to have flexibility on the WHERE clause. The example that I gave is "Bob" and "Charles".

    But if I wan select "Ashly" and "Charles"?

  • create table test

    (

    EmpID int,

    EmpName varchar(20)

    )

    insert into test

    select 1,'Ashly'

    union all

    select 2,'Bob'

    union all

    select 3,'Charles'

    CREATE procedure Emp_name_proc

    (

    @emp_id varchar(100)

    )

    as

    begin

    declare @abc varchar(100)

    select @abc = @emp_id

    select @abc = 'select ''' + replace (@ABC,',',''' union select ''')+''''

    create table #temp (name1 int)

    insert into #temp (name1)

    exec (@ABC)

    select EmpName from test

    where EmpID in (select name1 from #temp)

    end

    exec Emp_name_proc '1,2'

    EmpName

    Ashly

    Bob

    exec Emp_name_proc '1,3'

    EmpName

    Ashly

    Charles

    exec Emp_name_proc '2,3'

    EmpName

    Bob

    Charles

    exec Emp_name_proc '1,2,3'

    EmpName

    Ashly

    Bob

    Charles

  • Thanks for your help and I manage to solve this case.

    "arun.sas" you are such a genius man !!! 😀

    Remark: But cannot view Estimated Execution Plan, got error "Invalid object name '#temp'."

  • I think this code is much simpler.

    ALTER procedure Emp_name_proc

    (

    @emp_id varchar(100)

    )

    as

    begin

    declare @sql varchar(100)

    select @sql = 'SELECT EmpName FROM Test WHERE EmpID IN (' + @emp_id + ')'

    Exec( @sql )

    end

    No need for a temporary table. No need to modify the input string (assuming that you can be sure the inputs are separated by commas).

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • create table test

    (

    EmpID int,

    EmpName varchar(20)

    );

    create table TempEmployee

    (

    EmpID int,

    EmpName varchar(20)

    );

    insert into test

    select 1,'Ashly'

    union all

    select 2,'Bob'

    union all

    select 3,'Charles'

    declare @xmlNames xml;

    select @xmlNames = '

    Bob

    Charles';

    insert dbo.TempEmployee( empID, empName)

    select tbl.empID, tbl.empName

    from dbo.test tbl

    where tbl.empName in (

    select

    names.n.value('.', 'varchar(20)')

    from @xmlNames.nodes('/name') names(n)

    )



    Posting Data Etiquette - Jeff Moden[/url]
    Posting Performance Based Questions - Gail Shaw[/url]
    Hidden RBAR - Jeff Moden[/url]
    Cross Tabs and Pivots - Jeff Moden[/url]
    Catch-all queries - Gail Shaw[/url]


    If you don't have time to do it right, when will you have time to do it over?

  • for all these dynamic SQL things, you might want to consider reading this article:

    http://www.databasejournal.com/features/mssql/article.php/3830981/T-SQL-Best-Practices--Part-2.htm

    for example, the code drew posted,

    ALTER procedure Emp_name_proc

    (

    @emp_id varchar(100)

    )

    as

    begin

    declare @sql varchar(100)

    select @sql = 'SELECT EmpName FROM Test WHERE EmpID IN (' + @emp_id + ')'

    Exec( @sql )

    end

    instead of saying exec (@sql), which runs the risk of having injection. what you could do is rewrite it to be:

    set @sql = 'select EmpName FROM Test WHERE EmpID IN (' + @empid + ')'

    EXEC sp_executesql @sql, N'@emp_id varchar(100)',@emp_id=@emp_id

    this way, you can't throw injection in (well, at least not as easily)

    also, if you read through the article, you'll see that when you're dealing with multiple optional where clauses, this approach can give you a much better execution rate, since you don't have to worry about your indexes not being used due to where clauses that are not being used

  • set @sql = 'select EmpName FROM Test WHERE EmpID IN (' + @empid + ')'

    EXEC sp_executesql @sql, N'@emp_id varchar(100)',@emp_id=@emp_id

    this way, you can't throw injection in (well, at least not as easily)

    also, if you read through the article, you'll see that when you're dealing with multiple optional where clauses, this approach can give you a much better execution rate, since you don't have to worry about your indexes not being used due to where clauses that are not being used

    kramaswamy,

    I think you meant to have this code like the following. Otherwise with the code above there will not be an embedded parameter. It would just be concatenating whatever value was in @empid into the original string being created in @sql.:

    set @sql = 'select EmpName FROM Test WHERE EmpID IN (@empid)'

    EXEC sp_executesql @sql, N'@emp_id varchar(100)',@emp_id=@emp_id

  • drew.allen (8/14/2009)


    I think this code is much simpler.

    ALTER procedure Emp_name_proc

    (

    @emp_id varchar(100)

    )

    as

    begin

    declare @sql varchar(100)

    select @sql = 'SELECT EmpName FROM Test WHERE EmpID IN (' + @emp_id + ')'

    Exec( @sql )

    end

    No need for a temporary table. No need to modify the input string (assuming that you can be sure the inputs are separated by commas).

    Drew

    How if I want to make the select statement under "DECLARE CURSOR_ABC"?

  • You don't need any dynamic sql for this as I already demonstrated. You just give your procedure 1 parameter; the xml string with the names that you are looking for. No sql injection issues, no complicated parsing, no limitations with regards to cursors (which you should try and avoid at all costs, by the way) and -what i did not hear in this thread yet- no issues with choosing and implementing an escape sequence (i.e. what to do if one of the values in the comma separated string contains a comma). All that and it's a standard feature in SQL server 2005 and up.



    Posting Data Etiquette - Jeff Moden[/url]
    Posting Performance Based Questions - Gail Shaw[/url]
    Hidden RBAR - Jeff Moden[/url]
    Cross Tabs and Pivots - Jeff Moden[/url]
    Catch-all queries - Gail Shaw[/url]


    If you don't have time to do it right, when will you have time to do it over?

Viewing 13 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic. Login to reply