Bir satır eşleşen metin

5 Cevap php

Ben bu yüzden gibi benim mysql tabloda bir satır var

John - Hey (johnnny)

ancak çünkü nasıl dize i have biçimlendirilmiş

john hey johnnny

Ben bu sorguyu denedim

$q  = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE %".$_REQUEST['did']."%");

ancak bu işe yaramadı? Herhangi bir fikir?

5 Cevap

Tamamen soruyu takip ve ben bir Postgres adam değilim, ama benim en iyi tahminim tırnak parametre sarmak gerek olduğunu etmeyin.

$q  = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE '%{$_REQUEST['did']}%'");

Siz MySQL full text indexes/search bakmak isteyebilirsiniz. Ben doğal dil modu noktalama vs ne olursa olsun, kelime düzenin arama dizesi sonuçlarını bulmak mümkün olması gerektiğini düşünüyorum

Bu sadece MyISAM tablo ile çalıştığını unutmayın.

Bir ' içinde gibi parametre kaydırmak gerekir. Sen şu var:

$q  = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE %".$_REQUEST['did']."%");

Bu olmalıdır:

$q  = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE '% ".$_REQUEST['did']."%'");

Ben ilk ve son % 'ın önüne koymak iki kesme dikkat edin

edit

Eğer girişini john hey johnnny' and your looking for John alıyoruz Yani - Hey (johnnny) `veritabanında sonra sen aradığınız dize işlemek zorunda

$search = str_replace(" ", "%", $_REQUEST['did']); // john%hey%johnnny

$query = "SELECT * FROM mixes WHERE `tracklist` LIKE '".$search."'";
$q  = mysqli_query($id, $query);

% ihtiyacınız olanlar arasında herhangi bir boşluk veya karakter maç olacak. Bu biten maç olmayacak ). Bu yeterince iyi ama eğer satır seçecektir. Sen ) ve ya aradığınız dize önce herhangi bir karakter biten maç için $search değişken önce ve sonra % ekleyebilirsiniz.

Bazı seçenekler şunlardır:

  1. 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.
  2. 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 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']);
    
  3. 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.

Daha geniş bir soru var - neden bu maç için çalışıyoruz ve çözmeye çalıştığınız sorun ne vardır?

Senin sorunun çok derin olduğunu düşünüyorum - Eğer doğru problem çözme değildir. Ne gerçekten yapmaya çalışıyorsun?