获取 MySQL WHERE IN 定界字符串
Getting the MySQL WHERE IN delimited string
我最近遇到了一个问题,涉及将一串逗号分隔值发送到存储过程中。我的问题是,当我在 PHP 中执行我的存储过程时,它会像这样上传带有引号的值;
CALL `rankingInformation`('145', '5', '', '37,38,39,40,41')
不添加引号会使 MySQL 将它们解释为额外参数。
然而,这并不意味着像查询端的 WHERE IN 那样,它的格式应该像这样
'37', '38', '39', '40', '41'
这是下面的查询,有人能看出我能做些什么吗?这是我目前的情况。
CREATE DEFINER = `root`@` localhost` PROCEDURE` rankingInformation`(IN` surveyId` INT, IN` filterCounting` INT, IN` survey_filter_id` INT, IN` question_limit` TEXT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Gathers all the ranking information for a given ID'
BEGIN
DECLARE sfi int(2);
DECLARE ql TEXT;
IF(survey_filter_id = '') THEN
SET sfi = (SELECT sf2.survey_filter_id FROM survey_filters AS sf2 WHERE sf2.survey_id = 145 AND sf2.survey_filter_id IS NOT NULL LIMIT 1);
ELSE
SET sfi = survey_filter_id;
END IF;
SELECT
COUNT( * ) AS total, CONCAT(su.first_name, ' ', su.last_name) as full_name, sf.survey_filter_id, sf.survey_filter_name, qa.question_id, su.temp_group_1 AS department
FROM questions_answers AS qa
INNER JOIN survey_users AS su ON su.survey_users_id = qa.survey_users_id_answer
INNER JOIN survey_filters AS sf ON sf.survey_id = surveyId
WHERE qa.survey_id = surveyId
AND qa.question_id IN (splitAndTranslate(question_limit, ','))
AND sf.survey_filter_id = sfi
GROUP BY qa.survey_users_id_answer
HAVING total > filterCounting
ORDER BY total DESC;
END
splitAndTranslate
这是我发现的一个函数,它不是用来完成这项工作的,我不确定我离得很远。
CREATE DEFINER=`root`@`localhost` FUNCTION `splitAndTranslate`(`str` TEXT, `delim` VARCHAR(1))
RETURNS text CHARSET utf8
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Fixes all Where IN issues'
BEGIN
DECLARE i INT DEFAULT 0; -- total number of delimiters
DECLARE ctr INT DEFAULT 0; -- counter for the loop
DECLARE str_len INT; -- string length,self explanatory
DECLARE out_str text DEFAULT ''; -- return string holder
DECLARE temp_str text DEFAULT ''; -- temporary string holder
DECLARE temp_val VARCHAR(255) DEFAULT ''; -- temporary string holder for query
-- get length
SET str_len=LENGTH(str);
SET i = (LENGTH(str)-LENGTH(REPLACE(str, delim, '')))/LENGTH(delim) + 1;
-- get total number delimeters and add 1
-- add 1 since total separated values are 1 more than the number of delimiters
-- start of while loop
WHILE(ctr<i) DO
-- add 1 to the counter, which will also be used to get the value of the string
SET ctr=ctr+1;
-- get value separated by delimiter using ctr as the index
SET temp_str = REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, ctr), LENGTH(SUBSTRING_INDEX(str, delim,ctr - 1)) + 1), delim, '');
-- query real value and insert into temporary value holder, temp_str contains the exploded ID
#SELECT ImageFileName INTO temp_val FROM custombu_roomassets_images WHERE ImageID=temp_str;
-- concat real value into output string separated by delimiter
SET out_str=CONCAT(out_str, temp_val, ',');
END WHILE;
-- end of while loop
-- trim delimiter from end of string
SET out_str=TRIM(TRAILING delim FROM out_str);
RETURN(out_str); -- return
END
在 SQL IN 比较的上下文中,字符串值中的逗号 而不是 被解释为 SQL 文本。您的查询基本上是以下形式:
AND qa.question_id IN ('some,long,string,value')
并且字符串中的任何逗号字符都只是数据;只是作为字符串一部分的字符。这实际上与等于比较相同。
MySQL FIND_IN_SET
函数可能是您执行所需比较的一种方式。
http://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_find-in-set
你用 FIND_IN_SET 做了什么?基于 spencer7593 的答案,如果您替换它应该可以工作:
AND qa.question_id IN (splitAndTranslate(question_limit, ','))
和
AND FIND_IN_SET(qa.question_id, question_limit)>0
AND qa.question_id IN (splitAndTranslate(question_limit, ','))
用这些行代替上面的行
AND (qa.question_id = question_limit
OR qa.question_id LIKE CONCAT(question_limit,',%')
OR qa.question_id LIKE CONCAT('%,',question_limit,',%')
OR qa.question_id LIKE CONCAT('%,',question_limit))
那么您就不再需要 splitAndTranslate 函数了。 .
我最近遇到了一个问题,涉及将一串逗号分隔值发送到存储过程中。我的问题是,当我在 PHP 中执行我的存储过程时,它会像这样上传带有引号的值;
CALL `rankingInformation`('145', '5', '', '37,38,39,40,41')
不添加引号会使 MySQL 将它们解释为额外参数。
然而,这并不意味着像查询端的 WHERE IN 那样,它的格式应该像这样
'37', '38', '39', '40', '41'
这是下面的查询,有人能看出我能做些什么吗?这是我目前的情况。
CREATE DEFINER = `root`@` localhost` PROCEDURE` rankingInformation`(IN` surveyId` INT, IN` filterCounting` INT, IN` survey_filter_id` INT, IN` question_limit` TEXT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Gathers all the ranking information for a given ID'
BEGIN
DECLARE sfi int(2);
DECLARE ql TEXT;
IF(survey_filter_id = '') THEN
SET sfi = (SELECT sf2.survey_filter_id FROM survey_filters AS sf2 WHERE sf2.survey_id = 145 AND sf2.survey_filter_id IS NOT NULL LIMIT 1);
ELSE
SET sfi = survey_filter_id;
END IF;
SELECT
COUNT( * ) AS total, CONCAT(su.first_name, ' ', su.last_name) as full_name, sf.survey_filter_id, sf.survey_filter_name, qa.question_id, su.temp_group_1 AS department
FROM questions_answers AS qa
INNER JOIN survey_users AS su ON su.survey_users_id = qa.survey_users_id_answer
INNER JOIN survey_filters AS sf ON sf.survey_id = surveyId
WHERE qa.survey_id = surveyId
AND qa.question_id IN (splitAndTranslate(question_limit, ','))
AND sf.survey_filter_id = sfi
GROUP BY qa.survey_users_id_answer
HAVING total > filterCounting
ORDER BY total DESC;
END
splitAndTranslate 这是我发现的一个函数,它不是用来完成这项工作的,我不确定我离得很远。
CREATE DEFINER=`root`@`localhost` FUNCTION `splitAndTranslate`(`str` TEXT, `delim` VARCHAR(1))
RETURNS text CHARSET utf8
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Fixes all Where IN issues'
BEGIN
DECLARE i INT DEFAULT 0; -- total number of delimiters
DECLARE ctr INT DEFAULT 0; -- counter for the loop
DECLARE str_len INT; -- string length,self explanatory
DECLARE out_str text DEFAULT ''; -- return string holder
DECLARE temp_str text DEFAULT ''; -- temporary string holder
DECLARE temp_val VARCHAR(255) DEFAULT ''; -- temporary string holder for query
-- get length
SET str_len=LENGTH(str);
SET i = (LENGTH(str)-LENGTH(REPLACE(str, delim, '')))/LENGTH(delim) + 1;
-- get total number delimeters and add 1
-- add 1 since total separated values are 1 more than the number of delimiters
-- start of while loop
WHILE(ctr<i) DO
-- add 1 to the counter, which will also be used to get the value of the string
SET ctr=ctr+1;
-- get value separated by delimiter using ctr as the index
SET temp_str = REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, ctr), LENGTH(SUBSTRING_INDEX(str, delim,ctr - 1)) + 1), delim, '');
-- query real value and insert into temporary value holder, temp_str contains the exploded ID
#SELECT ImageFileName INTO temp_val FROM custombu_roomassets_images WHERE ImageID=temp_str;
-- concat real value into output string separated by delimiter
SET out_str=CONCAT(out_str, temp_val, ',');
END WHILE;
-- end of while loop
-- trim delimiter from end of string
SET out_str=TRIM(TRAILING delim FROM out_str);
RETURN(out_str); -- return
END
在 SQL IN 比较的上下文中,字符串值中的逗号 而不是 被解释为 SQL 文本。您的查询基本上是以下形式:
AND qa.question_id IN ('some,long,string,value')
并且字符串中的任何逗号字符都只是数据;只是作为字符串一部分的字符。这实际上与等于比较相同。
MySQL FIND_IN_SET
函数可能是您执行所需比较的一种方式。
http://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_find-in-set
你用 FIND_IN_SET 做了什么?基于 spencer7593 的答案,如果您替换它应该可以工作:
AND qa.question_id IN (splitAndTranslate(question_limit, ','))
和
AND FIND_IN_SET(qa.question_id, question_limit)>0
AND qa.question_id IN (splitAndTranslate(question_limit, ','))
用这些行代替上面的行
AND (qa.question_id = question_limit
OR qa.question_id LIKE CONCAT(question_limit,',%')
OR qa.question_id LIKE CONCAT('%,',question_limit,',%')
OR qa.question_id LIKE CONCAT('%,',question_limit))
那么您就不再需要 splitAndTranslate 函数了。 .