How can I simulate an array variable in MySQL?
Solution 1
Well, I've been using temporary tables instead of array variables. Not the greatest solution, but it works.
Note that you don't need to formally define their fields, just create them using a SELECT:
DROP TEMPORARY TABLE IF EXISTS my_temp_table;
CREATE TEMPORARY TABLE my_temp_table
SELECT first_name FROM people WHERE last_name = 'Smith';
(See also Create temporary table from select statement without using Create Table.)
Solution 2
You can achieve this in MySQL using WHILE
loop:
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;
EDIT:
Alternatively you can do it using 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
...
);
Solution 3
Try using FIND_IN_SET() function of MySql e.g.
SET @c = 'xxx,yyy,zzz';
SELECT * from countries
WHERE FIND_IN_SET(countryname,@c);
Note: You don't have to SET variable in StoredProcedure if you are passing parameter with CSV values.
Solution 4
Nowadays using a JSON array would be an obvious answer.
Since this is an old but still relevant question I produced a short example. JSON functions are available since mySQL 5.7.x / MariaDB 10.2.3
I prefer this solution over ELT() because it's really more like an array and this 'array' can be reused in the code.
But be careful: It (JSON) is certainly much slower than using a temporary table. Its just more handy. imo.
Here is how to use a JSON array:
SET @myjson = '["gmail.com","mail.ru","arcor.de","gmx.de","t-online.de",
"web.de","googlemail.com","freenet.de","yahoo.de","gmx.net",
"me.com","bluewin.ch","hotmail.com","hotmail.de","live.de",
"icloud.com","hotmail.co.uk","yahoo.co.jp","yandex.ru"]';
SELECT JSON_LENGTH(@myjson);
-- result: 19
SELECT JSON_VALUE(@myjson, '$[0]');
-- result: gmail.com
And here a little example to show how it works in a function/procedure:
DELIMITER //
CREATE OR REPLACE FUNCTION example() RETURNS varchar(1000) DETERMINISTIC
BEGIN
DECLARE _result varchar(1000) DEFAULT '';
DECLARE _counter INT DEFAULT 0;
DECLARE _value varchar(50);
SET @myjson = '["gmail.com","mail.ru","arcor.de","gmx.de","t-online.de",
"web.de","googlemail.com","freenet.de","yahoo.de","gmx.net",
"me.com","bluewin.ch","hotmail.com","hotmail.de","live.de",
"icloud.com","hotmail.co.uk","yahoo.co.jp","yandex.ru"]';
WHILE _counter < JSON_LENGTH(@myjson) DO
-- do whatever, e.g. add-up strings...
SET _result = CONCAT(_result, _counter, '-', JSON_VALUE(@myjson, CONCAT('$[',_counter,']')), '#');
SET _counter = _counter + 1;
END WHILE;
RETURN _result;
END //
DELIMITER ;
SELECT example();
Solution 5
Dont know about the arrays, but there is a way to store comma-separated lists in normal VARCHAR column.
And when you need to find something in that list you can use the FIND_IN_SET() function.
Related videos on Youtube
einpoklum
Made my way from the Olympus of Complexity Theory, Probabilistic Combinatorics and Property Testing to the down-to-earth domain of Heterogeneous and GPU Computing, and now I'm hoping to bring the gospel of GPU and massive-regularized parallelism to DBMS architectures. I've post-doc'ed at the DB architecture group in CWI Amsterdam to do (some of) that. I subscribe to most of Michael Richter's critique of StackOverflow; you might want to take the time to read it. If you listen closely you can hear me muttering "Why am I not socratic again already?"
Updated on July 08, 2022Comments
-
einpoklum almost 2 years
It appears that MySQL doesn't have array variables. What should I use instead?
There seem to be two alternatives suggested: A set-type scalar and temporary tables. The question I linked to suggests the former. But is it good practice to use these instead of array variables? Alternatively, if I go with sets, what would be the set-based idiom equivalent to
foreach
? -
einpoklum almost 12 yearsAren't loops possible only in stored procedures?
-
Omesh almost 12 yearsyes right, its possible inside stored procedures, functions and triggers.
-
einpoklum almost 12 yearsSo I can't use the code you provided... I need something that's applicable more generally.
-
Omesh almost 12 yearsYou can write a sample stored procedure and
CALL
it. -
Omesh almost 12 yearsI don't think arrays are needed. You can easily do it using temporary tables or
UNION ALL
without using procedure. -
einpoklum almost 12 yearsCan you please write another answer demonstration the use of UNION ALL in this context?
-
Omesh almost 12 yearsYa sure. See updated answer, it's similar to two dimensional array.
-
einpoklum over 11 yearsI'm not working with PHP, so that's not really relevant for me.
-
Akshay Vishnoi about 11 yearsIf i want to find subset in a set, is there any way?
-
wormhit about 11 yearsSorry! I'm not sure it is possible.
-
einpoklum almost 11 yearsUmm, I don't want associative arrays, just arrays.
-
Pavle Lekic almost 11 yearsyou can use a temporary memory table with only one column and then loop thru the values using cursors, that is the closest thing to using arrays and for/while loops in a non-declarative programming language
-
einpoklum almost 11 yearsThe language actually has this feature, i.e., there's no syntactic reason you shouldn't be able to select a vector into a variable just like you select a scalar into it.
-
einpoklum over 10 yearsWhat is 'this answer' you're referring to? Also, you don't get to have a CSV file.
-
Igbanam over 9 yearsOhhh :o I didn't know SQL had this!! The tables are only alive for the scope of al queries being run. NEAT!
-
Pacerier about 9 years@Yasky, That's provided you do not reuse connection. Because indeed it will last for the entire session.
-
Pacerier about 9 years@Omesh, Your method of doing it is seriously indirect. Why not simply loop
ELT(x, @myArrayOfValue);
until you getnull
? -
John about 9 yearsAnd you can't reuse a temporary table. So it's not very useful.
-
einpoklum about 9 years@John: How do you mean?
-
John about 9 years
-
einpoklum about 9 years@John: Yeah, well, you can reuse it, but not in the same query.
-
John about 9 years@einpoklum. No, unfortunately that did not work for me. I was trying two separate queries, which was the whole point of making a temporary table. The other funny part to me, was that the user has to have insert rights on the db for a temporary table, so the whole thing is a big hassle for seemingly no benefit (to me). I ended up just making a normal table.
-
einpoklum over 8 yearsPlease explain how this code is to be used and how it answers the question.
-
Rick James over 8 yearsUse JSON instead of serialize. It is more generic and language-independent.
-
Sagar Gangwal over 8 yearsAs here you make simple procedure which gives one by one element of that particular string which work as array in oracle.
-
einpoklum over 8 yearsOracle? This question is not about Oracle. Also, it looks like you're defining an array within the procedure.
-
Sagar Gangwal over 8 yearsKindly check Syntex it's only for mysql
-
einpoklum over 7 yearsCan you give an example of how I would do this?
-
Nemo over 6 yearsBeware of the length limits, which can be quite low: stackoverflow.com/q/2567000/1333493
-
Kanagavelu Sugumar almost 6 yearsAre you saying ELT is slower or JSON is slower ?
-
SeparateReality almost 6 years@Kanagavelu Sugumar: At the time of writing JSON is definitely slower. I edited the answer to make that clearer.
-
einpoklum over 5 yearsThis is a comment, not an answer. I did not indicate that is what I want to do with the array.
-
einpoklum over 5 yearsI think I understand what you're suggesting, but this is quite unwieldy and probably also incredibly slow...
-
Dave over 5 yearsI can't endorse or dismiss it without stress testing it. It is basically a primary key lookup and insertion on a temporary table (or normal table). I will use it until I run into problems or find a better way; but I do weird things like write compilers and games completely in Oracle PL/SQL.
-
Calvin over 5 yearsYou have the best solution
-
Eagle_Eye over 5 yearsDon't miss the last comma!
-
einpoklum over 4 yearsActually, it isn't clear what you're saying here. This question from 7 years ago has several relevant answers. Consider removing your answer or explaining what you're trying to tell us directly/generally rather than through an example.
-
einpoklum over 4 yearscomma-delimited strings have already been suggested - years ago.
-
Ulad Kasach over 4 years@einpoklum yep - and here is another way of interacting with them
-
Nico Haase about 4 yearsPlease share how to do this
-
einpoklum about 4 yearsMy accepted solution is to use a temporary table.
-
kraftydevil about 4 yearsOf course. I then included this answer for anyone like me that got to this page looking for a way to create an array type - who didn't initially understand why arrays are not a type in MySQL. It's by design it seems. The general case wasn't represented here so I included what I learned for others to understand that arrays are not typically needed. I don't expect you to select my answer. It depends on the use case. You have your accepted answer for a specific use case and I'm providing this answer for the general use case.
-
einpoklum about 4 yearsDuplicate of Clinton's answer, I think.
-
user2288580 almost 4 yearsI wasn't referring to a CSV file, I was referring to a CSV value such as '1,2,3,4... etc'
-
Aurast over 3 yearsIf you are reusing connections, you generally should DROP TEMPORARY TABLE IF EXISTS my_temp_table; before creating it.
-
Fabien Haddadi about 3 yearsELT(1, <string>) will return that string, not a substring. What's the point? I thin kyou meant
SELECT SUBSTRING(@myArrayOfValue, 1, LOCATE(',', @myArrayOfValue)-1);
-
Daniil about 2 yearsYou've done a great job! Thanks to you I 've found out about 4 new SQL-functions!
-
Clinton about 2 yearsDelighted to have been able to help.