Soru Bir dizi mysql içine nasıl saklanır?


Bir diziyi mysql alanına depolamanın bir yolu var mı? Bir yorum derecelendirme sistemi oluşturuyorum, bu yüzden çoklu oylamaları önlemek için kullanıcı kimlikleri dizilerini saklamak istiyorum. Bu yoruma oy veren yorum kimliğini ve kullanıcı kimlikleri dizisini içeren yeni bir tablo oluşturacağım. Bundan sonra, yorum tablosuna ve bu tabloya katılacağım ve mevcut kullanıcı kimliğinin seçmen dizisinde veya notunda bulunup bulunmadığını kontrol edeceğim. Oylama simgelerinden daha fazlaysa devre dışı bırakılır. Bu şekilde mysql sorgusunu döngüde kullanmayı engelleyeceğimi düşünüyorum.

Daha iyi bir yol biliyor musunuz?


44
2017-08-05 09:16


Menşei


Bir kullanıcının birden fazla oy kullanmasını önlemek için kolay bir görev olduğunu biliyorum, ancak belirli bir yorumu zaten oylayan ve mümkün olduğunca az sayıda mysql sorgu olarak kullanan kullanıcılar için devre dışı bırakılmış simgeleri göstermem gerekiyor. Serileştirme işlevini gördüğümde bu sorunla başa çıkacak ... - King Julien
Normalleştirilmiş yaklaşımı kullanacak olmanın zor olacağını düşündüğünüz herhangi bir sebep var mı? - Daniel Vassallo
@Daniel Vassallo Normalleştirilmiş yaklaşımda ne demek istiyorsun? - King Julien
Bu cevaplar @Pekka, @ Björn, @Dennis ve kendimin önerdiği yaklaşımdır. Temel olarak, bir dizinin tek bir veritabanı alanına serileştirilmesine karşı, ilişkilerinizi saklamak için başka bir tablo (bir kesişim tablosu olarak adlandırılır) kullanmanın lehine öneriyoruz. Cevaplarda daha fazla detay var :) - Daniel Vassallo
olası kopyası MySQL dizisinde - outis


Cevaplar:


Diziyi her zaman seri hale getirebilir ve veritabanında saklayabilirsiniz.
PHP Serileştir

Ardından, diziyi gerektiğinde sıralayabilirsiniz.


47
2017-08-05 09:19



Bu ilişkisel modeli bozar. - outis
Bu benim durumum için mükemmeldi. Sadece kullanıcı ayarları için değişken bir dizi depolamaya çalışıyor. Teşekkürler hibe. - CA3LE
Bu, daha sonra bu verilere nasıl erişeceğinize bağlı olarak daha anlamlı olabilir. Dizideki belirli bir öğeye bir kerede değil, yalnızca tüm diziye (istediğim şey) ihtiyacınız yoksa, bu çözüm gayet iyi. - King Julien
Seri hale getirme kötü bir uygulamadır ... DB'ye okuma veya yazmada üçüncü taraflara bağlı olarak, göç için daha az taşınabilir açık hale getirir. Belirtildiği gibi bir DB modelini yener. Bu gerekirse json_encode daha hızlı olduğu için daha iyi bir çözüm olabilir. Ayrıca aramaları ve sorguları çok daha fazla ve daha zor hale getirir. Diziler küçükse, patlar ve patlarsa oldukça iyi çalışır. - Yann Poiré


Bunu aşağıdaki gibi ele almak isteyebilirsiniz:

CREATE TABLE comments (
    comment_id int, 
    body varchar(100), 
    PRIMARY KEY (comment_id)
);

CREATE TABLE users (
    user_id int, 
    username varchar(20), 
    PRIMARY KEY (user_id)
);

CREATE TABLE comments_votes (
    comment_id int, 
    user_id int, 
    vote_type int, 
    PRIMARY KEY (comment_id, user_id)
);

Kompozit birincil anahtar  (comment_id, user_id) üzerinde kesişim tablosu  comments_votes kullanıcıların aynı yorumlarda birden çok kez oy kullanmasını engeller.

Yukarıdaki şemaya bazı veriler ekleyelim:

INSERT INTO comments VALUES (1, 'first comment');
INSERT INTO comments VALUES (2, 'second comment');
INSERT INTO comments VALUES (3, 'third comment');

INSERT INTO users VALUES (1, 'user_a');
INSERT INTO users VALUES (2, 'user_b');
INSERT INTO users VALUES (3, 'user_c');

Şimdi kullanıcı 1 için birkaç oy ekleyelim:

INSERT INTO comments_votes VALUES (1, 1, 1);
INSERT INTO comments_votes VALUES (2, 1, 1);

Yukarıdaki, kullanıcı 1'in, yorum 1 ve 2'de tip 1 oyu verdiğini ifade eder.

Aynı kullanıcı bu yorumlardan birinde tekrar oy kullanmaya çalışırsa, veritabanı reddeder:

INSERT INTO comments_votes VALUES (1, 1, 1);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'

Eğer kullanacaksan InnoDB'nin depolama motoru, kullanmak akıllıca olacaktır yabancı anahtar üzerinde kısıtlamalar comment_id ve user_id kesişim tablosunun alanları. Ancak şunu unutmayın MyISAM, MySQL'deki varsayılan depolama altyapısı, yabancı anahtar kısıtlamalarını zorlamaz:

CREATE TABLE comments (
    comment_id int, 
    body varchar(100), 
    PRIMARY KEY (comment_id)
) ENGINE=INNODB;

CREATE TABLE users (
    user_id int, 
    username varchar(20), 
    PRIMARY KEY (user_id)
) ENGINE=INNODB;

CREATE TABLE comments_votes (
    comment_id int, 
    user_id int, 
    vote_type int, 
    PRIMARY KEY (comment_id, user_id),
    FOREIGN KEY (comment_id) REFERENCES comments (comment_id),
    FOREIGN KEY (user_id) REFERENCES users (user_id)
) ENGINE=INNODB;

Bu yabancı anahtarlar bir satırın garantisini verir. comments_votes asla sahip olmayacak comment_id veya user_id var olmayan değer comments ve users sırasıyla tablolar. Yabancı anahtarların çalışan bir ilişkisel veri tabanına sahip olması gerekmemektedir, ancak kırık ilişkileri ve yetim satırlarını önlemek için kesinlikle gereklidirler (örn. bilgi tutarlılığı).

Aslında, referans bütünlüğü, seri hale getirilmiş dizileri tek bir veritabanı alanına depolarsanız zorlamak için çok zor olan bir şeydir.


57
2017-08-05 09:23



Bu doğrulanmış bir cevap olmalı. - tomsihap


Tablo yapısını bir yoruma ve ayrı bir oylama tablosuna normalleştirmeyi düşünün.

Tablo "yorumlar":

id
comment
user
...

Tablo "oy":

user_id  
comment_id
vote (downvote/upvote)

Bu, bir veritabanı alanının sınırları ile uğraşmak zorunda kalmadan sınırsız sayıda oylamaya izin verir.

Ayrıca, "bir kullanıcının aldığı tüm oyları göster", belirli oyları kaldırma veya günde en fazla oy sayısını sınırlandırma gibi işlemler için gelecekteki ihtiyaçlarınız olabilir. Bu işlemler, normalleştirilmiş bir yapı ile uygulanması kolay ve hızlıdır ve seri hale getirilmiş bir dizide korkunç derecede yavaş ve karmaşıktır.


13
2017-08-05 09:20



OP'nin sorusunun bütün noktası, muhtemelen birden fazla tablo kullanmaktan kaçınmaktır. - user18490


Üç tabloya sahip olmalısınız: Kullanıcılar, yorumlar ve comment_users.

comment_users'ın sadece iki alanı vardır: fk_user_id ve fk_comment_id

Böylece performansınızı maksimumda tutabilirsiniz :)


4
2017-08-05 09:19





Tablo yapınızı daha fazla normalleştirmeyi tercih ederim;

COMMENTS
-------
id (pk)
title
comment
userId


USERS
-----
id (pk)
name
email


COMMENT_VOTE
------------
commentId (pk)
userId (pk)
rating (float)

Artık bakımı daha kolay! Ve MySQL sadece kullanıcı başına bir oyu kabul eder ve yorum yapar.


4
2017-08-05 09:21





bu şekilde tablo oluştur,

CommentId    UserId
---------------------
   1            usr1
   1            usr2

Bu şekilde, kullanıcının yorumları yayınlayıp paylaşmadığını kontrol edebilirsiniz. Bunun dışında tablolar için Comments ve Users ilgili kimlik ile


1
2017-08-05 09:22





Verileri bir dizide saklıyorsanız, bir diziye el ile yerleştirmiş olsaydınız yaptığınız gibi

"INSERT INTO database_name.database_table (`array`)
    VALUES
    ('One,Two,Three,Four')";

Sonra veritabanından çekerken, explode () işlevini kullanın.

$sql = mysql_query("SELECT * FROM database_name.database_table");
$numrows = mysql_num_rows($sql);
if($numrows != 0){
    while($rows = mysql_fetch_assoc($sql)){
        $array_from_db = $rows['array'];
    }
}else{
    echo "No rows found!".mysql_error();
}
$array = explode(",",$array_from_db);
foreach($array as $varchar){
    echo $varchar."<br/>";
}

Öyle olsun!


1
2018-02-19 00:03





İle depolamak json veya tefrika dizi şu an için en iyi çözümdür. Bazı durumlarda ('karakterleri kırparak] json sorun yaşıyor olabilir ama serileştirmek harika bir seçim olmalı.

Not: Seri hale getirilmiş verileri manuel olarak değiştirirseniz, karakter sayımı konusunda dikkatli olmanız gerekir.


0
2017-08-06 00:15