我如何模拟MySQL中的数组variables?
看起来 MySQL没有数组variables。 我应该用什么来代替?
似乎有两个selectbuild议:一个集合types的标量和临时表 。 我连接的问题表明前者。 但是,使用这些而不是数组variables是好的做法吗? 另外,如果我使用set,那么与foreach
的set-based成语是什么?
那么,我一直在使用临时表,而不是数组variables。 不是最好的解决scheme,但它的工作原理。
请注意,您不需要正式定义其字段,只需使用SELECT创build它们即可:
CREATE TEMPORARY TABLE IF NOT EXISTS my_temp_table SELECT first_name FROM people WHERE last_name = 'Smith';
(另请参阅从select语句创build临时表,而不使用“创build表” 。
你可以使用WHILE
循环在MySQL中实现这个function:
SET @myArrayOfValue = '2,5,2,23,6,'; WHILE (LOCATE(',', @myArrayOfValue) > 0) DO SET @value = ELT(1, @myArrayOfValue); SET @myArrayOfValue= SUBSTRING(@myArrayOfValue, LOCATE(',',@myArrayOfValue) + 1); INSERT INTO `EXEMPLE` VALUES(@value, 'hello'); END WHILE;
编辑:或者,你可以使用UNION ALL
:
INSERT INTO `EXEMPLE` ( `value`, `message` ) ( SELECT 2 AS `value`, 'hello' AS `message` UNION ALL SELECT 5 AS `value`, 'hello' AS `message` UNION ALL SELECT 2 AS `value`, 'hello' AS `message` UNION ALL ... );
不知道数组,但有一种方法可以在普通的VARCHAR列中存储逗号分隔的列表。
而当你需要在列表中find某些东西时,你可以使用FIND_IN_SET()函数。
尝试使用MySql的FIND_IN_SET()函数,例如
SET @c = 'xxx,yyy,zzz'; SELECT * from countries WHERE FIND_IN_SET(countryname,@c);
注意:如果使用CSV值传递参数,则不必在StoredProcedure中设置variables。
DELIMITER $$ CREATE DEFINER=`mysqldb`@`%` PROCEDURE `abc`() BEGIN BEGIN set @value :='11,2,3,1,'; WHILE (LOCATE(',', @value) > 0) SET @V_DESIGNATION = SUBSTRING(@value,1, LOCATE(',',@value)-1); SET @value = SUBSTRING(@value, LOCATE(',',@value) + 1); select @V_DESIGNATION; END WHILE; END; END$$ DELIMITER ;
这是我做的。
首先,我创build了一个函数来检查一个Long / Integer /无论值是否在用逗号分隔的值列表中:
CREATE DEFINER = 'root'@'localhost' FUNCTION `is_id_in_ids`( `strIDs` VARCHAR(255), `_id` BIGINT ) RETURNS BIT(1) NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT '' BEGIN DECLARE strLen INT DEFAULT 0; DECLARE subStrLen INT DEFAULT 0; DECLARE subs VARCHAR(255); IF strIDs IS NULL THEN SET strIDs = ''; END IF; do_this: LOOP SET strLen = LENGTH(strIDs); SET subs = SUBSTRING_INDEX(strIDs, ',', 1); if ( CAST(subs AS UNSIGNED) = _id ) THEN -- founded return(1); END IF; SET subStrLen = LENGTH(SUBSTRING_INDEX(strIDs, ',', 1)); SET strIDs = MID(strIDs, subStrLen+2, strLen); IF strIDs = NULL or trim(strIds) = '' THEN LEAVE do_this; END IF; END LOOP do_this; -- not founded return(0); END;
所以现在你可以在一个以逗号分隔的ID列表中search一个ID,如下所示:
select `is_id_in_ids`('1001,1002,1003',1002);
你可以在WHERE子句中使用这个函数,就像这样:
SELECT * FROM table1 WHERE `is_id_in_ids`('1001,1002,1003',table1_id);
这是我发现将一个“数组”parameter passing给PROCEDURE的唯一方法。
如果你想要关联数组,可以用列(键,值)创build一个临时的内存表。 有一个内存表是在MySQL中有最接近的数组
这工作正常值的列表:
SET @myArrayOfValue = '2,5,2,23,6,'; WHILE (LOCATE(',', @myArrayOfValue) > 0) DO SET @value = ELT(1, @myArrayOfValue); SET @STR = SUBSTRING(@myArrayOfValue, 1, LOCATE(',',@myArrayOfValue)-1); SET @myArrayOfValue = SUBSTRING(@myArrayOfValue, LOCATE(',', @myArrayOfValue) + 1); INSERT INTO `Demo` VALUES(@STR, 'hello'); END WHILE;
使用集合的两个版本都不适合我(用MySQL 5.5testing)。 函数ELT()返回整个集合。 考虑到WHILE语句仅在PROCEDURE语境中可用,我将它添加到我的解决scheme中:
DROP PROCEDURE IF EXISTS __main__; DELIMITER $ CREATE PROCEDURE __main__() BEGIN SET @myArrayOfValue = '2,5,2,23,6,'; WHILE (LOCATE(',', @myArrayOfValue) > 0) DO SET @value = LEFT(@myArrayOfValue, LOCATE(',',@myArrayOfValue) - 1); SET @myArrayOfValue = SUBSTRING(@myArrayOfValue, LOCATE(',',@myArrayOfValue) + 1); END WHILE; END; $ DELIMITER ; CALL __main__;
说实话,我不认为这是一个好的做法。 即使它真的是必要的,这是几乎不可读和相当缓慢。
在5.7.x之后的MYSQL版本中,可以使用JSONtypes来存储数组。 你可以通过MYSQL获得一个数组的值。
我想我可以改善这个答案。 尝试这个:
参数“恶作剧”是一个CSV。 即。 '1,2,3,4 …..等等'
CREATE PROCEDURE AddRanks( IN Pranks TEXT ) BEGIN DECLARE VCounter INTEGER; DECLARE VStringToAdd VARCHAR(50); SET VCounter = 0; START TRANSACTION; REPEAT SET VStringToAdd = (SELECT TRIM(SUBSTRING_INDEX(Pranks, ',', 1))); SET Pranks = (SELECT RIGHT(Pranks, TRIM(LENGTH(Pranks) - LENGTH(SUBSTRING_INDEX(Pranks, ',', 1))-1))); INSERT INTO tbl_rank_names(rank) VALUES(VStringToAdd); SET VCounter = VCounter + 1; UNTIL (Pranks = '') END REPEAT; SELECT VCounter AS 'Records added'; COMMIT; END;
这个方法使search到的CSV值的string随着循环的每一次迭代而逐渐变短,我相信这对于优化来说会更好。
你有没有尝试过使用PHP的序列化()? 这允许你将一个variables的数组内容存储在一个string中。PHP可以理解并且对数据库是安全的(假设你已经先逃脱了它)。
$array = array( 1 => 'some data', 2 => 'some more' ); //Assuming you're already connected to the database $sql = sprintf("INSERT INTO `yourTable` (`rowID`, `rowContent`) VALUES (NULL, '%s')" , serialize(mysql_real_escape_string($array, $dbConnection))); mysql_query($sql, $dbConnection) or die(mysql_error());
你也可以做同样的事情,不用编号数组
$array2 = array( 'something' => 'something else' );
要么
$array3 = array( 'somethingNew' );