MySQL'de bir dizi değişkenini nasıl simüle edebilirim?


91

Görünen MySQL dizi değişkenleri yok. Onun yerine ne kullanmalıyım?


Önerilen iki alternatif var gibi görünüyor: Küme tipi bir skaler ve geçici tablolar . Bağlandığım soru ilkini akla getiriyor. Ancak dizi değişkenleri yerine bunları kullanmak iyi bir uygulama mı? Alternatif olarak, kümelerle gidersem, küme tabanlı deyim neye eşdeğer olur foreach?

Yanıtlar:


78

Dizi değişkenleri yerine geçici tablolar kullanıyorum. En büyük çözüm değil ama işe yarıyor.

Alanlarını resmi olarak tanımlamanıza gerek olmadığını unutmayın, sadece bir SEÇİM kullanarak oluşturun:

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

(Ayrıca bkz . Tablo Oluştur kullanmadan select deyiminden geçici tablo oluşturma .)


1
Ohhh: o SQL'in buna sahip olduğunu bilmiyordum !! Tablolar yalnızca çalıştırılan tüm sorguların kapsamı için canlıdır. DÜZGÜN!
iGbanam

2
@Yasky, Bağlantıyı yeniden kullanmamanız şartıyla. Çünkü gerçekten tüm seans boyunca sürecek .
Pacerier


4
@John: Evet, onu yeniden kullanabilirsiniz , ancak aynı sorguda değil.
einpoklum

1
Bağlantıları yeniden kullanıyorsanız, genel olarak GEÇİCİ TABLO VARSA DÜŞMELİSİNİZ my_temp_table; oluşturmadan önce.
Aurast

46

Bunu MySQL'de WHILEdöngü kullanarak elde edebilirsiniz :

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;

DÜZENLEME: Alternatif olarak şunu kullanarak da yapabilirsiniz 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
 ...
);

4
Döngüler yalnızca saklı yordamlarda mümkün değil mi?
einpoklum

2
evet doğru, saklanan prosedürler, işlevler ve tetikleyiciler içinde mümkündür.
Omesh

1
Bu yüzden verdiğiniz kodu kullanamıyorum ... Daha genel olarak uygulanabilir bir şeye ihtiyacım var.
einpoklum

Örnek bir saklı yordam yazabilirsiniz CALL.
Omesh

1
Dizilere ihtiyaç olduğunu sanmıyorum. Geçici tablolar UNION ALLkullanarak veya prosedür kullanmadan kolayca yapabilirsiniz .
Omesh

28

MySql'in FIND_IN_SET () işlevini kullanmayı deneyin örn.

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

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

Not: Parametreyi CSV değerleriyle geçiriyorsanız, StoredProcedure'da değişken AYARLAMAK zorunda değilsiniz.


Oldukça düşük olabilecek uzunluk sınırlarına dikkat edin: stackoverflow.com/q/2567000/1333493
Nemo

19

Günümüzde bir JSON dizisi kullanıyor bariz bir cevap olacaktır.

Bu eski ama yine de geçerli bir soru olduğu için kısa bir örnek oluşturdum. JSON işlevleri, mySQL 5.7.x / MariaDB 10.2.3'ten itibaren mevcuttur.

ELT () yerine bu çözümü tercih ediyorum çünkü gerçekten bir dizi gibi ve bu 'dizi' kodda yeniden kullanılabilir.

Ancak dikkatli olun: Bu (JSON) kesinlikle geçici bir tablo kullanmaktan çok daha yavaştır. Sadece daha kullanışlıdır. imo.

JSON dizisinin nasıl kullanılacağı aşağıda açıklanmıştır:

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

Ve burada bir fonksiyonda / prosedürde nasıl çalıştığını göstermek için küçük bir örnek:

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

ELT'nin daha yavaş olduğunu mu yoksa JSON'un daha yavaş olduğunu mu söylüyorsunuz?
Kanagavelu Sugumar

2
@Kanagavelu Sugumar: JSON yazarken kesinlikle daha yavaştır. Bunu daha net hale getirmek için cevabı düzenledim.
SeparateReality

16

Diziler hakkında bilgim yok, ancak virgülle ayrılmış listeleri normal VARCHAR sütununda saklamanın bir yolu var.

Ve bu listede bir şey bulmanız gerektiğinde, FIND_IN_SET () işlevini kullanabilirsiniz.


Bir kümede alt kümeyi bulmak istersem, herhangi bir yolu var mı?
Akshay Vishnoi

Afedersiniz! Bunun mümkün olduğundan emin değilim.
wormhit

En iyi çözüme sahipsin
Calvin

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

2
Lütfen bu kodun nasıl kullanılacağını ve soruyu nasıl yanıtladığını açıklayın.
einpoklum

Burada olduğu gibi, oracle'da dizi olarak çalışan belirli dizgenin tek tek elemanını veren basit bir prosedür yaparsınız.
Sagar Gangwal

Oracle? Bu soru Oracle ile ilgili değil. Ayrıca, prosedür içinde bir dizi tanımladığınız görülüyor.
einpoklum

Lütfen
Syntex'i

Son virgülü kaçırmayın!
Eagle_Eye

4

Bunun biraz geç bir yanıt olduğunu biliyorum, ancak yakın zamanda benzer bir sorunu çözmek zorunda kaldım ve bunun başkaları için yararlı olabileceğini düşündüm.

Arka fon

Aşağıdaki 'mytable' adlı tabloyu düşünün:

Başlangıç ​​tablosu

Sorun, yalnızca en son 3 kaydı tutmak ve systemid = 1 olan eski kayıtları silmekti (tablodaki diğer sistemid değerlerine sahip birçok başka kayıt olabilir)

Bunu basitçe ifadeyi kullanarak yapabilmen iyi olur.

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

Ancak bu MySQL'de henüz desteklenmemektedir ve bunu denerseniz, o zaman aşağıdaki gibi bir hata alırsınız:

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

Dolayısıyla, değişken kullanılarak IN seçiciye bir değerler dizisinin aktarıldığı bir geçici çözüm gereklidir. Bununla birlikte, değişkenlerin tek değerler olması gerektiğinden, bir diziyi simüle etmem gerekir . İşin püf noktası, diziyi virgülle ayrılmış değerler listesi (dize) olarak oluşturmak ve bunu değişkene aşağıdaki gibi atamaktır.

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'da depolanan sonuç

5,6,7

Ardından, FIND_IN_SET seçici, simüle edilen diziden seçim yapmak için kullanılır

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

Birleşik nihai sonuç aşağıdaki gibidir:

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

Bunun çok özel bir durum olduğunun farkındayım. Bununla birlikte, bir değişkenin bir değer dizisi depolaması gereken diğer herhangi bir duruma uyacak şekilde değiştirilebilir.

Umarım bu yardımcı olur.


3

İlişkili diziler istiyorsanız, sütunlarla (anahtar, değer) geçici bir bellek tablosu oluşturabilirsiniz. Bir bellek tablosuna sahip olmak, mysql'de dizilere sahip olmaya en yakın şeydir


Umm, ilişkisel diziler istemiyorum, sadece diziler.
einpoklum 01

Yalnızca bir sütunlu geçici bir bellek tablosu kullanabilir ve ardından imleçleri kullanarak değerlerde döngü yapabilirsiniz, bu, bildirimsel olmayan bir programlama dilinde dizileri ve for / while döngülerini kullanmaya en yakın şeydir
Pavle Lekic

Dil aslında bu özelliğe sahiptir, yani, bir skaler seçtiğiniz gibi, bir değişkene bir vektör seçememenizin sözdizimsel bir nedeni yoktur.
einpoklum

3

İşte bunu nasıl yaptım.

İlk olarak, bir Uzun / Tamsayı / virgülle ayrılmış değerler listesinde bir değer olup olmadığını kontrol eden bir işlev oluşturdum:

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;

Artık virgülle ayrılmış bir kimlik listesinde aşağıdaki gibi bir kimlik arayabilirsiniz:

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

Ve bu işlevi bir WHERE yan tümcesinde şu şekilde kullanabilirsiniz:

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

Bu, bir "dizi" parametresini bir PROSEDÜR'e geçirmenin tek yoluydu.


2

Dizilerin amacı verimli olmak değil mi? Sadece değerler arasında yineleme yapıyorsanız, geçici (veya kalıcı) bir tablodaki imleç virgül aramaktan daha mantıklı değil mi? Ayrıca daha temiz. Arama "mysql CURSOR".

Rastgele erişim için, sayısal olarak indekslenmiş birincil anahtara sahip geçici bir tablo. Maalesef alacağınız en hızlı erişim, gerçek bir rastgele erişim değil, bir karma tablodur.


Bu bir yorum, cevap değil. Diziyle yapmak istediğim şeyin bu olduğunu belirtmedim.
einpoklum

2

Cevapların hiçbirinin ELT / FIELD'den bahsetmediğine şaşırdım.

ELT / FIELD, özellikle statik verileriniz varsa bir diziye çok benzer şekilde çalışır.

FIND_IN_SET de benzer şekilde çalışır, ancak yerleşik bir tamamlayıcı işlevi yoktur, ancak bir tane yazmak için yeterince kolaydır.

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('BB','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)

1

Bu, değerler listesi için iyi çalışır:

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;

1

Set kullanan her iki sürüm de benim için çalışmadı (MySQL 5.5 ile test edildi). ELT () işlevi tüm kümeyi döndürür. WHILE ifadesinin yalnızca PROSEDÜR bağlamında geçerli olduğunu düşünerek onu çözümüme ekledim:

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

Dürüst olmak gerekirse, bunun iyi bir uygulama olduğunu düşünmüyorum. Gerçekten gerekli olsa bile, bu zar zor okunabilir ve oldukça yavaştır.


1

Aynı sorunu görmenin başka bir yolu. Umarım yardımcı olur

DELIMITER $$
CREATE PROCEDURE ARR(v_value VARCHAR(100))
BEGIN

DECLARE v_tam VARCHAR(100);
DECLARE v_pos VARCHAR(100);

CREATE TEMPORARY TABLE IF NOT EXISTS split (split VARCHAR(50));

SET v_tam = (SELECT (LENGTH(v_value) - LENGTH(REPLACE(v_value,',',''))));
SET v_pos = 1;

WHILE (v_tam >= v_pos)
DO
    INSERT INTO split 
    SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(v_value,',',v_pos),',', -1);
    SET v_pos = v_pos + 1;
END WHILE;

SELECT * FROM split;

DROP TEMPORARY TABLE split;

END$$


CALL ARR('1006212,1006404,1003404,1006505,444,');

Aslında burada ne söylediğiniz net değil. 7 yıl önceki bu sorunun birkaç alakalı cevabı var. Cevabınızı kaldırmayı veya bize anlatmaya çalıştığınız şeyi bir örnek yerine doğrudan / genel olarak açıklamayı düşünün.
einpoklum

0

5.7.x'ten sonraki MYSQL sürümünde, bir diziyi depolamak için JSON türünü kullanabilirsiniz. Bir dizinin değerini bir anahtarla MYSQL aracılığıyla alabilirsiniz.


7
Bunu nasıl yapacağımla ilgili bir örnek verebilir misiniz?
einpoklum

0

ELT (dizin numarası, dize1, dize2, dize3,…) işlevinden esinlenerek, aşağıdaki örneğin bir dizi örneği olarak çalıştığını düşünüyorum:

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

Umarım yardımcı olur.


0

Burada, virgülle ayrılmış bir dizede döngü yapmak için bir MySQL örneği verilmiştir.

DECLARE v_delimited_string_access_index INT;
DECLARE v_delimited_string_access_value VARCHAR(255);
DECLARE v_can_still_find_values_in_delimited_string BOOLEAN;

SET v_can_still_find_values_in_delimited_string = true;
SET v_delimited_string_access_index = 0;
WHILE (v_can_still_find_values_in_delimited_string) DO
  SET v_delimited_string_access_value = get_from_delimiter_split_string(in_array, ',', v_delimited_string_access_index); -- get value from string
  SET v_delimited_string_access_index = v_delimited_string_access_index + 1;
  IF (v_delimited_string_access_value = '') THEN
    SET v_can_still_find_values_in_delimited_string = false; -- no value at this index, stop looping
  ELSE
    -- DO WHAT YOU WANT WITH v_delimited_string_access_value HERE
  END IF;
END WHILE;

bu, get_from_delimiter_split_stringburada tanımlanan işlevi kullanır : https://stackoverflow.com/a/59666211/3068233


virgülle ayrılmış dizeler zaten önerilmişti - yıllar önce.
einpoklum

@einpoklum evet - ve işte onlarla etkileşim kurmanın başka bir yolu
Ulad Kasach

0

Bir dizi değişkeni gerçekten gerekli mi?

Soruyorum çünkü başlangıçta buraya MySQL tablo değişkeni olarak bir dizi eklemek isteyerek geldim. Veritabanı tasarımında nispeten yeniydim ve bunu tipik bir programlama dili tarzında nasıl yapacağımı düşünmeye çalışıyordum.

Ancak veritabanları farklıdır. Ben düşündüm ben bir değişken olarak bir dizi istedik, ama sadece bir ortak MySQL veritabanı uygulama değil çıkıyor.

Standart pratik

Dizilere alternatif çözüm, ek bir tablo eklemek ve ardından orijinal tablonuza bir yabancı anahtarla başvurmaktır.

Örnek olarak, bir evdeki herkesin mağazadan satın almak istediği tüm ürünleri takip eden bir uygulama hayal edelim.

Başlangıçta tasavvur ettiğim tabloyu oluşturma komutları şuna benzerdi:

#doesn't work
CREATE TABLE Person(
  name VARCHAR(50) PRIMARY KEY
  buy_list ARRAY
);

Buy_list'i virgülle ayrılmış bir öğe dizisi veya buna benzer bir şey olarak düşündüğümü düşünüyorum.

Ancak MySQL'in dizi türü alanı yok, bu yüzden gerçekten böyle bir şeye ihtiyacım vardı:

CREATE TABLE Person(
  name VARCHAR(50) PRIMARY KEY
);
CREATE TABLE BuyList(
  person VARCHAR(50),
  item VARCHAR(50),
  PRIMARY KEY (person, item),
  CONSTRAINT fk_person FOREIGN KEY (person) REFERENCES Person(name)
);

Burada fk_person adında bir kısıt tanımlıyoruz. Satın Alma Listesindeki 'kişi' alanının yabancı anahtar olduğunu söylüyor. Başka bir deyişle, başka bir tablodaki birincil anahtardır, özellikle de REFERANSLAR'ın ifade ettiği Kişi tablosundaki 'ad' alanıdır.

Kişi ve öğe kombinasyonunu da birincil anahtar olarak tanımladık, ancak teknik olarak bu gerekli değil.

Son olarak, bir kişinin listesindeki tüm öğeleri almak istiyorsanız, şu sorguyu çalıştırabilirsiniz:

SELECT item FROM BuyList WHERE person='John';

Bu size John'un listesindeki tüm öğeleri verir. Diziye gerek yok!


Kabul ettiğim çözüm , geçici bir tablo kullanmaktır.
einpoklum

Elbette. Daha sonra benim gibi bu sayfaya bir dizi türü yaratmanın bir yolunu arayan herkes için bu yanıtı ekledim - başlangıçta dizilerin neden MySQL'de bir tür olmadığını anlamayanlar. Görünüşe göre tasarım gereği. Genel durum burada temsil edilmedi, bu yüzden diğerlerinin tipik olarak dizilere ihtiyaç olmadığını anlaması için öğrendiklerimi dahil ettim. Cevabımı seçmenizi beklemiyorum. Kullanım durumuna bağlıdır. Belirli bir kullanım durumu için kabul ettiğiniz cevabı aldınız ve genel kullanım senaryosu için bu cevabı veriyorum.
kraftydevil

0

Böyle bir masamız varsa

mysql> select * from user_mail;
+------------+-------+
| email      | user | 
+------------+-------+-
| email1@gmail |     1 | 
| email2@gmail |     2 |
+------------+-------+--------+------------+

ve dizi tablosu:

mysql> select * from user_mail_array;
+------------+-------+-------------+
| email      | user | preferences |
+------------+-------+-------------+
| email1@gmail |     1 |           1 |
| email1@gmail |     1 |           2 |
| email1@gmail |     1 |           3 |
| email1@gmail |     1 |           4 |
| email2@gmail |     2 |           5 |
| email2@gmail |     2 |           6 |

CONCAT fonksiyonu ile ikinci tablonun satırlarını tek bir dizi olarak seçebiliriz:

mysql> SELECT t1.*, GROUP_CONCAT(t2.preferences) AS preferences
     FROM user_mail t1,user_mail_array t2
       where t1.email=t2.email and t1.user=t2.user
     GROUP BY t1.email,t1.user;

+------------+-------+--------+------------+-------------+
| email      | user | preferences |
+------------+-------+--------+------------+-------------+
|email1@gmail |     1 | 1,3,2,4     |
|email2@gmail |     2 | 5,6         |
+------------+-------+--------+------------+-------------+

Clinton'un cevabının kopyası sanırım.
einpoklum

-2

Sanırım bu yanıtı geliştirebilirim. Bunu dene:

'Şakalar' parametresi bir CSV'dir. yani. "1,2,3,4 ..... vb."

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;

Bu yöntem, iyileştirme için daha iyi olacağına inandığım, döngünün her yinelemesinde aranan CSV değerleri dizisini kademeli olarak kısaltır.


Bahsettiğiniz 'bu cevap' nedir? Ayrıca, bir CSV dosyasına sahip olamazsınız.
einpoklum

Bir CSV dosyasına atıfta bulunmuyordum, '1,2,3,4 ... vb.' Gibi bir CSV değerinden bahsediyordum
user2288580

-2

Birden fazla koleksiyon için buna benzer bir şey denerdim. MySQL acemisiyim. İşlev isimleri için üzgünüm, hangi isimlerin en iyi olacağına karar veremedim.

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

Sanırım ne önerdiğinizi anlıyorum, ama bu oldukça hantal ve muhtemelen inanılmaz derecede yavaş ...
einpoklum

Stres testi yapmadan onaylayamam ya da reddedemem. Temelde geçici bir tablo (veya normal tablo) üzerinde birincil anahtar arama ve ekleme işlemidir. Sorunlarla karşılaşana veya daha iyi bir yol bulana kadar kullanacağım; ancak tamamen Oracle PL / SQL'de derleyiciler ve oyunlar yazmak gibi garip şeyler yapıyorum.
Dave

-2

Verileri bir dizi olarak veya tek bir satırda kaydetmek yerine, alınan her değer için farklı satırlar oluşturmalısınız. Bu, hepsini bir araya getirmek yerine anlamayı çok daha kolay hale getirecek.


Lütfen bunu nasıl yapacağınızı paylaşın
Nico Haase

-5

PHP'nin serialize () yöntemini kullanmayı denediniz mi? Bu, bir değişken dizisinin içeriğini PHP'nin anladığı ve veritabanı için güvenli olan bir dizede saklamanıza izin verir (önce ondan kaçtığınızı varsayarak).

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

Numaralı bir dizi olmadan da aynısını yapabilirsiniz.

$array2 = array(
    'something' => 'something else'
);

veya

$array3 = array(
    'somethingNew'
);

7
PHP ile çalışmıyorum, bu yüzden bu benim için pek önemli değil.
einpoklum

1
Seri hale getirmek yerine JSON kullanın. Daha genel ve dilden bağımsızdır.
Rick James
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.