我如何可以模拟在MySQL中的数组变量?(How can I simulate an array v

2019-06-17 22:18发布

这似乎是MySQL没有数组变量。 我应该用什么呢?


似乎有两个选择建议:一组式标临时表 。 我挂的问题提出了前者。 但它是很好的做法,而是使用数组变量的这些? 或者,如果我带套去,这将是基于集合的成语相当于foreach

Answer 1:

好吧,我一直在使用临时表,而不是数组变量。 不是最大的解决方案,但它的工作原理。

请注意,您并不需要正式定义他们的田地,只是使用SELECT创建它们:

CREATE TEMPORARY TABLE IF NOT EXISTS my_temp_table
SELECT first_name FROM people WHERE last_name = 'Smith';

(另见创建从SELECT语句临时表中不使用创建表 。)



Answer 2:

您可以使用MySQL中实现这个WHILE循环:

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
 ...
);


Answer 3:

尝试使用MySQL例如FIND_IN_SET()函数

SET @c = 'xxx,yyy,zzz';

SELECT * from countries 
WHERE FIND_IN_SET(countryname,@c);

注意:您没有设置各种在StoredProcedure的,如果你正在传递参数与CSV值。



Answer 4:

不知道对数组,但存储逗号分隔的列表中正常VARCHAR列的方式。

而当你需要找到该列表中你可以使用的东西FIND_IN_SET()函数。



Answer 5:

如今使用JSON数组将是一个明显的答案。

由于这是一个古老的,但仍然具有现实意义的问题,我产生一个简单的例子。 JSON功能可从MySQL 5.7.x / MariaDB的10.2.3

我喜欢这个解决方案在ELT(),因为它看起来更像一个数组,这个“数组”可以在代码中重复使用。

但要注意:它(JSON)肯定比使用临时表慢得多。 它只是更加得心应手。 海事组织。

下面是如何使用JSON数组:

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

在这里,一个小例子来展示它是如何工作的一个函数/过程:

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();


Answer 6:

DELIMITER $$
CREATE DEFINER=`mysqldb`@`%` PROCEDURE `abc`()
BEGIN
  BEGIN 
    set @value :='11,2,3,1,'; 
    WHILE (LOCATE(',', @value) > 0) DO
      SET @V_DESIGNATION = SUBSTRING(@value,1, LOCATE(',',@value)-1); 
      SET @value = SUBSTRING(@value, LOCATE(',',@value) + 1); 
      select @V_DESIGNATION;
    END WHILE;
  END;
END$$
DELIMITER ;


Answer 7:

也许创建,如果你想关联数组列(键,值)的临时存储器表。 具有存储器表是最接近于具有MySQL的阵列



Answer 8:

以下是我做到了。

首先,我创建了检查的功能是否长/整数/任何值是用逗号分隔值的列表:

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:

select `is_id_in_ids`('1001,1002,1003',1002);

您还可以使用WHERE子句中这个功能,如下所示:

SELECT * FROM table1 WHERE `is_id_in_ids`('1001,1002,1003',table1_id);

这是我发现“阵列”参数传递给过程的唯一途径。



Answer 9:

这对值列表正常工作:

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;


Answer 10:

使用套我没有工作,两个版本(与MySQL 5.5测试)。 该功能ELT()返回整个集。 考虑到while语句只在过程上下文avaible我把它添加到我的解决方案:

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__;

说实话,我不认为这是一个很好的做法。 即使它真的有必要,这是几乎没有可读的,相当缓慢。



Answer 11:

我知道,这是一个有点迟了回应,但我最近不得不解决类似的问题,并认为这可能是有用的人。

背景

考虑下面叫“mytable的”表:

问题是只保留最新的3条记录,并删除任何较旧的记录,其SYSTEMID = 1(有可能是在与其他SYSTEMID值的表多项纪录)

这将是很好的,你可以做到这一点简单地使用语句

DELETE FROM mytable WHERE id IN (SELECT id FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3)

然而这还不是支持MySQL的,如果你试试这个,那么你会得到这样的错误

...doesn't yet support 'LIMIT & IN/ALL/SOME subquery'

因此,需要一种解决方法,由此值的数组传递到使用可变的IN选择器。 然而,作为变量必须是单值的,我需要模拟阵列关键是要创建的阵列作为逗号分隔值(字符串)的列表,并且分配此给变量如下

SET @myvar := (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);

存储在@myvar结果

5,6,7

接着,FIND_IN_SET选择器用于从模拟阵列选择

SELECT * FROM mytable WHERE FIND_IN_SET(id,@myvar);

将合并的最终结果如下:

SET @myvar := (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);
DELETE FROM mytable WHERE FIND_IN_SET(id,@myvar);

我知道,这是一个非常特殊的情况。 然而,它可被修改,以适应几乎当变量需要存储值的阵列的任何其他情况下。

我希望这个对你有用。



Answer 12:

是不是阵列的点是有效的? 如果你只是通过迭代值,我觉得在一个临时(或永久)表的游标更有意义不是寻求逗号,不是吗? 还干净。 查找 “mysql的DECLARE CURSOR”。

用于随机访问的临时表索引数字的主键。 不幸的是,你会得到最快的访问是一个哈希表,不是真正的随机访问。



Answer 13:

在5.7.x以后的MySQL版本,你可以使用JSON类型存储阵列。 您可以通过MYSQL的关键得到一个数组的值。



Answer 14:

由函数ELT(索引号,字符串1,字符串,STRING3,...),我想下面的例子可以作为一个数组例子启发:

set @i := 1;
while @i <= 3
do
  insert into table(val) values (ELT(@i ,'val1','val2','val3'...));
set @i = @i + 1;
end while;

希望它能帮助。



Answer 15:

我的答案感到惊讶没有提到ELT /场。

ELT /现场工作人员非常相似,特别是如果你有静态数据的数组。

FIND_IN_SET也适用类似但不具有一个内置的互补功能,但它是很容易写一个。

mysql> select elt(2,'AA','BB','CC');
+-----------------------+
| elt(2,'AA','BB','CC') |
+-----------------------+
| BB                    |
+-----------------------+
1 row in set (0.00 sec)

mysql> select field('BB','AA','BB','CC');
+----------------------------+
| field('BB','AA','BB','CC') |
+----------------------------+
|                          2 |
+----------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('CC','AA,BB,CC');
+------------------------------+
| find_in_set('BB','AA,BB,CC') |
+------------------------------+
|                            2 |
+------------------------------+
1 row in set (0.00 sec)

mysql>  SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('AA,BB,CC',',',2),',',-1);
+-----------------------------------------------------------+
| SUBSTRING_INDEX(SUBSTRING_INDEX('AA,BB,CC',',',2),',',-1) |
+-----------------------------------------------------------+
| BB                                                        |
+-----------------------------------------------------------+
1 row in set (0.01 sec)


Answer 16:

我想我可以改进这个答案。 试试这个:

参数“的恶作剧是一个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;

这种方法使CSV值的查找的字符串与循环的每次迭代,我相信会是更好的优化而逐渐变短。



Answer 17:

我会尝试这样的事情了多个集合。 我是一个MySQL的初学者。 很抱歉的函数名,不能决定什么名字将是最好的。

delimiter //

drop  procedure init_
//
create procedure init_()
begin
  CREATE TEMPORARY TABLE if not exists 
    val_store(  
    realm  varchar(30) 
    ,  id  varchar(30) 
    ,  val   varchar(255) 
    ,  primary key ( realm , id )
    );
end;
//

drop function if exists get_
//
create function get_( p_realm varchar(30) , p_id varchar(30) )
  returns varchar(255)
  reads sql data
begin 
  declare ret_val varchar(255);
  declare continue handler for 1146 set ret_val = null;
  select val into ret_val from val_store where id = p_id;
  return ret_val;
end;
//

drop procedure if exists set_
//
create procedure set_( p_realm varchar(30) , p_id varchar(30) , p_val varchar(255) )
begin
  call init_(); 
  insert into val_store (realm,id,val) values (p_realm , p_id , p_val) on duplicate key update val = p_val;
end;
//

drop   procedure if exists remove_
//
create procedure remove_( p_realm varchar(30) , p_id varchar(30) )
begin
  call init_();
  delete from val_store where realm = p_realm and id = p_id;
end;
//

drop   procedure if exists erase_
//
create procedure erase_( p_realm varchar(30) ) 
begin
  call init_();
  delete from val_store where realm = p_realm;
end;
//

call set_('my_array_table_name','my_key','my_value');

select get_('my_array_table_name','my_key');


Answer 18:

你有没有使用PHP的序列化()试过吗? 这允许您将变量数组的内容存储在一个字符串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'
);


文章来源: How can I simulate an array variable in MySQL?