Search code examples
mysqldatabasestored-proceduresmysql-error-1064

How to use query string inside IN statement in MySQL stored procedure


friends I have a stored procedure. which taking an input. But the input is a Query string. When I'm executing that string in IN statement I'm not getting anything.

My Stored Procedure is:

CREATE DEFINER=`root`@`localhost` PROCEDURE `SampleProcedure`(IN category VARCHAR(255) 
  IN location VARCHAR(255),
  IN classification VARCHAR(255))

BEGIN
    SELECT u1.firstname , u1.lastname, u1.avatar , s1.address ,c1.cityName 
    FROM user u1,serviceprovider s1, city c1 
    WHERE s1.userId=u1.id 
    AND c1.cityId=s1.city
    AND s1.serviceProviderId 
    IN
    (SELECT DISTINCT serviceprovider_cl AS serviceProviderId FROM  db.serviceprovider_classification t1
      INNER JOIN
      db.locationid t2 ON t1.serviceprovider_cl=t2.serviceprovider_locationId
        INNER JOIN 
            db.serviceprovider_category t3 ON t2.serviceprovider_location
                INNER JOIN
                    db.serviceprovider_category t3 ON t2.serviceprovider_locationId=t3.serviceprovider_category
      WHERE 

       t1.serviceproviderclassification_classification IN (classification)
        AND
      t2.location_serviceLocation IN (location)
       AND
      t3.category_serviceProviderCategory IN (category) 
    );
END

In category, classification and location. I'm getting another query in String. So to execute that string or How to convert it into query or how to use string as Query?
Thanks


Solution

  • for this you can use something called Prepared Statements, you can find more about that here...

    So here is an SQL Fiddle where you can see how prepared statement works...

    As you can see in this simple stored procedure it is not complicated that much. Basically there is three step to do this.

    First create string which will be used in prepared statement. You do this to connect your query and query you will get as a string (IN category VARCHAR(255)) into one statement.

    In my Fiddle:

    SET @myString = 
           CONCAT('SELECT * FROM t2 WHERE t1_id IN (', category, ')');
    

    That is the hardest part. Than you should perapare statement from that string

    PREPARE statement FROM @myString;
    

    End than execute the statement

    EXECUTE statement;
    

    When you call your procedure you pass your string which will be part of statement:

    CALL SimpleProcedure('SELECT id FROM t1 WHERE val1 = "myVal2"');
    

    And that's the logic you should apply on your problem.

    That should look like this:

    CREATE DEFINER=`root`@`localhost` PROCEDURE `SampleProcedure`(IN category VARCHAR(255))
    BEGIN
    
        SET @myString = 
            CONCAT('SELECT u1.firstname , u1.lastname, u1.avatar , s1.address ,c1.cityName 
        FROM user u1,serviceprovider s1, city c1 
        WHERE s1.userId=u1.id 
        AND c1.cityId=s1.city
        AND s1.serviceProviderId 
        IN
        (', category, 
           ' INNER JOIN
           db.serviceprovider_category t3 ON t2.serviceprovider_locationId=t3.serviceprovider_category
           WHERE 
           t3.category_serviceProviderCategory IN (', category, '))');
    
        PREPARE statement FROM @myString;
    
        EXECUTE statement;
    END
    

    EDIT: note that between ' and INNER JOIN there is one blank space because CONCAT, without that, would connect last word from 'category' query and inner join and that will cause you problem and your query wont work!

    GL!

    P.S. Also i notice that you mix both syntax when JOIN table (old comma separated JOIN and the new way) which is not look nice, it would be good to correct that and use new INNER JOIN syntax like you do in your sub query...

    New EDIT (based on question edit)

    CREATE DEFINER=`root`@`localhost` PROCEDURE `SampleProcedure`(IN category VARCHAR(255) 
      IN location VARCHAR(255),
      IN classification VARCHAR(255))
    
    BEGIN
        SET @myString =
        CONCAT('SELECT u1.firstname , u1.lastname, u1.avatar , s1.address ,c1.cityName 
        FROM user u1,serviceprovider s1, city c1 
        WHERE s1.userId=u1.id 
        AND c1.cityId=s1.city
        AND s1.serviceProviderId 
        IN
        (SELECT DISTINCT serviceprovider_cl AS serviceProviderId FROM  db.serviceprovider_classification t1
          INNER JOIN
          db.locationid t2 ON t1.serviceprovider_cl=t2.serviceprovider_locationId
          INNER JOIN 
            db.serviceprovider_category t3 ON t2.serviceprovider_location
                INNER JOIN
                    db.serviceprovider_category t3 ON t2.serviceprovider_locationId=t3.serviceprovider_category
      WHERE 
    
       t1.serviceproviderclassification_classification IN (', classification, ')
        AND
      t2.location_serviceLocation IN (', location, ')
       AND
      t3.category_serviceProviderCategory IN (', category, '))');
    
        PREPARE statement FROM @myString;
        EXECUTE statement;
    END