0

Suppose I have the below table ( TestTable ) :

ID , SystemID , UserID ( all columns are of type int )

I want to write a stored procedure that should accept a string parameter; its value like ((5 and 6) or 7) to return all users that apply the below queries :

Select * From TestTable Where SystemID = 5

Intersect

Select * From TestTable Where SystemID = 6

and the above result is union with

Select * From TestTable Where SystemID = 7

SP must accept any combination like (((4 or 5) and 6) or 8) , (((5 or 9) or 8) and 10) .. etc

How can I implement that ?

Update : my issue isn't how to split the string .. but how can i make dynamic sql to implement it's logical mean

4

3 回答 3

1
DECLARE @param NVARCHAR(MAX) = N'4 or 5 and 6 or 8 and 10';


DECLARE 
  @sql NVARCHAR(MAX) = N'', 
  @q NVARCHAR(MAX) = N'SELECT UserID FROM dbo.TestTable WHERE SystemID = ';

SELECT @sql = @q + REPLACE(REPLACE(@param, ' or ', '
   UNION ALL ' + @q),
 ' and ', '
   INTERSECT ' + @q);

PRINT @sql;
-- EXEC sp_executesql @sql;

Results:

SELECT UserID FROM dbo.TestTable WHERE SystemID = 4
   UNION ALL SELECT UserID FROM dbo.TestTable WHERE SystemID = 5
   INTERSECT SELECT UserID FROM dbo.TestTable WHERE SystemID = 6
   UNION ALL SELECT UserID FROM dbo.TestTable WHERE SystemID = 8
   INTERSECT SELECT UserID FROM dbo.TestTable WHERE SystemID = 10

Now, whether this query yields the results you're actually after, I have no idea, but I believe it meets the requirements as stated.

于 2013-04-22T11:56:01.740 回答
-1

Try this... I have little changed Aaron Bertrand's query.

 DECLARE @param NVARCHAR(MAX) = N'(((4 or 5) and 6) or 8)';
    DECLARE   @sql NVARCHAR(MAX) = N'', 
      @q NVARCHAR(MAX) =  N'SELECT * FROM dbo.TestTable WHERE SystemID = ',
      @paranth NVARCHAR(100) = substring(@param,0,PATINDEX('%[0-9]%',@param));
      set @param =substring(@param,PATINDEX('%[0-9]%',@param),len(@param)-PATINDEX('%[0-9]%',@param))

    SELECT @sql = @q + REPLACE(REPLACE(@param, ' or ', '
       UNION ALL ' + @q),
     ' and ', '
       INTERSECT ' + @q);
       set @sql=@paranth+@sql
       if (isnull(@paranth,'')<>'')
        set @sql=@sql+')'

    PRINT @sql;
于 2013-04-22T12:24:51.110 回答
-2

You could use a CSV to Integer table value function inside your SP. You have to create the CsvToInt function first of course. Then you can use it inside your Stored Procedure to turn a parameter into an integer list. As pointed out this only suits the "Or" component of your dynamic search criteria.

You can use this in conjunction with EXEC or sp_executesql. Which will allow you to add sql as a parameter.

SET @myBaseQuery = 'SELECT * FROM TestTable WHERE SystemId = ' + @myParam
EXECUTE(@myBaseQuery)

or

SELECT * FROM TestTable WHERE SystemID IN (SELECT IntValue FROM dbo.CsvToInt('2,3,4,5,6'))
-- use your parameters

CREATE FUNCTION [dbo].[CsvToInt] ( @Array VARCHAR(1000)) 
RETURNS @IntTable TABLE 
    (IntValue INT)
AS
BEGIN
    DECLARE @separator CHAR(1)
    SET @separator = ','
    DECLARE @separator_position INT 
    DECLARE @array_value VARCHAR(1000) 
    SET @array = @array + ','
    While patindex('%,%' , @array) <> 0 
    BEGIN
      SELECT @separator_position =  patindex('%,%' , @array)
      SELECT @array_value = LEFT(@array, @separator_position - 1)
        INSERT @IntTable
        VALUES (CAST(@array_value AS INT))
      SELECT @array = stuff(@array, 1, @separator_position, '')
    END
    RETURN
END

CsvToInt function taken from http://www.summit-pro.com/blog/2010/05/18/csv-list-to-int-sql-function/

于 2013-04-22T11:38:58.200 回答