Bazı seçenekler şunlardır:
- Non-alfanümerik ve boşluklar şeritler ve arama sorgusunda sütunda
tracklist
bunu uygulamak bir fonksiyon yazın. Bu kadar büyük bir dezavantajı sorgu tracklist
üzerinde herhangi endeksleri kullanmak mümkün olmayacaktır olduğunu.
Bulanık eşleştirme çeşit kullanın. Bu da büyük olasılıkla endeksleri yararlanmak olmaz. Sizin örnekte satır bulabilirsiniz ama aynı zamanda yanlış pozitif dönebilir Tom Haigh önerisi, var. Ayrıca bulanık eşleme yapmazlar ki, REGEXP
/ RLIKE
a> kullanabilirsiniz, ama yok bir ifade oluşturabilirsiniz:
$tracklist=preg_replace('/[^a-z]+/i', '[^[=a=]]+', $_REQUEST['did']);
$q = mysqli_query($id,"SELECT * FROM `mixes` WHERE `tracklist` REGEXP '$tracklist'");
Örneği $_REQUEST['did']
* 'johnny hey johnnny', çıkan sorgu "SELECT edilir kullanarak tracklist
regexp 'john [^ [a =]] + hey [^ [karışımları DAN = a =]] + johnnny '". Yukarıda alfabetik olmayan karakterler yok sayar. Olmayan-alfanümerik karakterleri göz ardı etmek istiyorsanız, aşağıdakilerden birini (ikinci göz ardı etmez '_') deneyin:
$tracklist=preg_replace('/[^a-z0-9]+/i', '[^[:alnum:]]+', $_REQUEST['did']);
$tracklist=preg_replace('/\W+/', '[^[:alnum:]_]+', $_REQUEST['did']);
Tablolar ve işleme mantığını yeniden. Bu çoğu iş ama kavramsal temiz uygulanmasını üretecek. I tracklist
Bir $ Ayraç (örn. virgül, noktalı virgül, ...) parça adları listesini ayrılmış olduğunu tahmin ediyorum. Bu durumda, mixes
bile first normal form olduğunu. Yeni bir tracklist
tablo oluşturun:
CREATE TABLE `tracklist` (
mix INTEGER REFERENCES mixes (id),
position INTEGER NOT NULL,
track INTEGER REFERENCES tracks (id),
PRIMARY KEY (mix, position),
KEY (mix, track),
KEY (track)
) ENGINE=InnoDB;
Belirli bir parça için karışımı bulmak için, bir birleştirme gerçekleştirmek:
SELECT mixes.* FROM mixes
JOIN tracklist
ON mixes.id = tracklist.mix
WHERE tracklist.track=$trackid
Endeksleri kullanımı sayesinde, yukarıda sorgu diğer iki seçenek daha hızlı olacaktır. Bu yaklaşımın temel dezavantajı, bir karışım için tracklist almak için daha fazla sorguları gerçekleştirmek gerekir olduğunu. Bir ters bir o tracklist düzenleme geliştirebilir. Uygun şekilde tanımlanmış endeksleri ile bu seçeneği hala geçerli DB tasarımı daha hızlı olabilir. Örneğin,
SELECT t2.mix, t2.position, tracks.*
FROM tracklist AS t1
JOIN tracklist AS t2
ON t1.mix = t2.mix
JOIN tracks
ON t2.track = tracks.id
WHERE t1.track=:trackid
çok makul bir varsayım tracklist.tracks
, tracklist.mix
ve tracks.id
endekslerinin, {[(3) yukarıda tanımı verilen, varsa oldukça verimli olacaktır ]} ve track.id
büyük olasılıkla birincil anahtar sütundur. MySQL sadece incelemek gerekiyor (number of mixes containing track :trackid) + (total number of tracks in all mixes that contain :trackid) * 2 rows
. Sırasıyla 8 ve 10 parça ile, "Johnny, Hey (johnnny)" içeren iki karışımları varsa, MySQL 38 satır toplam inceleyeceğiz (tracklist
20 ve 18 tracks
). Seçenek 1 ve 2 (number of mixes)
satırları incelemek gerekir. Sürece karışımları sayısı ortalama karışımı boyutuna ve karışımları pek görünmüyor aradığınız parçaya daha büyük olduğu gibi, bu seçenek, diğer ikisinden daha hızlıdır.
Not Eğer $_REQUEST['did']
sorgu oluşturarak önce, komut açıktır sterilize olmadıkça SQL injection ([2], [3]). Seçeneği 2 Yukarıdaki örnek kullanımları REGEXP
güvenli olduğunu (sanitization preg_replace
bir yan etkisi), ancak en güvenli, en genel yaklaşım {kullanmaktır [(6) }].
$q = mysqli_prepare($id,"SELECT * FROM `mixes` WHERE `tracklist` REGEXP ?");
$q->bind_param('s', $_REQUEST['did']);
$q->execute();
Ayrıca DB böylece hızını artırmak, sorguyu yeniden ayrıştırma gerek olmayacak demektir hazırlanmış sorguları yeniden kullanabilirsiniz.
function findMixFor($track) {
global $id;
static $q = Null;
if (is_null($q)) {
$q = mysqli_prepare($id,"SELECT * FROM `mixes` WHERE `tracklist` REGEXP ?");
}
$q->bind_param('s', $track);
$q->execute();
return $q;
}
findMixFor
sadece bir hazır sorgu yeniden göstermek için olduğunu unutmayın. Uygun bir uygulama bir veri erişim katmanı tüm DB erişimi ayırmak ve aynı zamanda hataları işlemek istiyorum.
Ayrıca PDO yerine mysqli'nin kullanarak içine bakmak isteyebilirsiniz. Bir kere, bu hazırlanan sorguları için destek çok daha zengin olduğunu bulunuyor. Başka için, bu kolay veritabanlarını geçmek için yapar.