ฉันจะสร้างแบบสอบถามแบบกำหนดพารามิเตอร์ PDO ด้วยคำสั่ง LIKE ได้อย่างไร


คำตอบ:


124

คิดออกทันทีหลังจากที่ฉันโพสต์:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->execute(array('value%'));

while ($results = $query->fetch())
{
    echo $results['column'];
}

1
@ แอนดรูว์: ถ้าใช้หลายตัวlikeล่ะ? อาร์เรย์จะดำเนินการอย่างไรตามลำดับ
โลแกน

ขอบคุณ. มีปัญหาคล้ายกันกับ csharp + Mysql + ODBC โดยใช้เหมือนว่าจะไม่ส่งคืนแถวใด ๆ โดยใช้ "เลือก * จากตารางที่คอลัมน์เช่น '%?%';" แต่ถ้าฉันทำเหมือนคุณ "เลือก * จากตารางที่คอลัมน์ชอบ?;" และตั้งค่าสตริงพารามิเตอร์ดังนั้น: string frag = $ "% {searchFragment}%"; จากนั้นใช้ frag สำหรับค่าพารามิเตอร์ แปลก
sdjuan

2
PDO ควรหลีกเลี่ยง% นั้นในการเรียกใช้งาน คำตอบของ Kaqai ดีกว่า
Peter Bagnall

ดูเหมือนว่าน่าสังเกตว่าบันทึกย่อที่ผู้ใช้มีส่วนร่วมอันดับต้น ๆ ในหน้าเอกสาร PDOStatement :: bindParamมีแนวทางที่แตกต่างกัน: เพิ่มเครื่องหมายเปอร์เซ็นต์ให้กับตัวแปรก่อนที่จะเชื่อมโยง
Dan Robinson

ลองดูวิธีแก้ปัญหาของ gavin ซึ่งนำมาจากหน้าสามัญสำนึกของคุณที่ด้านล่างของชุดข้อความนี้ เรียบง่าย ตรรกะ
RationalRabbit

85

สำหรับผู้ที่ใช้พารามิเตอร์ที่มีชื่อนี่คือวิธีใช้LIKEกับ%การจับคู่บางส่วนสำหรับฐานข้อมูล MySQL :

คอลัมน์ WHERE LIKE CONCAT ('%',: hazardstring, '%')

:dangerousstringที่พารามิเตอร์ชื่อเป็น

กล่าวอีกนัยหนึ่งคือใช้%เครื่องหมายที่ไม่ใช้ Escape อย่างชัดเจนในข้อความค้นหาของคุณเองซึ่งแยกออกจากกันและไม่ใช่ข้อมูลที่ผู้ใช้ป้อน

แก้ไข:ไวยากรณ์การเชื่อมต่อสำหรับฐานข้อมูล Oracleใช้ตัวดำเนินการต่อข้อมูล: ||ดังนั้นมันจะกลายเป็น:

โดยที่ column_name LIKE '%' || : สายรัดอันตราย || '%'

อย่างไรก็ตามมีข้อควรระวังตามที่ @bobince กล่าวไว้ที่นี่ว่า:

ความ ยาก เกิดขึ้นเมื่อคุณต้องการอนุญาตให้ใช้ตัวอักษร%หรือ_อักขระในสตริงการค้นหาโดยไม่ต้องทำหน้าที่เป็นตัวแทน

นั่นคือสิ่งอื่นที่ต้องระวังเมื่อรวมการเหมือนและการกำหนดพารามิเตอร์


6
+1 - นี่เป็นแนวทางที่ดีสำหรับฉันเนื่องจากการเชื่อมต่อทั้งหมดเกิดขึ้นในฐานข้อมูลหลังจากที่ตัวยึดตำแหน่งถูกแทนที่แล้วและหมายความว่าสามารถใช้ตัวยึดตำแหน่งที่มีชื่อได้ มันมูลค่าการกล่าวขวัญว่าไวยากรณ์ข้างต้นเป็นสำหรับ Oracle - ใน MySQL LIKE CONCAT('%', :something, '%')ไวยากรณ์คือ อ้างอิง: stackoverflow.com/a/661207/201648
Aaron Newton

1
สิ่งนี้ไม่ได้ผลสำหรับฉันอย่างแน่นอน แต่ทำให้ฉันมาถูกทางแล้ว ฉันต้องทำ LIKE '%': บางอย่าง '%' เพื่อให้มันทำงานได้
Christopher Smit

ฉันรู้ว่านี่ไม่ใช่หัวข้อ แต่ฉันสามารถฉีด peform sql ได้แม้จะใช้ statment นี้ทำไม?
Thiago Dias

สิ่งนี้ไม่ได้ผลสำหรับฉันฉันยังทดสอบด้วยคำสั่ง SQL SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )ซึ่งจะทำให้ฉันมีข้อผิดพลาด
Luzan Baral

@AaronNewton and it means named placeholders can be used. แม้กระทั่งปัญหากับตัวยึดตำแหน่งที่ระบุชื่อเมื่อคุณเชื่อมต่อใน PHP? เห็นได้ชัดว่าการเชื่อมต่อกันใน PHP รองรับทั้งแบบตั้งชื่อและตำแหน่งและแบบพกพามากขึ้นเนื่องจากคุณสามารถใช้แบบสอบถามเดียวกันสำหรับฐานข้อมูลใดก็ได้ ฉันไม่เข้าใจจริงๆว่าทำไมหลาย ๆ คนถึงคิดว่ามีความแตกต่างระหว่างตัวยึดตำแหน่งที่มีชื่อและตำแหน่ง
สามัญสำนึกของคุณ

18
$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->bindValue(1, "%$value%", PDO::PARAM_STR);
$query->execute();

if (!$query->rowCount() == 0) 
{
    while ($results = $query->fetch()) 
    {
        echo $results['column'] . "<br />\n";
    }       
} 
else 
{
    echo 'Nothing found';
}

1
มีข้อได้เปรียบของการใช้สิ่งนี้กับคำตอบที่ยอมรับหรือไม่? ใช้การbindValueป้องกันการโจมตีด้วยการฉีดยาหรือไม่? คำตอบที่ได้รับการยอมรับโดยทั่วไปจะลบล้างคุณค่าของการใช้?ตัวยึดตำแหน่งโดยการต่อสตริงการค้นหาให้%เหมือนกับในสมัยก่อน
felwithe

อะไรคือจุดของการใช้การปฏิเสธก่อน $ query-> rowCount () == 0? สิ่งนี้สมเหตุสมผลจริงหรือ
ssi-anik

15

คุณยังสามารถลองใช้อันนี้ ฉันประสบปัญหาคล้าย ๆ กัน แต่ได้ผลหลังจากการวิจัย

$query = $pdo_connection->prepare('SELECT * FROM table WHERE column LIKE :search');

$stmt= $pdo_connection->prepare($query);

$stmt->execute(array(':search' => '%'.$search_term.'%'));

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

print_r($result);

ฉันแก้ไขโพสต์ของคุณจะนำรหัสลงในการป้องกันรหัส - คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการโพสต์การจัดรูปแบบที่stackoverflow.com/help/formatting ผู้ใช้รายอื่นบางคนเลือกที่จะลดคะแนนคำตอบของคุณโดยไม่แสดงความคิดเห็นดังนั้นฉันจึงไม่แน่ใจเกี่ยวกับสาเหตุของการลดคะแนน
josliber

2
ขอย้ำอีกครั้งฉันไม่ได้โหวตคำถามของคุณ มีใครโหวตให้อีกบ้าง
josliber


2

ฉันได้รับสิ่งนี้จากการหลงผิด php

$search = "%$search%";
$stmt  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stmt->execute([$search]);
$data = $stmt->fetchAll();

และมันได้ผลสำหรับฉันง่ายมาก อย่างที่เขาพูดคุณต้อง "เตรียมตัวอักษรที่สมบูรณ์ของเราก่อน" ก่อนที่จะส่งไปยังแบบสอบถาม


0

PDO หนี "%" (อาจนำไปสู่การฉีด sql) : การใช้รหัสก่อนหน้านี้จะให้ผลลัพธ์ที่ต้องการเมื่อต้องการจับคู่สตริงบางส่วนแต่ถ้าผู้เยี่ยมชมพิมพ์อักขระ "%" คุณจะยังคงได้ผลลัพธ์แม้ว่าคุณจะไม่ได้รับ ไม่มีสิ่งใดที่เก็บไว้ในฐานข้อมูล (อาจนำไปสู่การฉีด sql)

ฉันได้ลองใช้รูปแบบต่างๆมากมายโดย PDO ผลลัพธ์เดียวกันคือการหลีกเลี่ยง "%" นำหน้าผลการค้นหาที่ไม่ต้องการ / ไม่ได้รับการร้องขอ

ฉันคิดว่ามันคุ้มค่าที่จะแบ่งปันหากใครพบคำศัพท์เกี่ยวกับเรื่องนี้โปรดแบ่งปัน


1
นี่มาจากคู่มือ: us3.php.net/manual/en/pdo.prepared-statements.php นี่เป็นอีกโพสต์ที่เกี่ยวกับเรื่องนี้: stackoverflow.com/questions/22030451/… ฉันอยากทราบความคิดเห็นของคุณเกี่ยวกับ การออกครั้งนี้
Ozkar R

1
วิธีแก้ไขที่เป็นไปได้ (ไม่มีการทดสอบ) ใช้CONCATเช่น: $ sql =“ SELECT item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')”; อ้างอิง: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R

3
PDO ไม่หนี% เป็นรหัสของคุณที่ทำผิด สำหรับวิธีแก้ปัญหาคุณควรอ่านคำตอบที่ให้ไว้แล้วที่นี่
สามัญสำนึกของคุณ

ขอบคุณสำหรับคำแนะนำ อย่างไรก็ตามรหัสที่ทดสอบเป็นรหัสจากคู่มือโดยใช้ตัวยึดตำแหน่งเพื่อหลีกเลี่ยงการแทรก SQL ฉันยังคงได้รับผลลัพธ์เดียวกันตัวอย่าง # 6 การใช้ตัวยึดตำแหน่ง PDO อย่างไม่ถูกต้องจะหลบหนี% โดยใช้รหัสด้านบนไม่ใช่รหัสของฉัน ฉันเพิ่งเคยใช้ฟอรัมและอาจไม่เข้าใจว่ากระบวนการแสดงความคิดเห็นโพสต์และชื่อเสียงทำงานอย่างไรที่นี่ฉันจะเก็บไว้ในใจต่อไปเพราะจากความคิดเห็นก่อนหน้านี้คุณต้องมีชื่อเสียงเพื่อช่วยเหลือผู้อื่นหรือแสดงความคิดเห็น ขอบคุณ.
Ozkar R
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.