[mysql] MySQL에서 배열 변수를 어떻게 시뮬레이션 할 수 있습니까?

나타납니다 MySQL이 배열 변수를 가지고 있지 않습니다. 대신 무엇을 사용해야합니까?


제안 된 두 가지 대안이있는 것 같습니다 : 집합 유형 스칼라임시 테이블 . 내가 연결 한 질문은 전자를 제안합니다. 그러나 배열 변수 대신 이것을 사용하는 것이 좋은 습관입니까? 또는 세트로 가면 세트 기반 관용구는 foreach무엇입니까?



답변

글쎄, 나는 배열 변수 대신 임시 테이블을 사용하고 있습니다. 최고의 솔루션은 아니지만 작동합니다.

공식적으로 필드를 정의 할 필요는 없으며 SELECT를 사용하여 생성하기 만하면됩니다.

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

( Create Table을 사용하지 않고 select 문에서 임시 테이블 만들기 도 참조하십시오 .)


답변

WHILE루프를 사용하여 MySQL에서이를 수행 할 수 있습니다 .

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


답변

MySql의 FIND_IN_SET () 함수를 사용해보십시오.

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

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

참고 : CSV 값과 함께 매개 변수를 전달하는 경우 StoredProcedure에서 변수를 설정할 필요가 없습니다.


답변

요즘에는 JSON 배열을 사용하는 것이 분명한 대답이 될 것입니다.

이것은 오래되었지만 여전히 관련이있는 질문이기 때문에 짧은 예를 만들었습니다. mySQL 5.7.x / MariaDB 10.2.3부터 JSON 함수를 사용할 수 있습니다.

ELT ()보다이 솔루션을 선호하는 이유는 배열과 비슷하고 코드에서이 ‘배열’을 재사용 할 수 있기 때문입니다.

하지만 조심하세요. (JSON)은 임시 테이블을 사용하는 것보다 확실히 훨씬 느립니다. 더 편리합니다. imo.

다음은 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();


답변

배열에 대해서는 모르지만 일반 VARCHAR 열에 쉼표로 구분 된 목록을 저장하는 방법이 있습니다.

그리고 그 목록에서 무언가를 찾아야 할 때 FIND_IN_SET () 함수를 사용할 수 있습니다 .


답변

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 ;


답변

답변이 다소 늦었다는 것을 알고 있지만 최근에 비슷한 문제를 해결해야했고 이것이 다른 사람에게 유용 할 것이라고 생각했습니다.

배경

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

나는 이것이 매우 특정한 경우라는 것을 알고 있습니다. 그러나 변수가 값의 배열을 저장해야하는 다른 경우에 맞게 수정할 수 있습니다.

이것이 도움이되기를 바랍니다.